@alfalab/core-components-confirmation 13.8.2 → 13.9.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 (109) hide show
  1. package/component.responsive.d.ts +5 -0
  2. package/component.responsive.js +2 -3
  3. package/components/base-confirmation/component.js +4 -4
  4. package/components/base-confirmation/index.css +2 -2
  5. package/components/countdown-loader/component.js +1 -1
  6. package/components/countdown-loader/index.css +2 -2
  7. package/components/header/component.js +1 -1
  8. package/components/header/index.css +4 -4
  9. package/components/screens/fatal-error/component.js +3 -3
  10. package/components/screens/fatal-error/index.css +7 -7
  11. package/components/screens/hint/component.js +7 -5
  12. package/components/screens/hint/index.css +13 -13
  13. package/components/screens/initial/component.js +1 -1
  14. package/components/screens/initial/countdown-section.js +1 -1
  15. package/components/screens/initial/index.css +19 -19
  16. package/components/screens/temp-block/component.js +1 -1
  17. package/components/screens/temp-block/index.css +8 -8
  18. package/context.js +1 -0
  19. package/{countdown-section-b633717a.js → countdown-section-d7a44cd1.js} +4 -4
  20. package/cssm/component.responsive.d.ts +5 -0
  21. package/cssm/component.responsive.js +2 -3
  22. package/cssm/components/base-confirmation/component.js +3 -3
  23. package/cssm/components/screens/fatal-error/component.js +2 -2
  24. package/cssm/components/screens/hint/component.js +6 -4
  25. package/cssm/components/screens/initial/countdown-section.js +3 -3
  26. package/cssm/context.js +1 -0
  27. package/cssm/types.d.ts +11 -27
  28. package/cssm/types.js +2 -0
  29. package/cssm/utils.d.ts +5 -1
  30. package/cssm/utils.js +8 -0
  31. package/esm/component.responsive.d.ts +5 -0
  32. package/esm/component.responsive.js +3 -4
  33. package/esm/components/base-confirmation/component.js +4 -4
  34. package/esm/components/base-confirmation/index.css +2 -2
  35. package/esm/components/countdown-loader/component.js +1 -1
  36. package/esm/components/countdown-loader/index.css +2 -2
  37. package/esm/components/header/component.js +1 -1
  38. package/esm/components/header/index.css +4 -4
  39. package/esm/components/screens/fatal-error/component.js +3 -3
  40. package/esm/components/screens/fatal-error/index.css +7 -7
  41. package/esm/components/screens/hint/component.js +7 -5
  42. package/esm/components/screens/hint/index.css +13 -13
  43. package/esm/components/screens/initial/component.js +1 -1
  44. package/esm/components/screens/initial/countdown-section.js +1 -1
  45. package/esm/components/screens/initial/index.css +19 -19
  46. package/esm/components/screens/temp-block/component.js +1 -1
  47. package/esm/components/screens/temp-block/index.css +8 -8
  48. package/esm/context.js +1 -0
  49. package/esm/{countdown-section-88d8eded.js → countdown-section-25714e1f.js} +4 -4
  50. package/esm/mobile/component.mobile.js +1 -1
  51. package/esm/mobile/mobile.css +2 -2
  52. package/esm/types.d.ts +11 -27
  53. package/esm/types.js +2 -0
  54. package/esm/utils.d.ts +5 -1
  55. package/esm/utils.js +8 -1
  56. package/mobile/component.mobile.js +1 -1
  57. package/mobile/mobile.css +2 -2
  58. package/modern/component.responsive.d.ts +5 -0
  59. package/modern/component.responsive.js +3 -4
  60. package/modern/components/base-confirmation/component.js +3 -3
  61. package/modern/components/base-confirmation/index.css +2 -2
  62. package/modern/components/countdown-loader/component.js +1 -1
  63. package/modern/components/countdown-loader/index.css +2 -2
  64. package/modern/components/header/component.js +1 -1
  65. package/modern/components/header/index.css +4 -4
  66. package/modern/components/screens/fatal-error/component.js +3 -3
  67. package/modern/components/screens/fatal-error/index.css +7 -7
  68. package/modern/components/screens/hint/component.js +7 -5
  69. package/modern/components/screens/hint/index.css +13 -13
  70. package/modern/components/screens/initial/component.js +1 -1
  71. package/modern/components/screens/initial/countdown-section.js +1 -1
  72. package/modern/components/screens/initial/index.css +19 -19
  73. package/modern/components/screens/temp-block/component.js +1 -1
  74. package/modern/components/screens/temp-block/index.css +8 -8
  75. package/modern/context.js +1 -0
  76. package/modern/{countdown-section-9cd2a918.js → countdown-section-cdcdc727.js} +4 -4
  77. package/modern/mobile/component.mobile.js +1 -1
  78. package/modern/mobile/mobile.css +2 -2
  79. package/modern/types.d.ts +11 -27
  80. package/modern/types.js +2 -0
  81. package/modern/utils.d.ts +5 -1
  82. package/modern/utils.js +8 -1
  83. package/moderncssm/component.responsive.d.ts +5 -0
  84. package/moderncssm/component.responsive.js +3 -4
  85. package/moderncssm/components/base-confirmation/component.js +2 -2
  86. package/moderncssm/components/screens/fatal-error/component.js +2 -2
  87. package/moderncssm/components/screens/hint/component.js +6 -4
  88. package/moderncssm/components/screens/initial/countdown-section.js +3 -3
  89. package/moderncssm/context.js +1 -0
  90. package/moderncssm/types.d.ts +11 -27
  91. package/moderncssm/types.js +2 -0
  92. package/moderncssm/utils.d.ts +5 -1
  93. package/moderncssm/utils.js +8 -1
  94. package/package.json +5 -5
  95. package/src/component.responsive.tsx +11 -5
  96. package/src/components/base-confirmation/component.tsx +3 -2
  97. package/src/components/screens/fatal-error/component.tsx +2 -1
  98. package/src/components/screens/hint/component.tsx +10 -6
  99. package/src/components/screens/initial/countdown-section.tsx +4 -2
  100. package/src/context.ts +1 -0
  101. package/src/types.ts +15 -11
  102. package/src/utils.ts +9 -0
  103. package/types.d.ts +11 -27
  104. package/types.js +2 -0
  105. package/utils.d.ts +5 -1
  106. package/utils.js +8 -0
  107. /package/{countdown-section-b633717a.d.ts → countdown-section-d7a44cd1.d.ts} +0 -0
  108. /package/esm/{countdown-section-88d8eded.d.ts → countdown-section-25714e1f.d.ts} +0 -0
  109. /package/modern/{countdown-section-9cd2a918.d.ts → countdown-section-cdcdc727.d.ts} +0 -0
package/modern/utils.js CHANGED
@@ -68,5 +68,12 @@ const useConfirmation = ({ state, screen, blockSmsRetry } = {}) => {
68
68
  setConfirmationBlockSmsRetry,
69
69
  };
70
70
  };
71
+ const NON_NUMBER_OR_PLUS_REGEXP = new RegExp(/[^\d+]/g);
72
+ /**
73
+ * @returns ссылку для набора номера
74
+ */
75
+ function getPhoneHref(phone) {
76
+ return `tel:${phone.replace(NON_NUMBER_OR_PLUS_REGEXP, '')}`;
77
+ }
71
78
 
72
- export { ONE_DAY, ONE_MINUTE, formatMsAsMinutes, useConfirmation, useCountdown };
79
+ export { ONE_DAY, ONE_MINUTE, formatMsAsMinutes, getPhoneHref, useConfirmation, useCountdown };
@@ -6,8 +6,13 @@ type ResponsiveConfirmationProps = Omit<ConfirmationProps, 'confirmationScreens'
6
6
  * @default 1024
7
7
  */
8
8
  breakpoint?: number;
9
+ /**
10
+ * Версия, которая будет использоваться при серверном рендеринге
11
+ */
12
+ client?: 'desktop' | 'mobile';
9
13
  /**
10
14
  * Значение по-умолчанию для хука useMatchMedia
15
+ * @deprecated Используйте client
11
16
  */
12
17
  defaultMatchMediaValue?: boolean | (() => boolean);
13
18
  };
@@ -1,11 +1,10 @@
1
1
  import React from 'react';
2
- import { useMatchMedia } from '@alfalab/core-components-mq/moderncssm';
3
- import { getComponentBreakpoint } from '@alfalab/core-components-shared/moderncssm';
2
+ import { useIsDesktop } from '@alfalab/core-components-mq/moderncssm';
4
3
  import { ConfirmationDesktop } from './desktop/component.desktop.js';
5
4
  import { ConfirmationMobile } from './mobile/component.mobile.js';
6
5
 
7
- const ConfirmationResponsive = ({ breakpoint = getComponentBreakpoint(), defaultMatchMediaValue = true, ...restProps }) => {
8
- const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue);
6
+ const ConfirmationResponsive = ({ breakpoint, client, defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', ...restProps }) => {
7
+ const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue);
9
8
  return isDesktop ? (React.createElement(ConfirmationDesktop, { ...restProps })) : (React.createElement(ConfirmationMobile, { breakpoint: breakpoint, ...restProps }));
10
9
  };
11
10
 
@@ -1,6 +1,5 @@
1
1
  import React, { useEffect, useMemo } from 'react';
2
2
  import cn from 'classnames';
3
- import { getComponentBreakpoint } from '@alfalab/core-components-shared/moderncssm';
4
3
  import { usePrevious } from '@alfalab/hooks';
5
4
  import { ConfirmationContext } from '../../context.js';
6
5
  import { defaultTexts } from '../../types.js';
@@ -17,7 +16,7 @@ const confirmationScreens = {
17
16
  FATAL_ERROR: FatalError,
18
17
  TEMP_BLOCK: TempBlock,
19
18
  };
20
- const BaseConfirmation = ({ state, screen, alignContent = 'left', children, requiredCharAmount = 5, countdownDuration = ONE_MINUTE, tempBlockDuration = ONE_DAY, phone, blockSmsRetry, dataTestId, className, getScreensMap, onInputFinished, onChangeState, onSmsRetryClick, onChangeScreen, onFatalErrorOkButtonClick, onTempBlockFinished, mobile, clearCodeOnError = true, hideCountdownSection = false, breakpoint = getComponentBreakpoint(), initialScreenHintSlot, errorVisibleDuration, ...restProps }) => {
19
+ const BaseConfirmation = ({ state, screen, alignContent = 'left', children, requiredCharAmount = 5, countdownDuration = ONE_MINUTE, tempBlockDuration = ONE_DAY, phone, blockSmsRetry, dataTestId, className, getScreensMap, onInputFinished, onChangeState, onSmsRetryClick, onChangeScreen, onFatalErrorOkButtonClick, onTempBlockFinished, mobile, clearCodeOnError = true, hideCountdownSection = false, breakpoint, client, initialScreenHintSlot, errorVisibleDuration, ...restProps }) => {
21
20
  const [timeLeft, startTimer, stopTimer] = useCountdown(countdownDuration);
22
21
  const prevState = usePrevious(state);
23
22
  useEffect(() => {
@@ -66,6 +65,7 @@ const BaseConfirmation = ({ state, screen, alignContent = 'left', children, requ
66
65
  phone,
67
66
  blockSmsRetry,
68
67
  breakpoint,
68
+ client,
69
69
  onTempBlockFinished,
70
70
  onChangeState,
71
71
  onChangeScreen,
@@ -7,14 +7,14 @@ import { Header } from '../../header/component.js';
7
7
  import styles from './index.module.css';
8
8
 
9
9
  const FatalError = ({ mobile }) => {
10
- const { alignContent, texts, onFatalErrorOkButtonClick, breakpoint } = useContext(ConfirmationContext);
10
+ const { alignContent, texts, onFatalErrorOkButtonClick, breakpoint, client } = useContext(ConfirmationContext);
11
11
  return (React.createElement("div", { className: cn(styles.component, styles[alignContent]) },
12
12
  React.createElement(Header, { mobile: mobile }, texts.fatalErrorTitle),
13
13
  React.createElement(Typography.Text, { view: 'primary-medium', color: 'primary', className: cn({
14
14
  [styles.typographyTheme]: !mobile,
15
15
  [styles.typographyThemeMobile]: mobile,
16
16
  }) }, texts.fatalErrorDescription),
17
- React.createElement(Button, { size: mobile ? 'xs' : 's', view: 'secondary', onClick: onFatalErrorOkButtonClick, className: styles.button, breakpoint: breakpoint }, texts.fatalErrorButton)));
17
+ React.createElement(Button, { size: mobile ? 'xs' : 's', view: 'secondary', onClick: onFatalErrorOkButtonClick, className: styles.button, breakpoint: breakpoint, client: client }, texts.fatalErrorButton)));
18
18
  };
19
19
 
20
20
  export { FatalError };
@@ -4,11 +4,13 @@ import { Button } from '@alfalab/core-components-button/moderncssm';
4
4
  import { Link } from '@alfalab/core-components-link/moderncssm';
5
5
  import { Typography } from '@alfalab/core-components-typography/moderncssm';
6
6
  import { ConfirmationContext } from '../../../context.js';
7
+ import { getPhoneHref } from '../../../utils.js';
7
8
  import { Header } from '../../header/component.js';
8
9
  import styles from './index.module.css';
9
10
 
10
11
  const Hint = ({ mobile }) => {
11
- const { alignContent, texts, onChangeScreen, onChangeState, breakpoint } = useContext(ConfirmationContext);
12
+ const { alignContent, texts, onChangeScreen, onChangeState, breakpoint, client } = useContext(ConfirmationContext);
13
+ const { domesticPhone = '', internationalPhone = '', hintButton } = texts;
12
14
  const handleReturnButtonClick = () => {
13
15
  onChangeScreen('INITIAL');
14
16
  onChangeState('INITIAL');
@@ -23,7 +25,7 @@ const Hint = ({ mobile }) => {
23
25
  [styles.phonesWrapMobile]: mobile,
24
26
  }) },
25
27
  React.createElement("div", { className: cn(styles.phoneWrap, { [styles.phoneContentMobile]: mobile }) },
26
- React.createElement(Link, { href: 'tel:+78002000000', underline: false, className: cn(styles.phoneLink, { [styles.typographyThemeMobile]: mobile }) }, "8 800 200 00 00"),
28
+ React.createElement(Link, { href: getPhoneHref(domesticPhone), underline: false, className: cn(styles.phoneLink, { [styles.typographyThemeMobile]: mobile }) }, domesticPhone),
27
29
  React.createElement(Typography.Text, { view: 'primary-medium', color: 'primary', className: cn(styles.text, {
28
30
  [styles.typographyTheme]: !mobile,
29
31
  [styles.typographyThemeMobile]: mobile,
@@ -31,7 +33,7 @@ const Hint = ({ mobile }) => {
31
33
  ? 'Для\u00A0звонков по\u00A0России'
32
34
  : ' \u2014\u00A0для звонков по\u00A0России')),
33
35
  React.createElement("div", { className: cn(styles.phoneWrap, { [styles.phoneContentMobile]: mobile }) },
34
- React.createElement(Link, { href: 'tel:+74957888878', underline: false, className: cn(styles.phoneLink, { [styles.typographyThemeMobile]: mobile }) }, "+7 495 78 888 78"),
36
+ React.createElement(Link, { href: getPhoneHref(internationalPhone), underline: false, className: cn(styles.phoneLink, { [styles.typographyThemeMobile]: mobile }) }, internationalPhone),
35
37
  React.createElement(Typography.Text, { view: 'primary-medium', color: 'primary', className: cn(styles.text, {
36
38
  [styles.typographyTheme]: !mobile,
37
39
  [styles.typographyThemeMobile]: mobile,
@@ -42,7 +44,7 @@ const Hint = ({ mobile }) => {
42
44
  [styles.typographyTheme]: !mobile,
43
45
  [styles.typographyThemeMobile]: mobile,
44
46
  }) }, "\u0415\u0441\u043B\u0438 \u043D\u043E\u043C\u0435\u0440 \u043D\u0435\u00A0\u043C\u0435\u043D\u044F\u043B\u0441\u044F, \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E, \u043F\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043D \u0441\u0435\u0440\u0432\u0438\u0441 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439. \u041F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u043C\u0438\u043D\u0443\u0442."),
45
- React.createElement(Button, { size: mobile ? 'xs' : 's', view: 'secondary', onClick: handleReturnButtonClick, className: styles.hintButton, breakpoint: breakpoint }, texts.hintButton)));
47
+ React.createElement(Button, { size: mobile ? 'xs' : 's', view: 'secondary', onClick: handleReturnButtonClick, className: styles.hintButton, breakpoint: breakpoint, client: client }, hintButton)));
46
48
  };
47
49
 
48
50
  export { Hint };
@@ -8,7 +8,7 @@ import { formatMsAsMinutes } from '../../../utils.js';
8
8
  import styles from './index.module.css';
9
9
 
10
10
  const CountdownSection = ({ codeSendHintVisible, timePassed, processing, mobile, handleSmsRetryClick, }) => {
11
- const { state, texts, timeLeft, blockSmsRetry, breakpoint } = useContext(ConfirmationContext);
11
+ const { state, texts, timeLeft, blockSmsRetry, breakpoint, client } = useContext(ConfirmationContext);
12
12
  const renderText = (text) => (React.createElement(Typography.Text, { className: cn(styles.countdownContainer, {
13
13
  [styles.countdownMobile]: mobile,
14
14
  [styles.typographyTheme]: !mobile,
@@ -20,13 +20,13 @@ const CountdownSection = ({ codeSendHintVisible, timePassed, processing, mobile,
20
20
  [styles.countdownLoaderMobile]: mobile,
21
21
  [styles.typographyTheme]: !mobile,
22
22
  }) },
23
- React.createElement(Spinner, { visible: true }),
23
+ React.createElement(Spinner, { preset: 24, visible: true }),
24
24
  React.createElement("span", { className: styles.loaderText }, state === 'CODE_CHECKING' ? texts.codeChecking : texts.codeSending)));
25
25
  }
26
26
  if (blockSmsRetry)
27
27
  return renderText(texts.noAttemptsLeft);
28
28
  if (timePassed) {
29
- return (React.createElement(Button, { size: mobile ? 'xs' : 'xxs', view: 'secondary', onClick: handleSmsRetryClick, className: cn(styles.getCodeButton, { [styles.getCodeButtonMobile]: mobile }), breakpoint: breakpoint }, texts.buttonRetry));
29
+ return (React.createElement(Button, { size: mobile ? 'xs' : 'xxs', view: 'secondary', onClick: handleSmsRetryClick, className: cn(styles.getCodeButton, { [styles.getCodeButtonMobile]: mobile }), breakpoint: breakpoint, client: client }, texts.buttonRetry));
30
30
  }
31
31
  return renderText(`${texts.countdown} ${formatMsAsMinutes(timeLeft)}`);
32
32
  };
@@ -14,6 +14,7 @@ const ConfirmationContext = createContext({
14
14
  phone: '',
15
15
  hideCountdownSection: false,
16
16
  breakpoint: 1024,
17
+ client: 'desktop',
17
18
  initialScreenHintSlot: null,
18
19
  onTempBlockFinished: mockFn,
19
20
  onInputFinished: mockFn,
@@ -77,11 +77,11 @@ type ConfirmationProps = {
77
77
  */
78
78
  onTempBlockFinished?: () => void;
79
79
  /**
80
- * Возввращает объект, где ключ - название экрана (screen), значение - компонент для экрана
80
+ * Возвращает объект, где ключ - название экрана (screen), значение - компонент для экрана
81
81
  */
82
- getScreensMap?: (defaulScreensMap: ScreensMap) => ScreensMap;
82
+ getScreensMap?: (defaultScreensMap: ScreensMap) => ScreensMap;
83
83
  /**
84
- * Дочерние элементы.
84
+ * Дочерние элементы
85
85
  */
86
86
  children?: ReactNode;
87
87
  /**
@@ -98,20 +98,18 @@ type ConfirmationProps = {
98
98
  * @default 1024
99
99
  */
100
100
  breakpoint?: number;
101
+ /**
102
+ * Версия, которая будет использоваться при серверном рендеринге
103
+ */
104
+ client?: 'desktop' | 'mobile';
101
105
  /**
102
106
  * Продолжительность отображения ошибки
103
107
  * @default 1300
104
108
  */
105
109
  errorVisibleDuration?: number;
106
110
  };
107
- type TConfirmationContext = Required<Pick<ConfirmationProps, 'alignContent' | 'texts' | 'state' | 'screen' | 'requiredCharAmount' | 'onInputFinished' | 'countdownDuration' | 'onChangeState' | 'onSmsRetryClick' | 'onChangeScreen' | 'onFatalErrorOkButtonClick' | 'tempBlockDuration' | 'hideCountdownSection'>> & Pick<ConfirmationProps, 'phone' | 'blockSmsRetry' | 'onTempBlockFinished' | 'clearCodeOnError' | 'initialScreenHintSlot' | 'errorVisibleDuration'> & {
111
+ type TConfirmationContext = Required<Pick<ConfirmationProps, 'alignContent' | 'texts' | 'state' | 'screen' | 'requiredCharAmount' | 'onInputFinished' | 'countdownDuration' | 'onChangeState' | 'onSmsRetryClick' | 'onChangeScreen' | 'onFatalErrorOkButtonClick' | 'tempBlockDuration' | 'hideCountdownSection'>> & Pick<ConfirmationProps, 'phone' | 'blockSmsRetry' | 'onTempBlockFinished' | 'clearCodeOnError' | 'initialScreenHintSlot' | 'errorVisibleDuration' | 'breakpoint' | 'client'> & {
108
112
  timeLeft: number;
109
- } & {
110
- /**
111
- * Контрольная точка для кнопки, с нее начинается desktop версия
112
- * @default 1024
113
- */
114
- breakpoint?: number;
115
113
  };
116
114
  type ConfirmationTexts = {
117
115
  /**
@@ -130,6 +128,8 @@ type ConfirmationTexts = {
130
128
  * Экран HINT
131
129
  */
132
130
  hintButton?: string;
131
+ domesticPhone?: string;
132
+ internationalPhone?: string;
133
133
  /**
134
134
  * Экран FATAL_ERROR
135
135
  */
@@ -147,21 +147,5 @@ type ConfirmationState = 'INITIAL' | 'CODE_CHECKING' | 'CODE_SENDING' | 'CODE_ER
147
147
  type ScreensMap = {
148
148
  [key: string]: ComponentType;
149
149
  };
150
- declare const defaultTexts: {
151
- title: string;
152
- codeError: string;
153
- codeChecking: string;
154
- codeSending: string;
155
- buttonRetry: string;
156
- linkToHint: string;
157
- hintButton: string;
158
- noAttemptsLeft: string;
159
- fatalErrorTitle: string;
160
- fatalErrorDescription: string;
161
- fatalErrorButton: string;
162
- tempBlockTitle: string;
163
- tempBlockDescription: string;
164
- codeSended: string;
165
- countdown: string;
166
- };
150
+ declare const defaultTexts: ConfirmationTexts;
167
151
  export { ConfirmationProps, TConfirmationContext, ConfirmationTexts, ConfirmationScreen, ConfirmationState, ScreensMap, defaultTexts };
@@ -14,6 +14,8 @@ const defaultTexts = {
14
14
  tempBlockDescription: 'Повторное подтверждение кодом будет возможно через 24\xa0часа',
15
15
  codeSended: 'Код выслан',
16
16
  countdown: 'Запросить повторно можно через',
17
+ domesticPhone: '8 800 200 00 00',
18
+ internationalPhone: '+7 495 78 888 78',
17
19
  };
18
20
 
19
21
  export { defaultTexts };
@@ -27,4 +27,8 @@ declare const useConfirmation: ({ state, screen, blockSmsRetry }?: UseConfirmati
27
27
  setConfirmationScreen: import("react").Dispatch<import("react").SetStateAction<string>>;
28
28
  setConfirmationBlockSmsRetry: import("react").Dispatch<import("react").SetStateAction<boolean>>;
29
29
  };
30
- export { formatMsAsMinutes, useCountdown, ONE_DAY, ONE_MINUTE, useConfirmation };
30
+ /**
31
+ * @returns ссылку для набора номера
32
+ */
33
+ declare function getPhoneHref(phone: string): string;
34
+ export { formatMsAsMinutes, useCountdown, ONE_DAY, ONE_MINUTE, useConfirmation, getPhoneHref };
@@ -68,5 +68,12 @@ const useConfirmation = ({ state, screen, blockSmsRetry } = {}) => {
68
68
  setConfirmationBlockSmsRetry,
69
69
  };
70
70
  };
71
+ const NON_NUMBER_OR_PLUS_REGEXP = new RegExp(/[^\d+]/g);
72
+ /**
73
+ * @returns ссылку для набора номера
74
+ */
75
+ function getPhoneHref(phone) {
76
+ return `tel:${phone.replace(NON_NUMBER_OR_PLUS_REGEXP, '')}`;
77
+ }
71
78
 
72
- export { ONE_DAY, ONE_MINUTE, formatMsAsMinutes, useConfirmation, useCountdown };
79
+ export { ONE_DAY, ONE_MINUTE, formatMsAsMinutes, getPhoneHref, useConfirmation, useCountdown };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfalab/core-components-confirmation",
3
- "version": "13.8.2",
3
+ "version": "13.9.0",
4
4
  "description": "Sms confirmation component",
5
5
  "keywords": [],
6
6
  "license": "MIT",
@@ -11,16 +11,16 @@
11
11
  "directory": "dist"
12
12
  },
13
13
  "dependencies": {
14
- "@alfalab/core-components-button": "^11.10.0",
15
- "@alfalab/core-components-code-input": "^3.9.0",
14
+ "@alfalab/core-components-button": "^11.10.1",
15
+ "@alfalab/core-components-code-input": "^3.9.1",
16
16
  "@alfalab/core-components-link": "^5.3.1",
17
- "@alfalab/core-components-spinner": "^3.5.0",
17
+ "@alfalab/core-components-spinner": "^4.0.0",
18
18
  "@alfalab/core-components-typography": "^4.10.2",
19
19
  "@alfalab/core-components-mq": "^4.3.0",
20
20
  "@alfalab/hooks": "^1.13.0",
21
21
  "classnames": "^2.3.1",
22
22
  "tslib": "^2.4.0",
23
- "@alfalab/core-components-shared": "^0.13.0"
23
+ "@alfalab/core-components-shared": "^0.14.0"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "react": "^16.9.0 || ^17.0.1 || ^18.0.0"
@@ -1,7 +1,6 @@
1
1
  import React, { FC } from 'react';
2
2
 
3
- import { useMatchMedia } from '@alfalab/core-components-mq';
4
- import { getComponentBreakpoint } from '@alfalab/core-components-shared';
3
+ import { useIsDesktop } from '@alfalab/core-components-mq';
5
4
 
6
5
  import { ConfirmationDesktop } from './desktop';
7
6
  import { ConfirmationMobile } from './mobile';
@@ -17,18 +16,25 @@ export type ResponsiveConfirmationProps = Omit<
17
16
  */
18
17
  breakpoint?: number;
19
18
 
19
+ /**
20
+ * Версия, которая будет использоваться при серверном рендеринге
21
+ */
22
+ client?: 'desktop' | 'mobile';
23
+
20
24
  /**
21
25
  * Значение по-умолчанию для хука useMatchMedia
26
+ * @deprecated Используйте client
22
27
  */
23
28
  defaultMatchMediaValue?: boolean | (() => boolean);
24
29
  };
25
30
 
26
31
  export const ConfirmationResponsive: FC<ResponsiveConfirmationProps> = ({
27
- breakpoint = getComponentBreakpoint(),
28
- defaultMatchMediaValue = true,
32
+ breakpoint,
33
+ client,
34
+ defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop',
29
35
  ...restProps
30
36
  }) => {
31
- const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue);
37
+ const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue);
32
38
 
33
39
  return isDesktop ? (
34
40
  <ConfirmationDesktop {...restProps} />
@@ -1,7 +1,6 @@
1
1
  import React, { ComponentType, FC, useEffect, useMemo } from 'react';
2
2
  import cn from 'classnames';
3
3
 
4
- import { getComponentBreakpoint } from '@alfalab/core-components-shared';
5
4
  import { usePrevious } from '@alfalab/hooks';
6
5
 
7
6
  import { ConfirmationContext } from '../../context';
@@ -40,7 +39,8 @@ export const BaseConfirmation: FC<ConfirmationProps> = ({
40
39
  mobile,
41
40
  clearCodeOnError = true,
42
41
  hideCountdownSection = false,
43
- breakpoint = getComponentBreakpoint(),
42
+ breakpoint,
43
+ client,
44
44
  initialScreenHintSlot,
45
45
  errorVisibleDuration,
46
46
  ...restProps
@@ -103,6 +103,7 @@ export const BaseConfirmation: FC<ConfirmationProps> = ({
103
103
  phone,
104
104
  blockSmsRetry,
105
105
  breakpoint,
106
+ client,
106
107
  onTempBlockFinished,
107
108
  onChangeState,
108
109
  onChangeScreen,
@@ -17,7 +17,7 @@ export type FatalErrorProps = {
17
17
  };
18
18
 
19
19
  export const FatalError: FC<FatalErrorProps> = ({ mobile }) => {
20
- const { alignContent, texts, onFatalErrorOkButtonClick, breakpoint } =
20
+ const { alignContent, texts, onFatalErrorOkButtonClick, breakpoint, client } =
21
21
  useContext(ConfirmationContext);
22
22
 
23
23
  return (
@@ -41,6 +41,7 @@ export const FatalError: FC<FatalErrorProps> = ({ mobile }) => {
41
41
  onClick={onFatalErrorOkButtonClick}
42
42
  className={styles.button}
43
43
  breakpoint={breakpoint}
44
+ client={client}
44
45
  >
45
46
  {texts.fatalErrorButton}
46
47
  </Button>
@@ -6,6 +6,7 @@ import { Link } from '@alfalab/core-components-link';
6
6
  import { Typography } from '@alfalab/core-components-typography';
7
7
 
8
8
  import { ConfirmationContext } from '../../../context';
9
+ import { getPhoneHref } from '../../../utils';
9
10
  import { Header } from '../../header';
10
11
 
11
12
  import styles from './index.module.css';
@@ -18,9 +19,11 @@ export type HintProps = {
18
19
  };
19
20
 
20
21
  export const Hint: FC<HintProps> = ({ mobile }) => {
21
- const { alignContent, texts, onChangeScreen, onChangeState, breakpoint } =
22
+ const { alignContent, texts, onChangeScreen, onChangeState, breakpoint, client } =
22
23
  useContext(ConfirmationContext);
23
24
 
25
+ const { domesticPhone = '', internationalPhone = '', hintButton } = texts;
26
+
24
27
  const handleReturnButtonClick = () => {
25
28
  onChangeScreen('INITIAL');
26
29
  onChangeState('INITIAL');
@@ -49,11 +52,11 @@ export const Hint: FC<HintProps> = ({ mobile }) => {
49
52
  >
50
53
  <div className={cn(styles.phoneWrap, { [styles.phoneContentMobile]: mobile })}>
51
54
  <Link
52
- href='tel:+78002000000'
55
+ href={getPhoneHref(domesticPhone)}
53
56
  underline={false}
54
57
  className={cn(styles.phoneLink, { [styles.typographyThemeMobile]: mobile })}
55
58
  >
56
- 8 800 200 00 00
59
+ {domesticPhone}
57
60
  </Link>
58
61
  <Typography.Text
59
62
  view='primary-medium'
@@ -71,11 +74,11 @@ export const Hint: FC<HintProps> = ({ mobile }) => {
71
74
 
72
75
  <div className={cn(styles.phoneWrap, { [styles.phoneContentMobile]: mobile })}>
73
76
  <Link
74
- href='tel:+74957888878'
77
+ href={getPhoneHref(internationalPhone)}
75
78
  underline={false}
76
79
  className={cn(styles.phoneLink, { [styles.typographyThemeMobile]: mobile })}
77
80
  >
78
- +7 495 78 888 78
81
+ {internationalPhone}
79
82
  </Link>
80
83
  <Typography.Text
81
84
  view='primary-medium'
@@ -110,8 +113,9 @@ export const Hint: FC<HintProps> = ({ mobile }) => {
110
113
  onClick={handleReturnButtonClick}
111
114
  className={styles.hintButton}
112
115
  breakpoint={breakpoint}
116
+ client={client}
113
117
  >
114
- {texts.hintButton}
118
+ {hintButton}
115
119
  </Button>
116
120
  </div>
117
121
  );
@@ -25,7 +25,8 @@ export const CountdownSection: FC<CountdownSectionProps> = ({
25
25
  mobile,
26
26
  handleSmsRetryClick,
27
27
  }) => {
28
- const { state, texts, timeLeft, blockSmsRetry, breakpoint } = useContext(ConfirmationContext);
28
+ const { state, texts, timeLeft, blockSmsRetry, breakpoint, client } =
29
+ useContext(ConfirmationContext);
29
30
 
30
31
  const renderText = (text?: string) => (
31
32
  <Typography.Text
@@ -50,7 +51,7 @@ export const CountdownSection: FC<CountdownSectionProps> = ({
50
51
  [styles.typographyTheme]: !mobile,
51
52
  })}
52
53
  >
53
- <Spinner visible={true} />
54
+ <Spinner preset={24} visible={true} />
54
55
 
55
56
  <span className={styles.loaderText}>
56
57
  {state === 'CODE_CHECKING' ? texts.codeChecking : texts.codeSending}
@@ -69,6 +70,7 @@ export const CountdownSection: FC<CountdownSectionProps> = ({
69
70
  onClick={handleSmsRetryClick}
70
71
  className={cn(styles.getCodeButton, { [styles.getCodeButtonMobile]: mobile })}
71
72
  breakpoint={breakpoint}
73
+ client={client}
72
74
  >
73
75
  {texts.buttonRetry}
74
76
  </Button>
package/src/context.ts CHANGED
@@ -17,6 +17,7 @@ export const ConfirmationContext = createContext<TConfirmationContext>({
17
17
  phone: '',
18
18
  hideCountdownSection: false,
19
19
  breakpoint: 1024,
20
+ client: 'desktop',
20
21
  initialScreenHintSlot: null,
21
22
  onTempBlockFinished: mockFn,
22
23
  onInputFinished: mockFn,
package/src/types.ts CHANGED
@@ -97,12 +97,12 @@ export type ConfirmationProps = {
97
97
  onTempBlockFinished?: () => void;
98
98
 
99
99
  /**
100
- * Возввращает объект, где ключ - название экрана (screen), значение - компонент для экрана
100
+ * Возвращает объект, где ключ - название экрана (screen), значение - компонент для экрана
101
101
  */
102
- getScreensMap?: (defaulScreensMap: ScreensMap) => ScreensMap;
102
+ getScreensMap?: (defaultScreensMap: ScreensMap) => ScreensMap;
103
103
 
104
104
  /**
105
- * Дочерние элементы.
105
+ * Дочерние элементы
106
106
  */
107
107
  children?: ReactNode;
108
108
 
@@ -123,6 +123,11 @@ export type ConfirmationProps = {
123
123
  */
124
124
  breakpoint?: number;
125
125
 
126
+ /**
127
+ * Версия, которая будет использоваться при серверном рендеринге
128
+ */
129
+ client?: 'desktop' | 'mobile';
130
+
126
131
  /**
127
132
  * Продолжительность отображения ошибки
128
133
  * @default 1300
@@ -156,14 +161,10 @@ export type TConfirmationContext = Required<
156
161
  | 'clearCodeOnError'
157
162
  | 'initialScreenHintSlot'
158
163
  | 'errorVisibleDuration'
164
+ | 'breakpoint'
165
+ | 'client'
159
166
  > & {
160
167
  timeLeft: number;
161
- } & {
162
- /**
163
- * Контрольная точка для кнопки, с нее начинается desktop версия
164
- * @default 1024
165
- */
166
- breakpoint?: number;
167
168
  };
168
169
 
169
170
  export type ConfirmationTexts = {
@@ -184,7 +185,8 @@ export type ConfirmationTexts = {
184
185
  * Экран HINT
185
186
  */
186
187
  hintButton?: string; // кнопка 'Вернуться'
187
-
188
+ domesticPhone?: string; // номер телефона для звонков по России
189
+ internationalPhone?: string; // номер телефона для звонков из-за границы
188
190
  /**
189
191
  * Экран FATAL_ERROR
190
192
  */
@@ -215,7 +217,7 @@ export type ScreensMap = {
215
217
  [key: string]: ComponentType;
216
218
  };
217
219
 
218
- export const defaultTexts = {
220
+ export const defaultTexts: ConfirmationTexts = {
219
221
  title: 'Введите код из\xa0сообщения',
220
222
  codeError: 'Код введён неверно',
221
223
  codeChecking: '',
@@ -232,4 +234,6 @@ export const defaultTexts = {
232
234
  tempBlockDescription: 'Повторное подтверждение кодом будет возможно через 24\xa0часа',
233
235
  codeSended: 'Код выслан',
234
236
  countdown: 'Запросить повторно можно через',
237
+ domesticPhone: '8 800 200 00 00',
238
+ internationalPhone: '+7 495 78 888 78',
235
239
  };
package/src/utils.ts CHANGED
@@ -105,3 +105,12 @@ export const useConfirmation = ({ state, screen, blockSmsRetry }: UseConfirmatio
105
105
  setConfirmationBlockSmsRetry,
106
106
  };
107
107
  };
108
+
109
+ const NON_NUMBER_OR_PLUS_REGEXP = new RegExp(/[^\d+]/g);
110
+
111
+ /**
112
+ * @returns ссылку для набора номера
113
+ */
114
+ export function getPhoneHref(phone: string): string {
115
+ return `tel:${phone.replace(NON_NUMBER_OR_PLUS_REGEXP, '')}`;
116
+ }
package/types.d.ts CHANGED
@@ -77,11 +77,11 @@ type ConfirmationProps = {
77
77
  */
78
78
  onTempBlockFinished?: () => void;
79
79
  /**
80
- * Возввращает объект, где ключ - название экрана (screen), значение - компонент для экрана
80
+ * Возвращает объект, где ключ - название экрана (screen), значение - компонент для экрана
81
81
  */
82
- getScreensMap?: (defaulScreensMap: ScreensMap) => ScreensMap;
82
+ getScreensMap?: (defaultScreensMap: ScreensMap) => ScreensMap;
83
83
  /**
84
- * Дочерние элементы.
84
+ * Дочерние элементы
85
85
  */
86
86
  children?: ReactNode;
87
87
  /**
@@ -98,20 +98,18 @@ type ConfirmationProps = {
98
98
  * @default 1024
99
99
  */
100
100
  breakpoint?: number;
101
+ /**
102
+ * Версия, которая будет использоваться при серверном рендеринге
103
+ */
104
+ client?: 'desktop' | 'mobile';
101
105
  /**
102
106
  * Продолжительность отображения ошибки
103
107
  * @default 1300
104
108
  */
105
109
  errorVisibleDuration?: number;
106
110
  };
107
- type TConfirmationContext = Required<Pick<ConfirmationProps, 'alignContent' | 'texts' | 'state' | 'screen' | 'requiredCharAmount' | 'onInputFinished' | 'countdownDuration' | 'onChangeState' | 'onSmsRetryClick' | 'onChangeScreen' | 'onFatalErrorOkButtonClick' | 'tempBlockDuration' | 'hideCountdownSection'>> & Pick<ConfirmationProps, 'phone' | 'blockSmsRetry' | 'onTempBlockFinished' | 'clearCodeOnError' | 'initialScreenHintSlot' | 'errorVisibleDuration'> & {
111
+ type TConfirmationContext = Required<Pick<ConfirmationProps, 'alignContent' | 'texts' | 'state' | 'screen' | 'requiredCharAmount' | 'onInputFinished' | 'countdownDuration' | 'onChangeState' | 'onSmsRetryClick' | 'onChangeScreen' | 'onFatalErrorOkButtonClick' | 'tempBlockDuration' | 'hideCountdownSection'>> & Pick<ConfirmationProps, 'phone' | 'blockSmsRetry' | 'onTempBlockFinished' | 'clearCodeOnError' | 'initialScreenHintSlot' | 'errorVisibleDuration' | 'breakpoint' | 'client'> & {
108
112
  timeLeft: number;
109
- } & {
110
- /**
111
- * Контрольная точка для кнопки, с нее начинается desktop версия
112
- * @default 1024
113
- */
114
- breakpoint?: number;
115
113
  };
116
114
  type ConfirmationTexts = {
117
115
  /**
@@ -130,6 +128,8 @@ type ConfirmationTexts = {
130
128
  * Экран HINT
131
129
  */
132
130
  hintButton?: string;
131
+ domesticPhone?: string;
132
+ internationalPhone?: string;
133
133
  /**
134
134
  * Экран FATAL_ERROR
135
135
  */
@@ -147,21 +147,5 @@ type ConfirmationState = 'INITIAL' | 'CODE_CHECKING' | 'CODE_SENDING' | 'CODE_ER
147
147
  type ScreensMap = {
148
148
  [key: string]: ComponentType;
149
149
  };
150
- declare const defaultTexts: {
151
- title: string;
152
- codeError: string;
153
- codeChecking: string;
154
- codeSending: string;
155
- buttonRetry: string;
156
- linkToHint: string;
157
- hintButton: string;
158
- noAttemptsLeft: string;
159
- fatalErrorTitle: string;
160
- fatalErrorDescription: string;
161
- fatalErrorButton: string;
162
- tempBlockTitle: string;
163
- tempBlockDescription: string;
164
- codeSended: string;
165
- countdown: string;
166
- };
150
+ declare const defaultTexts: ConfirmationTexts;
167
151
  export { ConfirmationProps, TConfirmationContext, ConfirmationTexts, ConfirmationScreen, ConfirmationState, ScreensMap, defaultTexts };