@alfalab/core-components-confirmation 12.5.2 → 13.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 (181) hide show
  1. package/component.desktop.d.ts +1 -1
  2. package/component.desktop.js +5 -3
  3. package/component.mobile.js +6 -4
  4. package/component.responsive.d.ts +2 -3
  5. package/component.responsive.js +9 -9
  6. package/components/base-confirmation/component.js +9 -6
  7. package/components/base-confirmation/index.css +2 -2
  8. package/components/base-confirmation/index.js +5 -3
  9. package/components/countdown-loader/component.js +1 -1
  10. package/components/countdown-loader/index.css +2 -2
  11. package/components/header/component.js +1 -1
  12. package/components/header/index.css +4 -4
  13. package/components/index.js +5 -3
  14. package/components/screens/fatal-error/component.js +3 -3
  15. package/components/screens/fatal-error/index.css +6 -6
  16. package/components/screens/hint/component.js +3 -3
  17. package/components/screens/hint/index.css +12 -12
  18. package/components/screens/index.js +5 -3
  19. package/components/screens/initial/component.js +12 -9
  20. package/components/screens/initial/countdown-section.js +1 -1
  21. package/components/screens/initial/index.css +17 -20
  22. package/components/screens/initial/index.js +5 -3
  23. package/components/screens/temp-block/component.js +1 -1
  24. package/components/screens/temp-block/index.css +7 -7
  25. package/context.js +1 -0
  26. package/{countdown-section-41f47745.js → countdown-section-fb6524aa.js} +3 -3
  27. package/cssm/component.desktop.d.ts +1 -1
  28. package/cssm/component.desktop.js +4 -2
  29. package/cssm/component.mobile.js +4 -2
  30. package/cssm/component.responsive.d.ts +2 -3
  31. package/cssm/component.responsive.js +8 -8
  32. package/cssm/components/base-confirmation/component.js +7 -4
  33. package/cssm/components/base-confirmation/index.js +4 -2
  34. package/cssm/components/index.js +4 -2
  35. package/cssm/components/screens/fatal-error/component.js +2 -2
  36. package/cssm/components/screens/hint/component.js +2 -2
  37. package/cssm/components/screens/index.js +4 -2
  38. package/cssm/components/screens/initial/component.js +11 -8
  39. package/cssm/components/screens/initial/countdown-section.js +2 -2
  40. package/cssm/components/screens/initial/index.js +4 -2
  41. package/cssm/components/screens/initial/index.module.css +0 -3
  42. package/cssm/context.js +1 -0
  43. package/cssm/desktop.d.ts +1 -1
  44. package/cssm/desktop.js +7 -3
  45. package/cssm/index.d.ts +2 -6
  46. package/cssm/index.js +18 -26
  47. package/cssm/mobile.d.ts +1 -1
  48. package/cssm/mobile.js +7 -3
  49. package/cssm/shared.d.ts +4 -0
  50. package/cssm/shared.js +43 -0
  51. package/cssm/types.d.ts +11 -0
  52. package/desktop.d.ts +1 -1
  53. package/desktop.js +8 -4
  54. package/esm/component.desktop.d.ts +1 -1
  55. package/esm/component.desktop.js +5 -3
  56. package/esm/component.mobile.js +6 -4
  57. package/esm/component.responsive.d.ts +2 -3
  58. package/esm/component.responsive.js +9 -9
  59. package/esm/components/base-confirmation/component.js +9 -6
  60. package/esm/components/base-confirmation/index.css +2 -2
  61. package/esm/components/base-confirmation/index.js +5 -3
  62. package/esm/components/countdown-loader/component.js +1 -1
  63. package/esm/components/countdown-loader/index.css +2 -2
  64. package/esm/components/header/component.js +1 -1
  65. package/esm/components/header/index.css +4 -4
  66. package/esm/components/index.js +5 -3
  67. package/esm/components/screens/fatal-error/component.js +3 -3
  68. package/esm/components/screens/fatal-error/index.css +6 -6
  69. package/esm/components/screens/hint/component.js +3 -3
  70. package/esm/components/screens/hint/index.css +12 -12
  71. package/esm/components/screens/index.js +5 -3
  72. package/esm/components/screens/initial/component.js +8 -5
  73. package/esm/components/screens/initial/countdown-section.js +1 -1
  74. package/esm/components/screens/initial/index.css +17 -20
  75. package/esm/components/screens/initial/index.js +5 -3
  76. package/esm/components/screens/temp-block/component.js +1 -1
  77. package/esm/components/screens/temp-block/index.css +7 -7
  78. package/esm/context.js +1 -0
  79. package/esm/{countdown-section-83bf5f20.js → countdown-section-c65cff2d.js} +3 -3
  80. package/esm/desktop.d.ts +1 -1
  81. package/esm/desktop.js +6 -4
  82. package/esm/index.d.ts +2 -6
  83. package/esm/index.js +17 -14
  84. package/esm/mobile.css +2 -2
  85. package/esm/mobile.d.ts +1 -1
  86. package/esm/mobile.js +6 -4
  87. package/esm/shared.d.ts +4 -0
  88. package/esm/shared.js +20 -0
  89. package/esm/types.d.ts +11 -0
  90. package/index.d.ts +2 -6
  91. package/index.js +16 -24
  92. package/mobile.css +2 -2
  93. package/mobile.d.ts +1 -1
  94. package/mobile.js +8 -4
  95. package/modern/component.desktop.d.ts +1 -1
  96. package/modern/component.desktop.js +5 -3
  97. package/modern/component.mobile.js +6 -4
  98. package/modern/component.responsive.d.ts +2 -3
  99. package/modern/component.responsive.js +9 -9
  100. package/modern/components/base-confirmation/component.js +8 -5
  101. package/modern/components/base-confirmation/index.css +2 -2
  102. package/modern/components/base-confirmation/index.js +5 -3
  103. package/modern/components/countdown-loader/component.js +1 -1
  104. package/modern/components/countdown-loader/index.css +2 -2
  105. package/modern/components/header/component.js +1 -1
  106. package/modern/components/header/index.css +4 -4
  107. package/modern/components/index.js +5 -3
  108. package/modern/components/screens/fatal-error/component.js +3 -3
  109. package/modern/components/screens/fatal-error/index.css +6 -6
  110. package/modern/components/screens/hint/component.js +3 -3
  111. package/modern/components/screens/hint/index.css +12 -12
  112. package/modern/components/screens/index.js +5 -3
  113. package/modern/components/screens/initial/component.js +8 -5
  114. package/modern/components/screens/initial/countdown-section.js +1 -1
  115. package/modern/components/screens/initial/index.css +17 -20
  116. package/modern/components/screens/initial/index.js +5 -3
  117. package/modern/components/screens/temp-block/component.js +1 -1
  118. package/modern/components/screens/temp-block/index.css +7 -7
  119. package/modern/context.js +1 -0
  120. package/modern/{countdown-section-a28d693c.js → countdown-section-dd4e5fe3.js} +3 -3
  121. package/modern/desktop.d.ts +1 -1
  122. package/modern/desktop.js +6 -4
  123. package/modern/index.d.ts +2 -6
  124. package/modern/index.js +17 -14
  125. package/modern/mobile.css +2 -2
  126. package/modern/mobile.d.ts +1 -1
  127. package/modern/mobile.js +6 -4
  128. package/modern/shared.d.ts +4 -0
  129. package/modern/shared.js +20 -0
  130. package/modern/types.d.ts +11 -0
  131. package/package.json +31 -6
  132. package/shared.d.ts +4 -0
  133. package/shared.js +37 -0
  134. package/src/component.desktop.tsx +10 -0
  135. package/src/component.mobile.tsx +13 -0
  136. package/src/component.responsive.tsx +31 -0
  137. package/src/components/base-confirmation/component.tsx +123 -0
  138. package/src/components/base-confirmation/index.module.css +8 -0
  139. package/src/components/base-confirmation/index.ts +1 -0
  140. package/src/components/countdown-loader/component.tsx +37 -0
  141. package/src/components/countdown-loader/index.module.css +7 -0
  142. package/src/components/countdown-loader/index.ts +1 -0
  143. package/src/components/header/component.tsx +28 -0
  144. package/src/components/header/index.module.css +21 -0
  145. package/src/components/header/index.ts +1 -0
  146. package/src/components/index.ts +2 -0
  147. package/src/components/screens/fatal-error/component.tsx +46 -0
  148. package/src/components/screens/fatal-error/index.module.css +23 -0
  149. package/src/components/screens/fatal-error/index.ts +1 -0
  150. package/src/components/screens/hint/component.tsx +94 -0
  151. package/src/components/screens/hint/index.module.css +51 -0
  152. package/src/components/screens/hint/index.ts +1 -0
  153. package/src/components/screens/index.ts +4 -0
  154. package/src/components/screens/initial/component.tsx +190 -0
  155. package/src/components/screens/initial/countdown-section.tsx +79 -0
  156. package/src/components/screens/initial/index.module.css +71 -0
  157. package/src/components/screens/initial/index.ts +1 -0
  158. package/src/components/screens/temp-block/component.tsx +58 -0
  159. package/src/components/screens/temp-block/index.module.css +28 -0
  160. package/src/components/screens/temp-block/index.ts +1 -0
  161. package/src/context.ts +26 -0
  162. package/src/desktop.ts +3 -0
  163. package/src/index.ts +6 -0
  164. package/src/mobile.module.css +3 -0
  165. package/src/mobile.ts +3 -0
  166. package/src/shared.ts +4 -0
  167. package/src/types.ts +219 -0
  168. package/src/utils.ts +107 -0
  169. package/src/vars.css +33 -0
  170. package/types.d.ts +11 -0
  171. package/cssm/responsive.d.ts +0 -2
  172. package/cssm/responsive.js +0 -39
  173. package/esm/responsive.d.ts +0 -2
  174. package/esm/responsive.js +0 -23
  175. package/modern/responsive.d.ts +0 -2
  176. package/modern/responsive.js +0 -22
  177. package/responsive.d.ts +0 -2
  178. package/responsive.js +0 -31
  179. /package/{countdown-section-41f47745.d.ts → countdown-section-fb6524aa.d.ts} +0 -0
  180. /package/esm/{countdown-section-83bf5f20.d.ts → countdown-section-c65cff2d.d.ts} +0 -0
  181. /package/modern/{countdown-section-a28d693c.d.ts → countdown-section-dd4e5fe3.d.ts} +0 -0
@@ -0,0 +1,94 @@
1
+ import React, { FC, useContext } from 'react';
2
+ import cn from 'classnames';
3
+
4
+ import { Button } from '@alfalab/core-components-button';
5
+ import { Link } from '@alfalab/core-components-link';
6
+ import { Typography } from '@alfalab/core-components-typography';
7
+
8
+ import { ConfirmationContext } from '../../../context';
9
+ import { Header } from '../../header';
10
+
11
+ import styles from './index.module.css';
12
+
13
+ export type HintProps = {
14
+ /**
15
+ * Отображать в мобильной версии экран компонента
16
+ */
17
+ mobile?: boolean;
18
+ };
19
+
20
+ export const Hint: FC<HintProps> = ({ mobile }) => {
21
+ const { alignContent, texts, onChangeScreen, onChangeState, breakpoint } =
22
+ useContext(ConfirmationContext);
23
+
24
+ const handleReturnButtonClick = () => {
25
+ onChangeScreen('INITIAL');
26
+ onChangeState('INITIAL');
27
+ };
28
+
29
+ return (
30
+ <div className={cn(styles.component, styles[alignContent])}>
31
+ <Header mobile={mobile}>Не&nbsp;приходит сообщение?</Header>
32
+
33
+ <Typography.Text
34
+ view='primary-medium'
35
+ color='primary'
36
+ className={cn(styles.text, { [styles.typographyTheme]: !mobile })}
37
+ >
38
+ Если у&nbsp;вас изменился номер телефона, позвоните нам или обратитесь в&nbsp;любое
39
+ отделение банка.
40
+ </Typography.Text>
41
+
42
+ <div className={styles.phonesWrap}>
43
+ <div className={cn(styles.phoneWrap, { [styles.phoneContentMobile]: mobile })}>
44
+ <Link href='tel:+78002000000' underline={false} className={styles.phoneLink}>
45
+ 8 800 200-00-00
46
+ </Link>
47
+ <Typography.Text
48
+ view='primary-medium'
49
+ color='primary'
50
+ className={cn(styles.text, { [styles.typographyTheme]: !mobile })}
51
+ >
52
+ {mobile
53
+ ? 'Для\u00A0звонков по\u00A0России'
54
+ : ' \u2014\u00A0для звонков по\u00A0России'}
55
+ </Typography.Text>
56
+ </div>
57
+
58
+ <div className={cn(styles.phoneWrap, { [styles.phoneContentMobile]: mobile })}>
59
+ <Link href='tel:+74957888878' underline={false} className={styles.phoneLink}>
60
+ +7 495 78-888-78
61
+ </Link>
62
+ <Typography.Text
63
+ view='primary-medium'
64
+ color='primary'
65
+ className={cn(styles.text, { [styles.typographyTheme]: !mobile })}
66
+ >
67
+ {mobile
68
+ ? 'В\u00A0Москве и\u00A0за\u00A0границей'
69
+ : ' \u2014\u00A0в\u00A0Москве и\u00A0за\u00A0границей'}
70
+ </Typography.Text>
71
+ </div>
72
+ </div>
73
+
74
+ <Typography.Text
75
+ view='primary-medium'
76
+ color='primary'
77
+ className={cn(styles.text, { [styles.typographyTheme]: !mobile })}
78
+ >
79
+ Если номер не&nbsp;менялся, возможно, перегружен сервис отправки сообщений.
80
+ Попробуйте повторить действие через несколько минут.
81
+ </Typography.Text>
82
+
83
+ <Button
84
+ size={mobile ? 'xs' : 's'}
85
+ view='secondary'
86
+ onClick={handleReturnButtonClick}
87
+ className={styles.hintButton}
88
+ breakpoint={breakpoint}
89
+ >
90
+ {texts.hintButton}
91
+ </Button>
92
+ </div>
93
+ );
94
+ };
@@ -0,0 +1,51 @@
1
+ @import '../../../vars.css';
2
+
3
+ .component {
4
+ display: flex;
5
+ flex-direction: column;
6
+ align-items: flex-start;
7
+ & span:last-of-type {
8
+ margin-bottom: 0;
9
+ }
10
+ }
11
+
12
+ .center {
13
+ align-items: center;
14
+ text-align: center;
15
+ }
16
+
17
+ .text.text {
18
+ margin-bottom: var(--gap-xl);
19
+ }
20
+
21
+ .typographyTheme.typographyTheme {
22
+ @mixin _confirmation-text;
23
+ }
24
+
25
+ .phonesWrap {
26
+ display: flex;
27
+ flex-direction: column;
28
+ margin-bottom: var(--gap-xl);
29
+ }
30
+
31
+ .phoneWrap {
32
+ margin-bottom: var(--gap-xs);
33
+
34
+ &:last-child {
35
+ margin-bottom: 0;
36
+ }
37
+ }
38
+
39
+ .phoneLink.phoneLink {
40
+ @mixin action_primary_medium;
41
+ }
42
+
43
+ .hintButton {
44
+ margin-top: var(--gap-2xl);
45
+ }
46
+
47
+ .phoneContentMobile {
48
+ display: flex;
49
+ flex-direction: column;
50
+ align-items: center;
51
+ }
@@ -0,0 +1 @@
1
+ export * from './component';
@@ -0,0 +1,4 @@
1
+ export * from './initial';
2
+ export * from './hint';
3
+ export * from './fatal-error';
4
+ export * from './temp-block';
@@ -0,0 +1,190 @@
1
+ import React, {
2
+ FC,
3
+ useCallback,
4
+ useContext,
5
+ useEffect,
6
+ useLayoutEffect,
7
+ useRef,
8
+ useState,
9
+ } from 'react';
10
+ import cn from 'classnames';
11
+
12
+ import { ButtonMobile } from '@alfalab/core-components-button/mobile';
13
+ import { CodeInputDesktop } from '@alfalab/core-components-code-input/desktop';
14
+ import { CodeInputMobile } from '@alfalab/core-components-code-input/mobile';
15
+ import { BaseCodeInputProps, CustomInputRef } from '@alfalab/core-components-code-input/shared';
16
+ import { Link } from '@alfalab/core-components-link';
17
+ import { Typography } from '@alfalab/core-components-typography';
18
+ import { usePrevious } from '@alfalab/hooks';
19
+
20
+ import { ConfirmationContext } from '../../../context';
21
+ import { Header } from '../../header';
22
+
23
+ import { CountdownSection } from './countdown-section';
24
+
25
+ import styles from './index.module.css';
26
+
27
+ export type InitialProps = {
28
+ /**
29
+ * Отображать в мобильной версии экран компонента
30
+ */
31
+ mobile?: boolean;
32
+ };
33
+
34
+ const CODE_SEND_HINT_VISIBLE_DURATION = 2000;
35
+
36
+ export const Initial: FC<InitialProps> = ({ mobile }) => {
37
+ const {
38
+ state,
39
+ alignContent,
40
+ texts,
41
+ requiredCharAmount,
42
+ timeLeft,
43
+ phone,
44
+ clearCodeOnError,
45
+ hideCountdownSection,
46
+ onChangeState,
47
+ onInputFinished,
48
+ onChangeScreen,
49
+ onSmsRetryClick,
50
+ } = useContext(ConfirmationContext);
51
+
52
+ const prevState = usePrevious(state);
53
+
54
+ const inputRef = useRef<CustomInputRef>(null);
55
+
56
+ const [codeSendHintVisible, setCodeSendHintVisible] = useState(false);
57
+
58
+ const timerId = useRef(0);
59
+
60
+ const handleInputComplete: BaseCodeInputProps['onComplete'] = (code) => {
61
+ onInputFinished(code);
62
+ };
63
+
64
+ const handleSmsHintLinkClick = () => {
65
+ onChangeScreen('HINT');
66
+ };
67
+
68
+ const handleInputChange = () => {
69
+ if (state === 'CODE_ERROR') {
70
+ onChangeState('INITIAL');
71
+ }
72
+ };
73
+
74
+ const handleSmsRetryClick = () => {
75
+ if (inputRef.current) {
76
+ inputRef.current.reset();
77
+ }
78
+
79
+ onSmsRetryClick();
80
+ };
81
+
82
+ const handleErrorAnimationEnd = () => {
83
+ if (clearCodeOnError && state !== 'INITIAL') {
84
+ onChangeState('INITIAL');
85
+ }
86
+ };
87
+
88
+ const clearTimer = useCallback(() => {
89
+ window.clearTimeout(timerId.current);
90
+ }, []);
91
+
92
+ useEffect(() => {
93
+ if (inputRef.current) {
94
+ inputRef.current.focus();
95
+ }
96
+
97
+ return () => {
98
+ clearTimer();
99
+ };
100
+ }, [clearTimer]);
101
+
102
+ useEffect(() => {
103
+ if (!inputRef.current) {
104
+ return;
105
+ }
106
+
107
+ if (state === 'CODE_ERROR' && prevState !== 'CODE_ERROR') {
108
+ inputRef.current.focus(requiredCharAmount - 1);
109
+ }
110
+
111
+ if (prevState === 'CODE_SENDING' && state !== 'CODE_SENDING') {
112
+ inputRef.current.focus();
113
+ }
114
+ }, [prevState, state, requiredCharAmount]);
115
+
116
+ useLayoutEffect(() => {
117
+ if (prevState === 'CODE_SENDING' && state !== 'CODE_SENDING') {
118
+ setCodeSendHintVisible(true);
119
+
120
+ clearTimer();
121
+
122
+ timerId.current = window.setTimeout(() => {
123
+ setCodeSendHintVisible(false);
124
+ }, CODE_SEND_HINT_VISIBLE_DURATION);
125
+ }
126
+ }, [prevState, state, clearTimer]);
127
+
128
+ const getCodeInputError = (): string | boolean => {
129
+ if (state === 'CODE_ERROR') {
130
+ return texts.codeError || true;
131
+ }
132
+
133
+ return false;
134
+ };
135
+
136
+ const processing = ['CODE_CHECKING', 'CODE_SENDING'].includes(state);
137
+
138
+ const timePassed = timeLeft === 0;
139
+
140
+ const ComponentCodeInput = mobile ? CodeInputMobile : CodeInputDesktop;
141
+
142
+ return (
143
+ <div className={cn(styles.component, styles[alignContent])}>
144
+ <Header mobile={mobile}>{texts.title}</Header>
145
+
146
+ <Typography.Text
147
+ view='primary-medium'
148
+ color='primary'
149
+ className={cn(styles.phone, { [styles.typographyTheme]: !mobile })}
150
+ >
151
+ Код отправлен на {phone}
152
+ </Typography.Text>
153
+ <ComponentCodeInput
154
+ disabled={processing}
155
+ error={getCodeInputError()}
156
+ ref={inputRef}
157
+ fields={requiredCharAmount}
158
+ className={cn(styles.containerInput, styles.codeInput)}
159
+ onComplete={handleInputComplete}
160
+ onChange={handleInputChange}
161
+ clearCodeOnError={clearCodeOnError}
162
+ onErrorAnimationEnd={handleErrorAnimationEnd}
163
+ />
164
+ {!hideCountdownSection && (
165
+ <CountdownSection
166
+ processing={processing}
167
+ timePassed={timePassed}
168
+ codeSendHintVisible={codeSendHintVisible}
169
+ handleSmsRetryClick={handleSmsRetryClick}
170
+ mobile={mobile}
171
+ />
172
+ )}
173
+
174
+ {mobile ? (
175
+ <ButtonMobile onClick={handleSmsHintLinkClick} view='link' size='xs'>
176
+ {texts.linkToHint}
177
+ </ButtonMobile>
178
+ ) : (
179
+ <Link
180
+ onClick={handleSmsHintLinkClick}
181
+ className={styles.smsComeLink}
182
+ view={mobile ? 'primary' : 'secondary'}
183
+ pseudo={true}
184
+ >
185
+ {texts.linkToHint}
186
+ </Link>
187
+ )}
188
+ </div>
189
+ );
190
+ };
@@ -0,0 +1,79 @@
1
+ import React, { FC, useContext } from 'react';
2
+ import cn from 'classnames';
3
+
4
+ import { Button } from '@alfalab/core-components-button';
5
+ import { Loader } from '@alfalab/core-components-loader';
6
+ import { Typography } from '@alfalab/core-components-typography';
7
+
8
+ import { ConfirmationContext } from '../../../context';
9
+ import { formatMsAsMinutes } from '../../../utils';
10
+
11
+ import styles from './index.module.css';
12
+
13
+ type CountdownSectionProps = {
14
+ codeSendHintVisible: boolean;
15
+ timePassed: boolean;
16
+ processing: boolean;
17
+ mobile?: boolean;
18
+ handleSmsRetryClick: () => void;
19
+ };
20
+
21
+ export const CountdownSection: FC<CountdownSectionProps> = ({
22
+ codeSendHintVisible,
23
+ timePassed,
24
+ processing,
25
+ mobile,
26
+ handleSmsRetryClick,
27
+ }) => {
28
+ const { state, texts, timeLeft, blockSmsRetry, breakpoint } = useContext(ConfirmationContext);
29
+
30
+ const renderText = (text?: string) => (
31
+ <Typography.Text
32
+ className={cn(styles.countdownContainer, {
33
+ [styles.countdownMobile]: mobile,
34
+ [styles.typographyTheme]: !mobile,
35
+ })}
36
+ view={mobile ? 'primary-small' : 'primary-medium'}
37
+ tag='div'
38
+ >
39
+ {text}
40
+ </Typography.Text>
41
+ );
42
+
43
+ if (codeSendHintVisible) return renderText(texts.codeSended);
44
+
45
+ if (processing) {
46
+ return (
47
+ <div
48
+ className={cn(styles.loaderWrap, styles.countdownContainer, {
49
+ [styles.countdownLoaderMobile]: mobile,
50
+ [styles.typographyTheme]: !mobile,
51
+ })}
52
+ >
53
+ <Loader />
54
+
55
+ <span className={styles.loaderText}>
56
+ {state === 'CODE_CHECKING' ? texts.codeChecking : texts.codeSending}
57
+ </span>
58
+ </div>
59
+ );
60
+ }
61
+
62
+ if (blockSmsRetry) return renderText(texts.noAttemptsLeft);
63
+
64
+ if (timePassed) {
65
+ return (
66
+ <Button
67
+ size={mobile ? 'xs' : 'xxs'}
68
+ view='secondary'
69
+ onClick={handleSmsRetryClick}
70
+ className={cn(styles.getCodeButton, { [styles.getCodeButtonMobile]: mobile })}
71
+ breakpoint={breakpoint}
72
+ >
73
+ {texts.buttonRetry}
74
+ </Button>
75
+ );
76
+ }
77
+
78
+ return renderText(`${texts.countdown} ${formatMsAsMinutes(timeLeft)}`);
79
+ };
@@ -0,0 +1,71 @@
1
+ @import '../../../vars.css';
2
+
3
+ .component {
4
+ display: flex;
5
+ flex-direction: column;
6
+ }
7
+
8
+ .typographyTheme.typographyTheme {
9
+ @mixin _confirmation-text;
10
+ }
11
+
12
+ .phone.phone {
13
+ color: var(--color-light-text-primary);
14
+ margin-bottom: var(--gap-2xl);
15
+ }
16
+
17
+ .compact {
18
+ margin-bottom: var(--gap-xl);
19
+ }
20
+
21
+ .loaderWrap {
22
+ display: flex;
23
+ align-items: center;
24
+ }
25
+
26
+ .left {
27
+ align-items: flex-start;
28
+ }
29
+
30
+ .center {
31
+ align-items: center;
32
+ text-align: center;
33
+
34
+ & .loaderWrap {
35
+ justify-content: center;
36
+ }
37
+ }
38
+
39
+ .codeInput {
40
+ margin-bottom: var(--gap-s);
41
+ }
42
+
43
+ .smsComeLink.smsComeLink {
44
+ @mixin action_primary_small;
45
+ }
46
+
47
+ .countdownContainer.countdownContainer {
48
+ color: var(--color-light-text-secondary);
49
+ margin-bottom: var(--gap-xl);
50
+ }
51
+
52
+ .countdownMobile.countdownMobile {
53
+ margin-bottom: var(--gap-l);
54
+ }
55
+ .countdownLoaderMobile.countdownLoaderMobile {
56
+ margin-bottom: var(--gap-m);
57
+ }
58
+
59
+ .getCodeButton {
60
+ position: relative;
61
+ top: var(--gap-2xs-neg);
62
+ margin-bottom: var(--gap-m);
63
+ }
64
+
65
+ .getCodeButtonMobile {
66
+ margin-bottom: 0;
67
+ }
68
+
69
+ .containerInput {
70
+ min-height: 80px;
71
+ }
@@ -0,0 +1 @@
1
+ export * from './component';
@@ -0,0 +1,58 @@
1
+ import React, { FC, useContext, useEffect } from 'react';
2
+ import cn from 'classnames';
3
+
4
+ import { Typography } from '@alfalab/core-components-typography';
5
+
6
+ import { ConfirmationContext } from '../../../context';
7
+ import { formatMsAsMinutes, useCountdown } from '../../../utils';
8
+ import { CountdownLoader } from '../../countdown-loader';
9
+ import { Header } from '../../header';
10
+
11
+ import styles from './index.module.css';
12
+
13
+ export type TempBlockProps = {
14
+ /**
15
+ * Отображать в мобильной версии экран компонента
16
+ */
17
+ mobile?: boolean;
18
+ };
19
+
20
+ export const TempBlock: FC<TempBlockProps> = ({ mobile }) => {
21
+ const { alignContent, texts, tempBlockDuration, onChangeScreen, onTempBlockFinished } =
22
+ useContext(ConfirmationContext);
23
+
24
+ const [timeLeft, startTimer] = useCountdown(tempBlockDuration);
25
+
26
+ useEffect(() => {
27
+ startTimer();
28
+ }, [startTimer]);
29
+
30
+ useEffect(() => {
31
+ if (timeLeft === 0 && onTempBlockFinished) {
32
+ onTempBlockFinished();
33
+ }
34
+ }, [timeLeft, onChangeScreen, onTempBlockFinished]);
35
+
36
+ return (
37
+ <div className={cn(styles.component, styles[alignContent])}>
38
+ <Header mobile={mobile}>{texts.tempBlockTitle}</Header>
39
+
40
+ <Typography.Text
41
+ view='primary-medium'
42
+ color='primary'
43
+ className={cn(styles.description, { [styles.typographyTheme]: !mobile })}
44
+ >
45
+ {texts.tempBlockDescription}
46
+ </Typography.Text>
47
+
48
+ <div className={cn(styles.countdownWrap, { [styles.typographyTheme]: !mobile })}>
49
+ <CountdownLoader
50
+ progress={1 - timeLeft / tempBlockDuration}
51
+ className={styles.loader}
52
+ />
53
+
54
+ {formatMsAsMinutes(timeLeft)}
55
+ </div>
56
+ </div>
57
+ );
58
+ };
@@ -0,0 +1,28 @@
1
+ @import '../../../vars.css';
2
+
3
+ .component {
4
+ display: flex;
5
+ flex-direction: column;
6
+ }
7
+
8
+ .center {
9
+ align-items: center;
10
+ text-align: center;
11
+ }
12
+
13
+ .typographyTheme.typographyTheme {
14
+ @mixin _confirmation-text;
15
+ }
16
+
17
+ .description.description {
18
+ margin-bottom: var(--gap-xs);
19
+ }
20
+
21
+ .countdownWrap {
22
+ display: flex;
23
+ align-items: center;
24
+ }
25
+
26
+ .loader {
27
+ margin-right: var(--gap-xs);
28
+ }
@@ -0,0 +1 @@
1
+ export * from './component';
package/src/context.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { createContext } from 'react';
2
+
3
+ import { TConfirmationContext } from './types';
4
+ import { ONE_DAY, ONE_MINUTE } from './utils';
5
+
6
+ const mockFn = () => undefined;
7
+
8
+ export const ConfirmationContext = createContext<TConfirmationContext>({
9
+ alignContent: 'left',
10
+ texts: {},
11
+ state: 'INITIAL',
12
+ screen: 'INITIAL',
13
+ requiredCharAmount: 5,
14
+ countdownDuration: ONE_MINUTE,
15
+ timeLeft: ONE_MINUTE,
16
+ tempBlockDuration: ONE_DAY,
17
+ phone: '',
18
+ hideCountdownSection: false,
19
+ breakpoint: 1024,
20
+ onTempBlockFinished: mockFn,
21
+ onInputFinished: mockFn,
22
+ onChangeState: mockFn,
23
+ onSmsRetryClick: mockFn,
24
+ onChangeScreen: mockFn,
25
+ onFatalErrorOkButtonClick: mockFn,
26
+ });
package/src/desktop.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './component.desktop';
2
+
3
+ export { useConfirmation, useCountdown } from './utils';
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export {
2
+ ConfirmationResponsive as Confirmation,
3
+ ResponsiveConfirmationProps as ConfirmationProps,
4
+ } from './component.responsive';
5
+
6
+ export { useConfirmation, useCountdown } from './utils';
@@ -0,0 +1,3 @@
1
+ .container {
2
+ max-width: 288px;
3
+ }
package/src/mobile.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './component.mobile';
2
+
3
+ export { useConfirmation, useCountdown } from './utils';
package/src/shared.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './components';
2
+ export * from './context';
3
+ export * from './types';
4
+ export { formatMsAsMinutes, ONE_MINUTE, ONE_DAY } from './utils';