@cloud-ru/uikit-product-fields-predefined 2.4.8-preview-5e39e65e.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,95 +0,0 @@
1
- import { useRefState } from '@siberiacancode/reactuse';
2
- import { useCallback, useEffect } from 'react';
3
- import { useValueControl } from '@snack-uikit/utils';
4
- import { ZERO_WIDTH_SPACE } from '../constants';
5
- import { isNumberChar, isStringCodeLength, isZeroWidthSpace } from '../utils';
6
- const buildCodeArray = (str, codeLength) => Array.from({ length: codeLength }, (_, idx) => str[idx] || ZERO_WIDTH_SPACE);
7
- export function useCodeInput(params) {
8
- const { value: valueProp, onChange: onChangeProp, codeLength, moveFocus, onComplete } = params;
9
- const [value = '', onChange] = useValueControl({
10
- value: valueProp,
11
- onChange: onChangeProp,
12
- defaultValue: '',
13
- });
14
- const codeRef = useRefState(buildCodeArray(value, codeLength));
15
- const updateCodeByIndex = useCallback((index, newChar) => {
16
- codeRef.current[index] = newChar;
17
- onChange === null || onChange === void 0 ? void 0 : onChange(codeRef.current.join(''));
18
- }, [codeRef, onChange]);
19
- const updateFullCode = useCallback((newCode) => {
20
- codeRef.current = newCode.split('');
21
- onChange === null || onChange === void 0 ? void 0 : onChange(newCode);
22
- moveFocus(codeLength - 1);
23
- onComplete === null || onComplete === void 0 ? void 0 : onComplete(newCode);
24
- }, [codeLength, codeRef, moveFocus, onChange, onComplete]);
25
- const handleAfterCellUpdate = useCallback((index) => {
26
- const normalizedCode = codeRef.current.join('');
27
- const isLastInput = index === codeLength - 1;
28
- const isAllInputsFilled = isStringCodeLength(normalizedCode, codeLength);
29
- if (!isLastInput) {
30
- moveFocus(index + 1);
31
- }
32
- else if (isAllInputsFilled) {
33
- onComplete === null || onComplete === void 0 ? void 0 : onComplete(normalizedCode);
34
- }
35
- }, [codeLength, codeRef, moveFocus, onComplete]);
36
- const deleteChar = useCallback((index) => {
37
- if (codeRef.current[index] && !isZeroWidthSpace(codeRef.current[index])) {
38
- updateCodeByIndex(index, ZERO_WIDTH_SPACE);
39
- }
40
- else if (index > 0) {
41
- moveFocus(index - 1);
42
- }
43
- }, [codeRef, moveFocus, updateCodeByIndex]);
44
- const onAutoCompleteInput = useCallback((code, index) => {
45
- if (isStringCodeLength(code, codeLength)) {
46
- updateFullCode(code);
47
- return;
48
- }
49
- if (!isNumberChar(code)) {
50
- return;
51
- }
52
- updateCodeByIndex(index, code);
53
- handleAfterCellUpdate(index);
54
- }, [codeLength, handleAfterCellUpdate, updateCodeByIndex, updateFullCode]);
55
- const onKeyDown = useCallback((e, index) => {
56
- switch (e.key) {
57
- case 'ArrowLeft':
58
- moveFocus(index - 1);
59
- break;
60
- case 'ArrowRight':
61
- moveFocus(index + 1);
62
- break;
63
- case 'Backspace':
64
- deleteChar(index);
65
- break;
66
- default:
67
- if (isNumberChar(e.key)) {
68
- e.preventDefault();
69
- updateCodeByIndex(index, e.key);
70
- handleAfterCellUpdate(index);
71
- }
72
- break;
73
- }
74
- }, [deleteChar, handleAfterCellUpdate, moveFocus, updateCodeByIndex]);
75
- const onPaste = useCallback((e) => {
76
- var _a;
77
- const codeInput = (_a = e === null || e === void 0 ? void 0 : e.clipboardData.getData('text')) !== null && _a !== void 0 ? _a : '';
78
- if (!isStringCodeLength(codeInput, codeLength)) {
79
- return;
80
- }
81
- updateFullCode(codeInput);
82
- }, [codeLength, updateFullCode]);
83
- useEffect(() => {
84
- codeRef.current = buildCodeArray(value, codeLength);
85
- }, [codeLength, codeRef, value]);
86
- return {
87
- code: codeRef.current,
88
- cellHandlers: {
89
- onKeyDown,
90
- onPaste,
91
- onChange: onAutoCompleteInput,
92
- },
93
- onChangeCode: onChange,
94
- };
95
- }
@@ -1,8 +0,0 @@
1
- export type UseFieldCodeValidateParams = {
2
- /** Ожидаемая длина кода (цифр) */
3
- codeLength: number;
4
- };
5
- /**
6
- * Возвращает функцию валидации значения кода (пусто / неполный код).
7
- */
8
- export declare function useFieldCodeValidate(params: UseFieldCodeValidateParams): (value?: string | number) => string | undefined;
@@ -1,21 +0,0 @@
1
- import { useCallback } from 'react';
2
- import { useLocale } from '@cloud-ru/uikit-product-locale';
3
- import { isNumberChar } from '../utils';
4
- /**
5
- * Возвращает функцию валидации значения кода (пусто / неполный код).
6
- */
7
- export function useFieldCodeValidate(params) {
8
- const { codeLength } = params;
9
- const { t } = useLocale('FieldsPredefined');
10
- return useCallback((value) => {
11
- const str = value != null ? String(value) : '';
12
- const digits = str.split('').filter(isNumberChar).join('');
13
- if (digits.length === 0) {
14
- return t('FieldCode.required');
15
- }
16
- if (digits.length < codeLength) {
17
- return t('FieldCode.minLength', { count: codeLength });
18
- }
19
- return undefined;
20
- }, [codeLength, t]);
21
- }
@@ -1,13 +0,0 @@
1
- import { type FieldCodeFocusEffect } from '../constants';
2
- type UseFieldHelpersParams = {
3
- onChangeCode: (code: string) => void;
4
- moveFocus: (index: number) => void;
5
- focusEffects: readonly FieldCodeFocusEffect[];
6
- showEmptyChars?: boolean;
7
- code: readonly string[];
8
- codeLength: number;
9
- };
10
- export declare function useFieldHelpers(params: UseFieldHelpersParams): {
11
- resetCode: () => void;
12
- };
13
- export {};
@@ -1,31 +0,0 @@
1
- import { useCallback, useEffect, useMemo } from 'react';
2
- import { getFirstEmptyCellIndex } from '../utils';
3
- export function useFieldHelpers(params) {
4
- const { onChangeCode, moveFocus, focusEffects: focusEffectsProp, showEmptyChars, code, codeLength } = params;
5
- const focusEffectsKey = [...focusEffectsProp].sort().join(',');
6
- const focusEffects = useMemo(() => [...focusEffectsProp],
7
- // eslint-disable-next-line react-hooks/exhaustive-deps
8
- [focusEffectsKey]);
9
- const resetCode = useCallback(() => {
10
- onChangeCode('');
11
- if (focusEffects.includes('firstCellOnReset')) {
12
- moveFocus(0);
13
- }
14
- }, [focusEffects, moveFocus, onChangeCode]);
15
- useEffect(() => {
16
- if (focusEffects.includes('firstCellOnMount')) {
17
- moveFocus(0);
18
- }
19
- }, [focusEffects, moveFocus]);
20
- useEffect(() => {
21
- if (!focusEffects.includes('firstCellWhenShowEmptyChars') || !showEmptyChars) {
22
- return;
23
- }
24
- const emptyIndex = getFirstEmptyCellIndex(code);
25
- if (emptyIndex >= 0) {
26
- moveFocus(emptyIndex);
27
- }
28
- // eslint-disable-next-line react-hooks/exhaustive-deps
29
- }, [showEmptyChars, focusEffects, moveFocus, codeLength]);
30
- return { resetCode };
31
- }
@@ -1,5 +0,0 @@
1
- export declare function useFocusCell(codeLength: number): {
2
- inputsRef: import("react").MutableRefObject<HTMLInputElement[]>;
3
- moveFocus: (newIndex: number) => void;
4
- blurFields: () => void;
5
- };
@@ -1,19 +0,0 @@
1
- import { useCallback, useRef } from 'react';
2
- export function useFocusCell(codeLength) {
3
- const inputsRef = useRef([]);
4
- const focusInput = useCallback((index) => {
5
- var _a;
6
- (_a = inputsRef.current[index]) === null || _a === void 0 ? void 0 : _a.focus();
7
- }, [inputsRef]);
8
- const moveFocus = useCallback((newIndex) => {
9
- if (newIndex >= 0 && newIndex < codeLength) {
10
- focusInput(newIndex);
11
- }
12
- }, [codeLength, focusInput]);
13
- const blurFields = useCallback(() => {
14
- inputsRef.current.forEach(input => {
15
- input === null || input === void 0 ? void 0 : input.blur();
16
- });
17
- }, [inputsRef]);
18
- return { inputsRef, moveFocus, blurFields };
19
- }
@@ -1,2 +0,0 @@
1
- export * from './FieldCode';
2
- export { useFieldCodeValidate, type UseFieldCodeValidateParams } from './hooks/useFieldCodeValidate';
@@ -1,2 +0,0 @@
1
- export * from './FieldCode';
2
- export { useFieldCodeValidate } from './hooks/useFieldCodeValidate';
@@ -1,30 +0,0 @@
1
- .fieldCode{
2
- display:flex;
3
- flex-direction:column;
4
- align-items:center;
5
- gap:8px;
6
- }
7
-
8
- .codeContainer{
9
- display:flex;
10
- justify-content:center;
11
- }
12
- .codeContainer[data-size=s]{
13
- gap:8px;
14
- }
15
- .codeContainer[data-size=m]{
16
- gap:8px;
17
- }
18
- .codeContainer[data-size=l]{
19
- gap:12px;
20
- }
21
-
22
- .cellSpacing[data-size=s]{
23
- margin-right:8px;
24
- }
25
- .cellSpacing[data-size=m]{
26
- margin-right:8px;
27
- }
28
- .cellSpacing[data-size=l]{
29
- margin-right:12px;
30
- }
@@ -1,6 +0,0 @@
1
- import { FieldTextProps } from '@snack-uikit/fields';
2
- export declare const isNumberChar: (char: string) => boolean;
3
- export declare const isStringCodeLength: (input: string, codeLength: number) => boolean;
4
- export declare const isZeroWidthSpace: (value: string) => value is "​";
5
- export declare function getFirstEmptyCellIndex(code: readonly string[]): number;
6
- export declare const getCellValidationState: (value: string, showEmptyChars?: boolean, error?: boolean) => FieldTextProps["validationState"];
@@ -1,13 +0,0 @@
1
- import { ZERO_WIDTH_SPACE } from './constants';
2
- export const isNumberChar = (char) => /^\d$/.test(char);
3
- export const isStringCodeLength = (input, codeLength) => new RegExp(`^\\d{${codeLength}}$`).test(input);
4
- export const isZeroWidthSpace = (value) => value === ZERO_WIDTH_SPACE;
5
- export function getFirstEmptyCellIndex(code) {
6
- return code.findIndex(isZeroWidthSpace);
7
- }
8
- export const getCellValidationState = (value, showEmptyChars, error) => {
9
- if (showEmptyChars) {
10
- return isZeroWidthSpace(value) ? 'error' : 'default';
11
- }
12
- return error ? 'error' : 'default';
13
- };
@@ -1,201 +0,0 @@
1
- import cn from 'classnames';
2
- import { forwardRef, KeyboardEventHandler, useEffect, useMemo, useRef, useState } from 'react';
3
-
4
- import { EyeClosedSVG, EyeSVG, PasswordLockSVG } from '@cloud-ru/uikit-product-icons';
5
- import { useLocale } from '@cloud-ru/uikit-product-locale';
6
- import {
7
- AdaptiveFieldTextArea,
8
- FieldTextAreaProps,
9
- getAdaptiveFieldProps,
10
- } from '@cloud-ru/uikit-product-mobile-fields';
11
- import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
12
- import { ButtonFunction, ButtonOutline } from '@snack-uikit/button';
13
- import { themeVars } from '@snack-uikit/figma-tokens';
14
- import { Tooltip } from '@snack-uikit/tooltip';
15
- import { Typography } from '@snack-uikit/typography';
16
-
17
- import { FieldSubmitButton } from '../../helperComponents/FieldSubmitButton';
18
- import { TextAreaActionsFooter } from '../../helperComponents/TextAreaActionsFooter';
19
- import { isTouchDevice as isTouchDeviceHelper } from '../../helpers';
20
- import { AIDisclaimer } from '../AIDisclaimer/AIDisclaimer';
21
- import { AlertButton } from './components/AlertButton';
22
- import { MobileFieldAi } from './components/MobileFieldAi';
23
- import { WithPasswordValidation } from './components/WithPasswordValidation';
24
- import styles from './styles.module.scss';
25
- import { getValidationPassword, ValidationPasswordKey } from './utils';
26
-
27
- export type FieldAiProps = WithLayoutType<
28
- Omit<FieldTextAreaProps, 'placeholder' | 'labelTooltip' | 'label' | 'required' | 'size' | 'spellCheck' | 'footer'> & {
29
- /** Режим ввода sensitive данных (пароля, API ключей, токенов, etc) */
30
- secure?: boolean | 'password';
31
- /** Колбек действия при отправке */
32
- onSubmit(value: string): void;
33
- /** Действие при клике по кнопке сброса контекста */
34
- onResetContextClick?(): void;
35
- /** Действие для отмены секьюрности поля */
36
- onCancelSecure?(): void;
37
- }
38
- >;
39
-
40
- export const FieldAi = forwardRef<HTMLTextAreaElement, FieldAiProps>(
41
- (
42
- {
43
- secure = false,
44
- onSubmit: handleSubmitProp,
45
- value,
46
- onResetContextClick,
47
- onCancelSecure,
48
- disabled,
49
- className,
50
- ...props
51
- },
52
- ref,
53
- ) => {
54
- const { layoutType, validationState } = props;
55
- const { t } = useLocale('FieldsPredefined');
56
- const isTouchDevice = isTouchDeviceHelper(layoutType);
57
-
58
- const [isValueHidden, setIsValueHidden] = useState<boolean>(true);
59
- const [animatedValidationKey, setAnimatedValidationKey] = useState<ValidationPasswordKey | null>(null);
60
- const timerRef = useRef<NodeJS.Timeout | null>(null);
61
-
62
- const isValueValid = typeof value === 'string' && value.trim().length > 0;
63
- const isPasswordMode = secure === 'password';
64
-
65
- const passwordValidation = useMemo(() => getValidationPassword(value), [value]);
66
- const isPasswordValid = isPasswordMode ? Object.values(passwordValidation).every(Boolean) : true;
67
- const showPasswordError = !isPasswordValid && secure && value;
68
- const showPasswordAlert = Boolean(onCancelSecure) && secure === 'password';
69
-
70
- useEffect(
71
- () => () => {
72
- if (timerRef.current) {
73
- clearTimeout(timerRef.current);
74
- }
75
- },
76
- [],
77
- );
78
-
79
- const handleSubmit = () => {
80
- if (isValueValid && isPasswordValid) {
81
- handleSubmitProp(value);
82
- }
83
- };
84
-
85
- const triggerValidationHighlight = (key: ValidationPasswordKey) => {
86
- setAnimatedValidationKey(key);
87
-
88
- timerRef.current = setTimeout(() => {
89
- setAnimatedValidationKey(null);
90
- }, 1000);
91
- };
92
-
93
- const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = event => {
94
- if (isTouchDevice) {
95
- return;
96
- }
97
-
98
- if (isPasswordMode && event.key.length === 1) {
99
- const isLetter = /\p{L}/u.test(event.key);
100
- const isLatinLetter = /^[a-zA-Z]$/.test(event.key);
101
-
102
- if (isLetter && !isLatinLetter) {
103
- event.preventDefault();
104
- triggerValidationHighlight('onlyLatin');
105
- return;
106
- }
107
- }
108
-
109
- if (event.key === 'Enter' && !event.shiftKey) {
110
- event.preventDefault();
111
-
112
- if (!disabled) {
113
- handleSubmit();
114
- }
115
-
116
- return;
117
- }
118
- };
119
-
120
- if (isTouchDevice && !secure) {
121
- return (
122
- <MobileFieldAi
123
- {...props}
124
- {...getAdaptiveFieldProps(props)}
125
- onSubmit={handleSubmit}
126
- submitEnabled={isValueValid && !disabled}
127
- ref={ref}
128
- value={value}
129
- />
130
- );
131
- }
132
-
133
- return (
134
- <div className={cn(styles.wrapper, isPasswordMode && styles.passwordWrapper, className)}>
135
- {showPasswordAlert && (
136
- <div className={styles.alert}>
137
- <PasswordLockSVG size={16} color={themeVars.sys.neutral.textSupport} />
138
- <Typography.SansBodyS className={styles.alertText}>{t('FieldAi.secret.alert.text')}</Typography.SansBodyS>
139
- <AlertButton label={t('FieldAi.secret.alert.button')} onClick={onCancelSecure} />
140
- </div>
141
- )}
142
- <WithPasswordValidation
143
- showValidation={isPasswordMode}
144
- passwordValidation={passwordValidation}
145
- layoutType={layoutType}
146
- animatedKey={animatedValidationKey}
147
- >
148
- <AdaptiveFieldTextArea
149
- {...props}
150
- ref={ref}
151
- value={value}
152
- size='m'
153
- minRows={secure ? 1 : 2}
154
- maxRows={secure ? 1 : 4}
155
- placeholder={secure ? t('FieldAi.secret.placeholder') : t('FieldAi.regular.placeholder')}
156
- className={cn(styles.textarea, secure && isValueHidden ? styles.secured : undefined)}
157
- onKeyDown={handleKeyDown}
158
- spellCheck={!secure}
159
- validationState={showPasswordError ? 'error' : validationState}
160
- footer={
161
- <TextAreaActionsFooter
162
- left={
163
- secure && (
164
- <ButtonFunction
165
- size='xs'
166
- icon={isValueHidden ? <EyeSVG /> : <EyeClosedSVG />}
167
- onClick={() => setIsValueHidden(prev => !prev)}
168
- />
169
- )
170
- }
171
- right={
172
- <>
173
- {secure && onResetContextClick && (
174
- <Tooltip tip={t('FieldAi.resetContext.tooltip')} hoverDelayOpen={600}>
175
- <ButtonOutline
176
- size='xs'
177
- label={t('FieldAi.resetContext.label')}
178
- onClick={onResetContextClick}
179
- appearance='destructive'
180
- />
181
- </Tooltip>
182
- )}
183
- <FieldSubmitButton
184
- showTooltip={!isTouchDevice}
185
- className={cn(styles.submitButton, isTouchDevice ? styles.mobileSubmitButton : undefined)}
186
- active={isValueValid && !disabled && isPasswordValid}
187
- handleClick={handleSubmit}
188
- size={isTouchDevice ? 's' : 'xs'}
189
- />
190
- </>
191
- }
192
- />
193
- }
194
- />
195
- </WithPasswordValidation>
196
-
197
- {!isPasswordMode && <AIDisclaimer layoutType={layoutType} />}
198
- </div>
199
- );
200
- },
201
- );
@@ -1,16 +0,0 @@
1
- import { Typography } from '@snack-uikit/typography';
2
-
3
- import styles from './styles.module.scss';
4
-
5
- export type AlertButtonProps = {
6
- label: string;
7
- onClick?(): void;
8
- };
9
-
10
- export function AlertButton({ label, onClick }: AlertButtonProps) {
11
- return (
12
- <button onClick={onClick} className={styles.button}>
13
- <Typography.SansLabelM className={styles.label}>{label}</Typography.SansLabelM>
14
- </button>
15
- );
16
- }
@@ -1 +0,0 @@
1
- export * from './AlertButton';
@@ -1,20 +0,0 @@
1
- @use '@cloud-ru/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as stv;
2
-
3
- .button {
4
- outline: none;
5
- border: none;
6
- background-color: transparent;
7
- cursor: pointer;
8
- height: 16px;
9
- display: flex;
10
- align-items: center;
11
- justify-content: center;
12
- }
13
-
14
- .label {
15
- color: stv.$sys-blue-text-support;
16
-
17
- &:hover {
18
- color: stv.$sys-neutral-text-main;
19
- }
20
- }
@@ -1,45 +0,0 @@
1
- import { useEffect, useState } from 'react';
2
-
3
- import { CheckSVG } from '@cloud-ru/uikit-product-icons';
4
- import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
5
- import { Typography } from '@snack-uikit/typography';
6
-
7
- import styles from './styles.module.scss';
8
-
9
- type CheckItemProps = WithLayoutType<{
10
- label: string;
11
- checked: boolean;
12
- shouldHide?: boolean;
13
- animated?: boolean;
14
- }>;
15
-
16
- const CHECKED_ITEM_DISAPPEAR_TIMEOUT = 500;
17
-
18
- export function CheckItem({ label, checked, layoutType, shouldHide = false, animated = false }: CheckItemProps) {
19
- const [visible, setVisible] = useState(checked);
20
-
21
- useEffect(() => {
22
- if (checked) {
23
- const timeoutId = setTimeout(() => {
24
- setVisible(false);
25
- }, CHECKED_ITEM_DISAPPEAR_TIMEOUT);
26
-
27
- return () => clearTimeout(timeoutId);
28
- }
29
-
30
- setVisible(true);
31
- }, [checked]);
32
-
33
- if (shouldHide && !visible) {
34
- return null;
35
- }
36
-
37
- return (
38
- <div className={styles.checkItem} data-layout-type={layoutType} data-animated={animated}>
39
- <CheckSVG size={16} className={styles.icon} data-checked={checked} />
40
- <Typography.SansBodyM className={styles.label} data-checked={checked}>
41
- {label}
42
- </Typography.SansBodyM>
43
- </div>
44
- );
45
- }
@@ -1 +0,0 @@
1
- export * from './CheckItem';
@@ -1,44 +0,0 @@
1
- @use '@cloud-ru/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as ste;
2
-
3
- @keyframes shake {
4
- 0%, 100% {
5
- transform: translateX(0);
6
- }
7
- 10%, 30%, 50%, 70%, 90% {
8
- transform: translateX(-4px);
9
- }
10
- 20%, 40%, 60%, 80% {
11
- transform: translateX(4px);
12
- }
13
- }
14
-
15
- .checkItem {
16
- display: inline-flex;
17
- gap: 10px;
18
-
19
- &[data-layout-type='mobile'],
20
- &[data-layout-type='tablet'] {
21
- gap: 8px;
22
- }
23
-
24
- &[data-animated='true'] {
25
- animation: shake 0.5s ease-in-out;
26
- }
27
- }
28
-
29
- .icon {
30
- flex-shrink: 0;
31
- color: ste.$sys-neutral-accent-default;
32
-
33
- &[data-checked='true'] {
34
- color: ste.$sys-primary-text-light;
35
- }
36
- }
37
-
38
- .label {
39
- color: ste.$sys-neutral-text-light;
40
-
41
- &[data-checked='true'] {
42
- color: ste.$sys-primary-text-light;
43
- }
44
- }
@@ -1,57 +0,0 @@
1
- import { forwardRef } from 'react';
2
-
3
- import { useLocale } from '@cloud-ru/uikit-product-locale';
4
- import { FieldTextAreaProps } from '@cloud-ru/uikit-product-mobile-fields';
5
- import { Scroll } from '@snack-uikit/scroll';
6
-
7
- import { FieldSubmitButton } from '../../../../helperComponents/FieldSubmitButton';
8
- import { TextArea } from '../TextArea';
9
- import styles from './styles.module.scss';
10
-
11
- type MobileFieldAiProps = Omit<
12
- FieldTextAreaProps,
13
- 'placeholder' | 'labelTooltip' | 'label' | 'required' | 'size' | 'spellCheck' | 'footer'
14
- > & {
15
- onSubmit(): void;
16
- submitEnabled: boolean;
17
- };
18
-
19
- const MIN_ROWS = 1;
20
- const MAX_ROWS = 6;
21
-
22
- export const MobileFieldAi = forwardRef<HTMLTextAreaElement, MobileFieldAiProps>(
23
- ({ onSubmit, value, submitEnabled, ...props }, ref) => {
24
- const { t } = useLocale('FieldsPredefined');
25
-
26
- return (
27
- <div
28
- className={styles.mobileInputWrapper}
29
- style={{ '--max-rows': MAX_ROWS, '--min-rows': MIN_ROWS }}
30
- data-size='m'
31
- >
32
- <Scroll className={styles.scrollContainer} size='s' barHideStrategy='never'>
33
- <TextArea
34
- {...props}
35
- className={styles.textarea}
36
- ref={ref}
37
- value={value}
38
- minRows={MIN_ROWS}
39
- placeholder={t('FieldAi.regular.placeholder')}
40
- spellCheck={true}
41
- />
42
- </Scroll>
43
-
44
- <div className={styles.mobileSubmitButtonWrapper}>
45
- <FieldSubmitButton
46
- showTooltip={false}
47
- className={styles.mobileSubmitButton}
48
- fullWidth={true}
49
- active={submitEnabled}
50
- handleClick={onSubmit}
51
- size='s'
52
- />
53
- </div>
54
- </div>
55
- );
56
- },
57
- );
@@ -1 +0,0 @@
1
- export * from './MobileFieldAi';