@alfalab/core-components-confirmation 9.0.7 → 10.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 (233) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/component.d.ts +4 -164
  3. package/dist/component.js +113 -101
  4. package/dist/components/countdown-loader/component.d.ts +1 -1
  5. package/dist/components/countdown-loader/component.js +1 -1
  6. package/dist/components/countdown-loader/index.css +2 -2
  7. package/dist/components/index.d.ts +1 -3
  8. package/dist/components/index.js +15 -14
  9. package/dist/components/screens/fatal-error/component.d.ts +3 -0
  10. package/dist/components/screens/fatal-error/component.js +25 -0
  11. package/dist/components/screens/fatal-error/index.css +61 -0
  12. package/dist/components/{code-input → screens/fatal-error}/index.d.ts +0 -0
  13. package/dist/components/screens/fatal-error/index.js +13 -0
  14. package/dist/components/screens/hint/component.d.ts +3 -0
  15. package/dist/components/screens/hint/component.js +45 -0
  16. package/dist/components/screens/hint/index.css +103 -0
  17. package/dist/components/{countdown → screens/hint}/index.d.ts +0 -0
  18. package/dist/components/screens/hint/index.js +15 -0
  19. package/dist/components/screens/index.d.ts +4 -0
  20. package/dist/components/screens/index.js +26 -0
  21. package/dist/components/screens/initial/component.d.ts +3 -0
  22. package/dist/components/screens/initial/component.js +95 -0
  23. package/dist/components/screens/initial/countdown-section.d.ts +0 -0
  24. package/dist/components/screens/initial/countdown-section.js +15 -0
  25. package/dist/components/screens/initial/index.css +98 -0
  26. package/dist/components/{overlimit → screens/initial}/index.d.ts +0 -0
  27. package/dist/components/screens/initial/index.js +19 -0
  28. package/dist/components/screens/temp-block/component.d.ts +3 -0
  29. package/dist/components/screens/temp-block/component.js +36 -0
  30. package/dist/components/{overlimit → screens/temp-block}/index.css +9 -31
  31. package/dist/components/{sign-confirmation → screens/temp-block}/index.d.ts +0 -0
  32. package/dist/components/screens/temp-block/index.js +13 -0
  33. package/dist/context.d.ts +4 -0
  34. package/dist/context.js +27 -0
  35. package/dist/countdown-section-2edac0a0.d.ts +9 -0
  36. package/dist/countdown-section-2edac0a0.js +41 -0
  37. package/dist/cssm/component.d.ts +4 -164
  38. package/dist/cssm/component.js +115 -103
  39. package/dist/cssm/components/countdown-loader/component.d.ts +1 -1
  40. package/dist/cssm/components/index.d.ts +1 -3
  41. package/dist/cssm/components/index.js +19 -18
  42. package/dist/cssm/components/screens/fatal-error/component.d.ts +3 -0
  43. package/dist/cssm/components/screens/fatal-error/component.js +24 -0
  44. package/dist/cssm/components/{code-input → screens/fatal-error}/index.d.ts +0 -0
  45. package/dist/cssm/components/screens/fatal-error/index.js +14 -0
  46. package/dist/cssm/components/screens/fatal-error/index.module.css +60 -0
  47. package/dist/cssm/components/screens/hint/component.d.ts +3 -0
  48. package/dist/cssm/components/screens/hint/component.js +44 -0
  49. package/dist/cssm/components/{countdown → screens/hint}/index.d.ts +0 -0
  50. package/dist/cssm/components/screens/hint/index.js +16 -0
  51. package/dist/cssm/components/screens/hint/index.module.css +102 -0
  52. package/dist/cssm/components/screens/index.d.ts +4 -0
  53. package/dist/cssm/components/screens/index.js +31 -0
  54. package/dist/cssm/components/screens/initial/component.d.ts +3 -0
  55. package/dist/cssm/components/screens/initial/component.js +97 -0
  56. package/dist/cssm/components/screens/initial/countdown-section.d.ts +9 -0
  57. package/dist/cssm/components/screens/initial/countdown-section.js +41 -0
  58. package/dist/cssm/components/{overlimit → screens/initial}/index.d.ts +0 -0
  59. package/dist/cssm/components/screens/initial/index.js +20 -0
  60. package/dist/cssm/components/{sign-confirmation → screens/initial}/index.module.css +40 -50
  61. package/dist/cssm/components/screens/temp-block/component.d.ts +3 -0
  62. package/dist/cssm/components/screens/temp-block/component.js +36 -0
  63. package/dist/cssm/components/{sign-confirmation → screens/temp-block}/index.d.ts +0 -0
  64. package/dist/cssm/components/screens/temp-block/index.js +15 -0
  65. package/dist/cssm/components/{overlimit → screens/temp-block}/index.module.css +6 -28
  66. package/dist/cssm/context.d.ts +4 -0
  67. package/dist/cssm/context.js +27 -0
  68. package/dist/cssm/index.d.ts +3 -0
  69. package/dist/cssm/index.js +29 -20
  70. package/dist/cssm/index.module.css +5 -77
  71. package/dist/cssm/types.d.ts +130 -0
  72. package/dist/cssm/types.js +23 -0
  73. package/dist/cssm/utils.d.ts +30 -0
  74. package/dist/cssm/utils.js +84 -0
  75. package/dist/esm/component.d.ts +4 -164
  76. package/dist/esm/component.js +114 -102
  77. package/dist/esm/components/countdown-loader/component.d.ts +1 -1
  78. package/dist/esm/components/countdown-loader/component.js +1 -1
  79. package/dist/esm/components/countdown-loader/index.css +2 -2
  80. package/dist/esm/components/index.d.ts +1 -3
  81. package/dist/esm/components/index.js +11 -10
  82. package/dist/esm/components/screens/fatal-error/component.d.ts +3 -0
  83. package/dist/esm/components/screens/fatal-error/component.js +17 -0
  84. package/dist/esm/components/screens/fatal-error/index.css +61 -0
  85. package/dist/esm/components/{code-input → screens/fatal-error}/index.d.ts +0 -0
  86. package/dist/esm/components/screens/fatal-error/index.js +5 -0
  87. package/dist/esm/components/screens/hint/component.d.ts +3 -0
  88. package/dist/esm/components/screens/hint/component.js +36 -0
  89. package/dist/esm/components/screens/hint/index.css +103 -0
  90. package/dist/esm/components/{countdown → screens/hint}/index.d.ts +0 -0
  91. package/dist/esm/components/screens/hint/index.js +7 -0
  92. package/dist/esm/components/screens/index.d.ts +4 -0
  93. package/dist/esm/components/screens/index.js +15 -0
  94. package/dist/esm/components/screens/initial/component.d.ts +3 -0
  95. package/dist/esm/components/screens/initial/component.js +86 -0
  96. package/dist/esm/components/screens/initial/countdown-section.d.ts +0 -0
  97. package/dist/esm/components/screens/initial/countdown-section.js +7 -0
  98. package/dist/esm/components/screens/initial/index.css +98 -0
  99. package/dist/esm/components/{overlimit → screens/initial}/index.d.ts +0 -0
  100. package/dist/esm/components/screens/initial/index.js +11 -0
  101. package/dist/esm/components/screens/temp-block/component.d.ts +3 -0
  102. package/dist/esm/components/screens/temp-block/component.js +28 -0
  103. package/dist/{modern/components/overlimit → esm/components/screens/temp-block}/index.css +9 -31
  104. package/dist/esm/components/{sign-confirmation → screens/temp-block}/index.d.ts +0 -0
  105. package/dist/esm/components/screens/temp-block/index.js +5 -0
  106. package/dist/esm/context.d.ts +4 -0
  107. package/dist/esm/context.js +23 -0
  108. package/dist/esm/countdown-section-ddb744a6.d.ts +9 -0
  109. package/dist/esm/countdown-section-ddb744a6.js +33 -0
  110. package/dist/esm/index.css +7 -79
  111. package/dist/esm/index.d.ts +3 -0
  112. package/dist/esm/index.js +13 -11
  113. package/dist/esm/types.d.ts +130 -0
  114. package/dist/esm/types.js +19 -0
  115. package/dist/esm/utils.d.ts +30 -0
  116. package/dist/esm/utils.js +76 -0
  117. package/dist/index.css +7 -79
  118. package/dist/index.d.ts +3 -0
  119. package/dist/index.js +25 -16
  120. package/dist/modern/component.d.ts +4 -164
  121. package/dist/modern/component.js +75 -102
  122. package/dist/modern/components/countdown-loader/component.d.ts +1 -1
  123. package/dist/modern/components/countdown-loader/component.js +1 -1
  124. package/dist/modern/components/countdown-loader/index.css +2 -2
  125. package/dist/modern/components/index.d.ts +1 -3
  126. package/dist/modern/components/index.js +11 -10
  127. package/dist/modern/components/screens/fatal-error/component.d.ts +3 -0
  128. package/dist/modern/components/screens/fatal-error/component.js +17 -0
  129. package/dist/modern/components/screens/fatal-error/index.css +61 -0
  130. package/dist/modern/components/{code-input → screens/fatal-error}/index.d.ts +0 -0
  131. package/dist/modern/components/screens/fatal-error/index.js +5 -0
  132. package/dist/modern/components/screens/hint/component.d.ts +3 -0
  133. package/dist/modern/components/screens/hint/component.js +36 -0
  134. package/dist/modern/components/screens/hint/index.css +103 -0
  135. package/dist/modern/components/{countdown → screens/hint}/index.d.ts +0 -0
  136. package/dist/modern/components/screens/hint/index.js +7 -0
  137. package/dist/modern/components/screens/index.d.ts +4 -0
  138. package/dist/modern/components/screens/index.js +15 -0
  139. package/dist/modern/components/screens/initial/component.d.ts +3 -0
  140. package/dist/modern/components/screens/initial/component.js +86 -0
  141. package/dist/modern/components/screens/initial/countdown-section.d.ts +0 -0
  142. package/dist/modern/components/screens/initial/countdown-section.js +7 -0
  143. package/dist/modern/components/screens/initial/index.css +98 -0
  144. package/dist/modern/components/{overlimit → screens/initial}/index.d.ts +0 -0
  145. package/dist/modern/components/screens/initial/index.js +11 -0
  146. package/dist/modern/components/screens/temp-block/component.d.ts +3 -0
  147. package/dist/modern/components/screens/temp-block/component.js +28 -0
  148. package/dist/{esm/components/overlimit → modern/components/screens/temp-block}/index.css +9 -31
  149. package/dist/modern/components/{sign-confirmation → screens/temp-block}/index.d.ts +0 -0
  150. package/dist/modern/components/screens/temp-block/index.js +5 -0
  151. package/dist/modern/context.d.ts +4 -0
  152. package/dist/modern/context.js +23 -0
  153. package/dist/modern/countdown-section-91f055c8.d.ts +9 -0
  154. package/dist/modern/countdown-section-91f055c8.js +32 -0
  155. package/dist/modern/index.css +7 -79
  156. package/dist/modern/index.d.ts +3 -0
  157. package/dist/modern/index.js +12 -10
  158. package/dist/modern/types.d.ts +130 -0
  159. package/dist/modern/types.js +19 -0
  160. package/dist/modern/utils.d.ts +30 -0
  161. package/dist/modern/utils.js +74 -0
  162. package/dist/types.d.ts +130 -0
  163. package/dist/types.js +23 -0
  164. package/dist/utils.d.ts +30 -0
  165. package/dist/utils.js +84 -0
  166. package/package.json +3 -2
  167. package/dist/components/code-input/component.d.ts +0 -16
  168. package/dist/components/code-input/component.js +0 -160
  169. package/dist/components/code-input/index.css +0 -99
  170. package/dist/components/code-input/index.js +0 -13
  171. package/dist/components/code-input/utils.d.ts +0 -10
  172. package/dist/components/code-input/utils.js +0 -21
  173. package/dist/components/countdown/component.d.ts +0 -23
  174. package/dist/components/countdown/component.js +0 -117
  175. package/dist/components/countdown/index.css +0 -85
  176. package/dist/components/countdown/index.js +0 -16
  177. package/dist/components/overlimit/component.d.ts +0 -12
  178. package/dist/components/overlimit/component.js +0 -73
  179. package/dist/components/overlimit/index.js +0 -17
  180. package/dist/components/sign-confirmation/component.d.ts +0 -37
  181. package/dist/components/sign-confirmation/component.js +0 -62
  182. package/dist/components/sign-confirmation/index.css +0 -108
  183. package/dist/components/sign-confirmation/index.js +0 -20
  184. package/dist/cssm/components/code-input/component.d.ts +0 -16
  185. package/dist/cssm/components/code-input/component.js +0 -159
  186. package/dist/cssm/components/code-input/index.js +0 -14
  187. package/dist/cssm/components/code-input/index.module.css +0 -98
  188. package/dist/cssm/components/code-input/utils.d.ts +0 -10
  189. package/dist/cssm/components/code-input/utils.js +0 -21
  190. package/dist/cssm/components/countdown/component.d.ts +0 -23
  191. package/dist/cssm/components/countdown/component.js +0 -117
  192. package/dist/cssm/components/countdown/index.js +0 -18
  193. package/dist/cssm/components/countdown/index.module.css +0 -84
  194. package/dist/cssm/components/overlimit/component.d.ts +0 -12
  195. package/dist/cssm/components/overlimit/component.js +0 -74
  196. package/dist/cssm/components/overlimit/index.js +0 -20
  197. package/dist/cssm/components/sign-confirmation/component.d.ts +0 -37
  198. package/dist/cssm/components/sign-confirmation/component.js +0 -64
  199. package/dist/cssm/components/sign-confirmation/index.js +0 -24
  200. package/dist/esm/components/code-input/component.d.ts +0 -16
  201. package/dist/esm/components/code-input/component.js +0 -151
  202. package/dist/esm/components/code-input/index.css +0 -99
  203. package/dist/esm/components/code-input/index.js +0 -5
  204. package/dist/esm/components/code-input/utils.d.ts +0 -10
  205. package/dist/esm/components/code-input/utils.js +0 -17
  206. package/dist/esm/components/countdown/component.d.ts +0 -23
  207. package/dist/esm/components/countdown/component.js +0 -107
  208. package/dist/esm/components/countdown/index.css +0 -85
  209. package/dist/esm/components/countdown/index.js +0 -7
  210. package/dist/esm/components/overlimit/component.d.ts +0 -12
  211. package/dist/esm/components/overlimit/component.js +0 -65
  212. package/dist/esm/components/overlimit/index.js +0 -9
  213. package/dist/esm/components/sign-confirmation/component.d.ts +0 -37
  214. package/dist/esm/components/sign-confirmation/component.js +0 -53
  215. package/dist/esm/components/sign-confirmation/index.css +0 -108
  216. package/dist/esm/components/sign-confirmation/index.js +0 -12
  217. package/dist/modern/components/code-input/component.d.ts +0 -16
  218. package/dist/modern/components/code-input/component.js +0 -123
  219. package/dist/modern/components/code-input/index.css +0 -99
  220. package/dist/modern/components/code-input/index.js +0 -5
  221. package/dist/modern/components/code-input/utils.d.ts +0 -10
  222. package/dist/modern/components/code-input/utils.js +0 -16
  223. package/dist/modern/components/countdown/component.d.ts +0 -23
  224. package/dist/modern/components/countdown/component.js +0 -102
  225. package/dist/modern/components/countdown/index.css +0 -85
  226. package/dist/modern/components/countdown/index.js +0 -7
  227. package/dist/modern/components/overlimit/component.d.ts +0 -12
  228. package/dist/modern/components/overlimit/component.js +0 -64
  229. package/dist/modern/components/overlimit/index.js +0 -9
  230. package/dist/modern/components/sign-confirmation/component.d.ts +0 -37
  231. package/dist/modern/components/sign-confirmation/component.js +0 -51
  232. package/dist/modern/components/sign-confirmation/index.css +0 -108
  233. package/dist/modern/components/sign-confirmation/index.js +0 -12
@@ -0,0 +1,74 @@
1
+ import { useRef, useState, useCallback, useEffect } from 'react';
2
+
3
+ /**
4
+ * Форматирование миллисекунд в hh:mm:ss.
5
+ *
6
+ * @param {Number} ms миллисекунды
7
+ * @returns {String} время в формате mm:ss
8
+ */
9
+ function formatMsAsMinutes(ms) {
10
+ const totalSeconds = Math.ceil(ms / 1000);
11
+ const totalMinutes = Math.floor(totalSeconds / 60);
12
+ const totalHours = Math.floor(totalMinutes / 60);
13
+ const seconds = totalSeconds % 60;
14
+ const paddedSeconds = `00${seconds}`.slice(-2);
15
+ if (totalHours > 0) {
16
+ const minutes = totalMinutes % 60;
17
+ const paddedMinutes = `00${minutes}`.slice(-2);
18
+ const paddedHours = `00${totalHours}`.slice(-2);
19
+ return `${paddedHours}:${paddedMinutes}:${paddedSeconds}`;
20
+ }
21
+ const paddedMinutes = `00${totalMinutes}`.slice(-2);
22
+ return `${paddedMinutes}:${paddedSeconds}`;
23
+ }
24
+ /**
25
+ * Возвращает время, которое осталось до истечения таймера в ms
26
+ */
27
+ const useCountdown = (countdownDuration, tick = 1000) => {
28
+ const timerId = useRef(0);
29
+ const start = useRef(0);
30
+ const [timePassed, setTimePassed] = useState(0);
31
+ const stopTimer = useCallback(() => {
32
+ window.clearInterval(timerId.current);
33
+ }, []);
34
+ const updateProgress = useCallback(() => {
35
+ const passed = Date.now() - start.current;
36
+ if (passed >= countdownDuration) {
37
+ stopTimer();
38
+ setTimePassed(countdownDuration);
39
+ }
40
+ else {
41
+ setTimePassed(passed);
42
+ }
43
+ }, [countdownDuration, stopTimer]);
44
+ const startTimer = useCallback(() => {
45
+ stopTimer();
46
+ start.current = Date.now();
47
+ updateProgress();
48
+ timerId.current = window.setInterval(updateProgress, tick);
49
+ }, [stopTimer, updateProgress, tick]);
50
+ const timeLeft = countdownDuration - timePassed;
51
+ useEffect(() => {
52
+ return () => {
53
+ stopTimer();
54
+ };
55
+ }, [stopTimer]);
56
+ return [timeLeft, startTimer, stopTimer];
57
+ };
58
+ const ONE_DAY = 24 * 60 * 60 * 1000;
59
+ const ONE_MINUTE = 60 * 1000;
60
+ const useConfirmation = ({ state, screen, blockSmsRetry } = {}) => {
61
+ const [confirmationState, setConfirmationState] = useState(state ?? 'INITIAL');
62
+ const [confirmationScreen, setConfirmationScreen] = useState(screen ?? 'INITIAL');
63
+ const [confirmationBlockSmsRetry, setConfirmationBlockSmsRetry] = useState(blockSmsRetry ?? false);
64
+ return {
65
+ confirmationState,
66
+ confirmationScreen,
67
+ confirmationBlockSmsRetry,
68
+ setConfirmationState,
69
+ setConfirmationScreen,
70
+ setConfirmationBlockSmsRetry,
71
+ };
72
+ };
73
+
74
+ export { ONE_DAY, ONE_MINUTE, formatMsAsMinutes, useConfirmation, useCountdown };
@@ -0,0 +1,130 @@
1
+ import { ComponentType, ReactNode } from 'react';
2
+ type ConfirmationProps = {
3
+ /**
4
+ * Экран компонента
5
+ */
6
+ screen: ConfirmationScreen | string;
7
+ /**
8
+ * Состояние компонента
9
+ */
10
+ state: ConfirmationState | string;
11
+ /**
12
+ * Позиционирование контента
13
+ */
14
+ alignContent?: 'left' | 'center';
15
+ /**
16
+ * Объект с текстами
17
+ */
18
+ texts?: ConfirmationTexts;
19
+ /**
20
+ * Количество символов, которое можно ввести в поле ввода подписания до того, как произойдет автоотправка
21
+ */
22
+ requiredCharAmount?: number;
23
+ /**
24
+ * Длительность обратного отсчета на кнопке повторного запроса сообщения, в милисекундах
25
+ */
26
+ countdownDuration?: number;
27
+ /**
28
+ * Продолжительность блокировки формы (ms)
29
+ */
30
+ tempBlockDuration?: number;
31
+ /**
32
+ * Номер телефона, на который отправлен код
33
+ */
34
+ phone?: string;
35
+ /**
36
+ * Не осталось попыток ввода кода
37
+ */
38
+ blockSmsRetry?: boolean;
39
+ /**
40
+ * Идентификатор для систем автоматизированного тестирования
41
+ */
42
+ dataTestId?: string;
43
+ /**
44
+ * Сss класс для стилизации общей обёртки
45
+ */
46
+ className?: string;
47
+ /**
48
+ * Функция обновления состояния компонента
49
+ */
50
+ onChangeState: (state: ConfirmationState | string) => void;
51
+ /**
52
+ * Функция обновления состояния компонента
53
+ */
54
+ onChangeScreen: (state: ConfirmationScreen | string) => void;
55
+ /**
56
+ * Обработчик события завершения ввода кода подписания
57
+ */
58
+ onInputFinished: (code: string) => void;
59
+ /**
60
+ * Обработчик события нажатия на кнопку "Запросить код"
61
+ */
62
+ onSmsRetryClick: () => void;
63
+ /**
64
+ * Клик по кнопке "Понятно" на экране фатальной ошибки
65
+ */
66
+ onFatalErrorOkButtonClick?: () => void;
67
+ /**
68
+ * Временная блокировка формы закончилась
69
+ */
70
+ onTempBlockFinished?: () => void;
71
+ /**
72
+ * Возввращает объект, где ключ - название экрана (screen), значение - компонент для экрана
73
+ */
74
+ getScreensMap?: (defaulScreensMap: ScreensMap) => ScreensMap;
75
+ };
76
+ type TConfirmationContext = Required<Pick<ConfirmationProps, 'alignContent' | 'texts' | 'state' | 'screen' | 'requiredCharAmount' | 'onInputFinished' | 'countdownDuration' | 'onChangeState' | 'onSmsRetryClick' | 'onChangeScreen' | 'onFatalErrorOkButtonClick' | 'tempBlockDuration'>> & Pick<ConfirmationProps, 'phone' | 'blockSmsRetry' | 'onTempBlockFinished'> & {
77
+ timeLeft: number;
78
+ };
79
+ type ConfirmationTexts = {
80
+ /**
81
+ * Экран INITIAL
82
+ */
83
+ title?: ReactNode;
84
+ codeError?: string;
85
+ codeChecking?: string;
86
+ codeSending?: string;
87
+ codeSended?: string;
88
+ buttonRetry?: string;
89
+ linkToHint?: string;
90
+ noAttemptsLeft?: string;
91
+ countdown?: string;
92
+ /**
93
+ * Экран HINT
94
+ */
95
+ hintButton?: string;
96
+ /**
97
+ * Экран FATAL_ERROR
98
+ */
99
+ fatalErrorTitle?: ReactNode;
100
+ fatalErrorDescription?: ReactNode;
101
+ fatalErrorButton?: string;
102
+ /**
103
+ * Экран TEMP_BLOCK
104
+ */
105
+ tempBlockTitle?: ReactNode;
106
+ tempBlockDescription?: ReactNode;
107
+ };
108
+ type ConfirmationScreen = 'INITIAL' | 'HINT' | 'FATAL_ERROR' | 'TEMP_BLOCK';
109
+ type ConfirmationState = 'INITIAL' | 'CODE_CHECKING' | 'CODE_SENDING' | 'CODE_ERROR';
110
+ type ScreensMap = {
111
+ [key: string]: ComponentType;
112
+ };
113
+ declare const defaultTexts: {
114
+ title: string;
115
+ codeError: string;
116
+ codeChecking: string;
117
+ codeSending: string;
118
+ buttonRetry: string;
119
+ linkToHint: string;
120
+ hintButton: string;
121
+ noAttemptsLeft: string;
122
+ fatalErrorTitle: string;
123
+ fatalErrorDescription: string;
124
+ fatalErrorButton: string;
125
+ tempBlockTitle: string;
126
+ tempBlockDescription: string;
127
+ codeSended: string;
128
+ countdown: string;
129
+ };
130
+ export { ConfirmationProps, TConfirmationContext, ConfirmationTexts, ConfirmationScreen, ConfirmationState, ScreensMap, defaultTexts };
package/dist/types.js ADDED
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var defaultTexts = {
6
+ title: 'Введите код из\xa0сообщения',
7
+ codeError: 'Код введён неверно',
8
+ codeChecking: '',
9
+ codeSending: '',
10
+ buttonRetry: 'Запросить код повторно',
11
+ linkToHint: 'Не\xa0приходит сообщение?',
12
+ hintButton: 'Вернуться к\xa0вводу кода',
13
+ noAttemptsLeft: 'Не\xa0осталось попыток запроса кода',
14
+ fatalErrorTitle: 'Ввести код больше нельзя',
15
+ fatalErrorDescription: 'Вы\xa0ввели код неверно более 5\xa0раз. В\xa0целях безопасности мы\xa0ограничили дальнейший ввод.',
16
+ fatalErrorButton: 'Понятно',
17
+ tempBlockTitle: 'Превышено количество попыток запроса кода',
18
+ tempBlockDescription: 'Повторное подтверждение кодом будет возможно через 24\xa0часа',
19
+ codeSended: 'Код выслан',
20
+ countdown: 'Запросить повторно можно через',
21
+ };
22
+
23
+ exports.defaultTexts = defaultTexts;
@@ -0,0 +1,30 @@
1
+ /// <reference types="react" />
2
+ import { ConfirmationProps } from "./types";
3
+ /**
4
+ * Форматирование миллисекунд в hh:mm:ss.
5
+ *
6
+ * @param {Number} ms миллисекунды
7
+ * @returns {String} время в формате mm:ss
8
+ */
9
+ declare function formatMsAsMinutes(ms: number): string;
10
+ type UseCountdown = (countdownDuration: number, tick?: number) => [number, () => void, () => void];
11
+ /**
12
+ * Возвращает время, которое осталось до истечения таймера в ms
13
+ */
14
+ declare const useCountdown: UseCountdown;
15
+ declare const ONE_DAY: number;
16
+ declare const ONE_MINUTE: number;
17
+ type UseConfirmationParams = {
18
+ state?: ConfirmationProps['state'];
19
+ screen?: ConfirmationProps['screen'];
20
+ blockSmsRetry?: ConfirmationProps['blockSmsRetry'];
21
+ };
22
+ declare const useConfirmation: ({ state, screen, blockSmsRetry }?: UseConfirmationParams) => {
23
+ confirmationState: string;
24
+ confirmationScreen: string;
25
+ confirmationBlockSmsRetry: boolean;
26
+ setConfirmationState: import("react").Dispatch<import("react").SetStateAction<string>>;
27
+ setConfirmationScreen: import("react").Dispatch<import("react").SetStateAction<string>>;
28
+ setConfirmationBlockSmsRetry: import("react").Dispatch<import("react").SetStateAction<boolean>>;
29
+ };
30
+ export { formatMsAsMinutes, useCountdown, ONE_DAY, ONE_MINUTE, useConfirmation };
package/dist/utils.js ADDED
@@ -0,0 +1,84 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var React = require('react');
6
+
7
+ /**
8
+ * Форматирование миллисекунд в hh:mm:ss.
9
+ *
10
+ * @param {Number} ms миллисекунды
11
+ * @returns {String} время в формате mm:ss
12
+ */
13
+ function formatMsAsMinutes(ms) {
14
+ var totalSeconds = Math.ceil(ms / 1000);
15
+ var totalMinutes = Math.floor(totalSeconds / 60);
16
+ var totalHours = Math.floor(totalMinutes / 60);
17
+ var seconds = totalSeconds % 60;
18
+ var paddedSeconds = ("00" + seconds).slice(-2);
19
+ if (totalHours > 0) {
20
+ var minutes = totalMinutes % 60;
21
+ var paddedMinutes_1 = ("00" + minutes).slice(-2);
22
+ var paddedHours = ("00" + totalHours).slice(-2);
23
+ return paddedHours + ":" + paddedMinutes_1 + ":" + paddedSeconds;
24
+ }
25
+ var paddedMinutes = ("00" + totalMinutes).slice(-2);
26
+ return paddedMinutes + ":" + paddedSeconds;
27
+ }
28
+ /**
29
+ * Возвращает время, которое осталось до истечения таймера в ms
30
+ */
31
+ var useCountdown = function (countdownDuration, tick) {
32
+ if (tick === void 0) { tick = 1000; }
33
+ var timerId = React.useRef(0);
34
+ var start = React.useRef(0);
35
+ var _a = React.useState(0), timePassed = _a[0], setTimePassed = _a[1];
36
+ var stopTimer = React.useCallback(function () {
37
+ window.clearInterval(timerId.current);
38
+ }, []);
39
+ var updateProgress = React.useCallback(function () {
40
+ var passed = Date.now() - start.current;
41
+ if (passed >= countdownDuration) {
42
+ stopTimer();
43
+ setTimePassed(countdownDuration);
44
+ }
45
+ else {
46
+ setTimePassed(passed);
47
+ }
48
+ }, [countdownDuration, stopTimer]);
49
+ var startTimer = React.useCallback(function () {
50
+ stopTimer();
51
+ start.current = Date.now();
52
+ updateProgress();
53
+ timerId.current = window.setInterval(updateProgress, tick);
54
+ }, [stopTimer, updateProgress, tick]);
55
+ var timeLeft = countdownDuration - timePassed;
56
+ React.useEffect(function () {
57
+ return function () {
58
+ stopTimer();
59
+ };
60
+ }, [stopTimer]);
61
+ return [timeLeft, startTimer, stopTimer];
62
+ };
63
+ var ONE_DAY = 24 * 60 * 60 * 1000;
64
+ var ONE_MINUTE = 60 * 1000;
65
+ var useConfirmation = function (_a) {
66
+ var _b = _a === void 0 ? {} : _a, state = _b.state, screen = _b.screen, blockSmsRetry = _b.blockSmsRetry;
67
+ var _c = React.useState(state !== null && state !== void 0 ? state : 'INITIAL'), confirmationState = _c[0], setConfirmationState = _c[1];
68
+ var _d = React.useState(screen !== null && screen !== void 0 ? screen : 'INITIAL'), confirmationScreen = _d[0], setConfirmationScreen = _d[1];
69
+ var _e = React.useState(blockSmsRetry !== null && blockSmsRetry !== void 0 ? blockSmsRetry : false), confirmationBlockSmsRetry = _e[0], setConfirmationBlockSmsRetry = _e[1];
70
+ return {
71
+ confirmationState: confirmationState,
72
+ confirmationScreen: confirmationScreen,
73
+ confirmationBlockSmsRetry: confirmationBlockSmsRetry,
74
+ setConfirmationState: setConfirmationState,
75
+ setConfirmationScreen: setConfirmationScreen,
76
+ setConfirmationBlockSmsRetry: setConfirmationBlockSmsRetry,
77
+ };
78
+ };
79
+
80
+ exports.ONE_DAY = ONE_DAY;
81
+ exports.ONE_MINUTE = ONE_MINUTE;
82
+ exports.formatMsAsMinutes = formatMsAsMinutes;
83
+ exports.useConfirmation = useConfirmation;
84
+ exports.useCountdown = useCountdown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfalab/core-components-confirmation",
3
- "version": "9.0.7",
3
+ "version": "10.0.0",
4
4
  "description": "Sms confirmation component",
5
5
  "keywords": [],
6
6
  "license": "MIT",
@@ -17,6 +17,7 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@alfalab/core-components-button": "^5.1.1",
20
+ "@alfalab/core-components-code-input": "^1.1.0",
20
21
  "@alfalab/core-components-link": "^3.2.1",
21
22
  "@alfalab/core-components-loader": "^2.0.2",
22
23
  "@alfalab/hooks": "^1.4.1",
@@ -27,5 +28,5 @@
27
28
  "peerDependencies": {
28
29
  "react": "^16.9.0 || ^17.0.1"
29
30
  },
30
- "gitHead": "07e0a3991a53623ef78766790ea2c1b06049f31f"
31
+ "gitHead": "fe7b54ff82e4f2933502e522ea7a5319057cb50f"
31
32
  }
@@ -1,16 +0,0 @@
1
- /// <reference types="react" />
2
- import React from 'react';
3
- import { KeyboardEvent } from "react";
4
- import { ContentAlign } from "../../component";
5
- type CodeInputProps = {
6
- processing: boolean;
7
- value: string;
8
- slotsCount: number;
9
- error: boolean;
10
- className?: string;
11
- alignContent: ContentAlign;
12
- handleChange: (code: string) => void;
13
- handleInputKeyDown: (event: KeyboardEvent) => void;
14
- };
15
- declare const CodeInput: React.ForwardRefExoticComponent<CodeInputProps & React.RefAttributes<HTMLInputElement>>;
16
- export { CodeInput };
@@ -1,160 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var React = require('react');
6
- var cn = require('classnames');
7
- var hooks = require('@alfalab/hooks');
8
- var components_codeInput_utils = require('./utils.js');
9
-
10
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11
-
12
- var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
13
- var cn__default = /*#__PURE__*/_interopDefaultLegacy(cn);
14
-
15
- /*! *****************************************************************************
16
- Copyright (c) Microsoft Corporation.
17
-
18
- Permission to use, copy, modify, and/or distribute this software for any
19
- purpose with or without fee is hereby granted.
20
-
21
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
22
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
23
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
24
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
25
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27
- PERFORMANCE OF THIS SOFTWARE.
28
- ***************************************************************************** */
29
- function __spreadArrays() {
30
- for (var s = 0, i = 0, il = arguments.length; i < il; i++)
31
- s += arguments[i].length;
32
- for (var r = Array(s), k = 0, i = 0; i < il; i++)
33
- for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
34
- r[k] = a[j];
35
- return r;
36
- }
37
-
38
- var styles = {"component":"confirmation__component_1s527","input":"confirmation__input_1s527","hasError":"confirmation__hasError_1s527","center":"confirmation__center_1s527","disabled":"confirmation__disabled_1s527","compact":"confirmation__compact_1s527","shake":"confirmation__shake_1s527"};
39
- require('./index.css')
40
-
41
- var Input = function (_a) {
42
- var _b;
43
- var index = _a.index, slotsCount = _a.slotsCount, error = _a.error, processing = _a.processing, value = _a.value, alignContent = _a.alignContent, handleChange = _a.handleChange, handleInputKeyDown = _a.handleInputKeyDown, setRef = _a.setRef, focus = _a.focus;
44
- var splittedValue = value.split('');
45
- var inputRef = React.useRef(null);
46
- var onChange = function (event) {
47
- var targetValue = event.target.value;
48
- if (/^\d$/.test(targetValue)) {
49
- var newValues = __spreadArrays(splittedValue);
50
- newValues[index] = targetValue;
51
- handleChange(newValues.join(''));
52
- }
53
- else if (/^\d{1,}$/.test(targetValue) && index !== slotsCount - 1) {
54
- /*
55
- * если пользователь хочет ввести более 1 цифры в инпут,
56
- * то предполагаем, что это вставка кода (например, из смс)
57
- */
58
- var newValues = components_codeInput_utils.mergeArrays({
59
- sourceArray: splittedValue,
60
- targetArray: targetValue.split(''),
61
- startIndex: index,
62
- resultArrayLength: slotsCount,
63
- });
64
- handleChange(newValues.join(''));
65
- }
66
- };
67
- var onInputKeyDown = function (event) {
68
- var key = event.key;
69
- var newValues = __spreadArrays(splittedValue);
70
- switch (key) {
71
- case 'Backspace':
72
- case 'Delete':
73
- newValues[index] = '';
74
- handleChange(newValues.join('').trim());
75
- if (index !== 0) {
76
- focus(index - 1);
77
- }
78
- break;
79
- case 'ArrowRight':
80
- if (index !== slotsCount - 1) {
81
- focus(index + 1);
82
- }
83
- break;
84
- case 'ArrowLeft':
85
- if (index !== 0) {
86
- focus(index - 1);
87
- }
88
- break;
89
- case 'Home':
90
- focus(0);
91
- break;
92
- case 'End':
93
- focus(slotsCount - 1);
94
- break;
95
- }
96
- handleInputKeyDown(event);
97
- };
98
- var handleRef = function (node) {
99
- inputRef.current = node;
100
- setRef({ node: node, index: index });
101
- };
102
- return (React__default['default'].createElement("input", { className: cn__default['default'](styles.input, styles[alignContent], (_b = {},
103
- _b[styles.hasError] = error,
104
- _b[styles.disabled] = processing,
105
- _b)), disabled: processing, value: splittedValue[index] || '', autoComplete: index === 0 ? 'one-time-code' : '', inputMode: 'numeric', pattern: '[0-9]*', onChange: onChange, onKeyDown: onInputKeyDown, ref: handleRef }));
106
- };
107
- var CodeInput = React.forwardRef(function (_a, ref) {
108
- var _b;
109
- var processing = _a.processing, _c = _a.value, value = _c === void 0 ? '' : _c, slotsCount = _a.slotsCount, error = _a.error, handleInputKeyDown = _a.handleInputKeyDown, handleChange = _a.handleChange, className = _a.className, alignContent = _a.alignContent;
110
- var inputs = React.useRef([]);
111
- React.useImperativeHandle(ref, function () { return inputs.current[0]; });
112
- var prevValue = hooks.usePrevious(value) || '';
113
- var focus = React.useCallback(function (index) {
114
- var input = inputs.current[index];
115
- if (input) {
116
- input.focus();
117
- input.setSelectionRange(1, 1);
118
- }
119
- }, []);
120
- var setRef = React.useCallback(function (_a) {
121
- var node = _a.node, index = _a.index;
122
- inputs.current[index] = node;
123
- }, []);
124
- /**
125
- * Устанавливаем фокус на инпуте:
126
- * 1) если код введен неверно
127
- * 2) по нажатию кнопки 'Запросить код'
128
- */
129
- React.useEffect(function () {
130
- var inputIndex = value.length === slotsCount ? value.length - 1 : value.length;
131
- var needFocus = !processing || error;
132
- if (needFocus && value.length === prevValue.length) {
133
- focus(inputIndex);
134
- }
135
- }, [focus, error, slotsCount, value.length, prevValue.length, processing]);
136
- React.useEffect(function () {
137
- if (value.length > prevValue.length && value.length < slotsCount) {
138
- /**
139
- * Если value.length увеличился - ставим фокус на следующем инпуте
140
- */
141
- var nextInputIndex = value.length;
142
- focus(nextInputIndex);
143
- }
144
- else if (value.length <= prevValue.length && value.length > 0) {
145
- /**
146
- * Если value.length уменьшился - ставим фокус на предыдущем инпуте
147
- */
148
- var nextInputIndex = value.length - 1;
149
- focus(nextInputIndex);
150
- }
151
- }, [value.length, prevValue.length, slotsCount, focus]);
152
- return (React__default['default'].createElement("div", { className: cn__default['default'](styles.component, className, (_b = {},
153
- _b[styles.shake] = Boolean(error),
154
- _b[styles.compact] = slotsCount > 6,
155
- _b)) }, new Array(slotsCount).fill('').map(function (_, index) { return (React__default['default'].createElement(Input, { value: value, index: index, error: error, processing: processing, slotsCount: slotsCount, alignContent: alignContent, handleChange: handleChange, handleInputKeyDown: handleInputKeyDown, setRef: setRef, focus: focus,
156
- // eslint-disable-next-line react/no-array-index-key
157
- key: index })); })));
158
- });
159
-
160
- exports.CodeInput = CodeInput;
@@ -1,99 +0,0 @@
1
- /* hash: 19upi */
2
- :root {
3
- --color-light-bg-negative-muted: #feebea;
4
- --color-light-bg-secondary: #f3f4f5;
5
- --color-light-text-negative: #d91d0b;
6
- --color-light-text-primary: #0b1f35;
7
- --color-light-text-tertiary: #b6bcc3;
8
- }
9
- :root {
10
-
11
- /* Hard */
12
-
13
- /* Up */
14
-
15
- /* Hard up */
16
- }
17
- :root {
18
- --gap-2xs: 4px;
19
- --gap-xs: 8px;
20
- }
21
- :root {
22
- --font-family-system: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica,
23
- sans-serif;
24
- }
25
- :root {
26
- --border-radius-s: 4px;
27
- }
28
- :root {
29
- /* title */
30
-
31
- /* text */
32
-
33
- /* error */
34
- --confirmation-error-color: var(--color-light-text-negative);
35
-
36
- /* input */
37
- --confirmation-input-font-size: 30px;
38
- --confirmation-input-font-weight: 700;
39
- --confirmation-input-font-family: var(--font-family-system);
40
- --confirmation-input-text-color: var(--color-light-text-primary);
41
- --confirmation-input-bg-color: var(--color-light-bg-secondary);
42
- --confirmation-input-error-bg-color: var(--color-light-bg-negative-muted);
43
- }
44
- .confirmation__component_1s527 {
45
- display: flex;
46
- }
47
- .confirmation__input_1s527 {
48
- flex-shrink: 0;
49
- width: 36px;
50
- height: 48px;
51
- margin-right: var(--gap-xs);
52
- padding: 0;
53
- background-color: var(--confirmation-input-bg-color);
54
- border: none;
55
- border-radius: var(--border-radius-s);
56
- box-sizing: border-box;
57
- outline: none;
58
- color: var(--confirmation-input-text-color);
59
- text-align: center;
60
- font-size: var(--confirmation-input-font-size);
61
- font-weight: var(--confirmation-input-font-weight);
62
- font-family: var(--confirmation-input-font-family)
63
- }
64
- .confirmation__input_1s527.confirmation__hasError_1s527 {
65
- color: var(--confirmation-error-color);
66
- caret-color: var(--confirmation-input-text-color);
67
- background-color: var(--confirmation-input-error-bg-color);
68
- }
69
- .confirmation__input_1s527.confirmation__center_1s527 {
70
- margin: 0 var(--gap-2xs);
71
- }
72
- .confirmation__input_1s527.confirmation__disabled_1s527 {
73
- color: var(--color-light-text-tertiary);
74
- opacity: 1;
75
- }
76
- .confirmation__compact_1s527 .confirmation__input_1s527 {
77
- width: 28px;
78
- height: 40px;
79
- }
80
- @keyframes confirmation__shake_1s527 {
81
- 0% {
82
- transform: translateX(0);
83
- }
84
-
85
- 25% {
86
- transform: translateX(-2px);
87
- }
88
-
89
- 75% {
90
- transform: translateX(2px);
91
- }
92
-
93
- 100% {
94
- transform: translateX(0);
95
- }
96
- }
97
- .confirmation__shake_1s527 {
98
- animation: confirmation__shake_1s527 0.15s linear 0s 3;
99
- }
@@ -1,13 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- require('react');
6
- require('classnames');
7
- require('@alfalab/hooks');
8
- var components_codeInput_component = require('./component.js');
9
- require('./utils.js');
10
-
11
-
12
-
13
- exports.CodeInput = components_codeInput_component.CodeInput;
@@ -1,10 +0,0 @@
1
- /**
2
- * Начиная с указанного индекса, заменяет элементы исходного массива
3
- */
4
- declare const mergeArrays: ({ sourceArray, targetArray, startIndex, resultArrayLength, }: {
5
- sourceArray: string[];
6
- targetArray: string[];
7
- startIndex: number;
8
- resultArrayLength: number;
9
- }) => string[];
10
- export { mergeArrays };