@snack-uikit/toaster 0.8.15 → 0.8.17-preview-bc9ca5dd.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 (125) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +9 -3
  3. package/dist/cjs/components/ToastSystemEvent/styles.module.css +2 -3
  4. package/dist/cjs/components/ToastUpload/ToastUpload.d.ts +60 -0
  5. package/dist/cjs/components/ToastUpload/ToastUpload.js +122 -0
  6. package/dist/cjs/components/ToastUpload/ToastUploadToaster.d.ts +3 -0
  7. package/dist/cjs/components/ToastUpload/ToastUploadToaster.js +16 -0
  8. package/dist/cjs/components/ToastUpload/constants.d.ts +16 -0
  9. package/dist/cjs/components/ToastUpload/constants.js +26 -0
  10. package/dist/cjs/components/ToastUpload/helperComponents/ButtonIcon/ButtonIcon.d.ts +3 -0
  11. package/dist/cjs/components/ToastUpload/helperComponents/ButtonIcon/ButtonIcon.js +32 -0
  12. package/dist/cjs/components/ToastUpload/helperComponents/ButtonIcon/index.d.ts +1 -0
  13. package/dist/cjs/components/ToastUpload/helperComponents/ButtonIcon/index.js +25 -0
  14. package/dist/cjs/components/ToastUpload/helperComponents/ButtonIcon/styles.module.css +30 -0
  15. package/dist/cjs/components/ToastUpload/helperComponents/FileItem/FileItem.d.ts +5 -0
  16. package/dist/cjs/components/ToastUpload/helperComponents/FileItem/FileItem.js +85 -0
  17. package/dist/cjs/components/ToastUpload/helperComponents/FileItem/index.d.ts +1 -0
  18. package/dist/cjs/components/ToastUpload/helperComponents/FileItem/index.js +25 -0
  19. package/dist/cjs/components/ToastUpload/helperComponents/FileItem/styles.module.css +85 -0
  20. package/dist/cjs/components/ToastUpload/helperComponents/LoadingStatus/LoadingStatus.d.ts +6 -0
  21. package/dist/cjs/components/ToastUpload/helperComponents/LoadingStatus/LoadingStatus.js +42 -0
  22. package/dist/cjs/components/ToastUpload/helperComponents/LoadingStatus/index.d.ts +1 -0
  23. package/dist/cjs/components/ToastUpload/helperComponents/LoadingStatus/index.js +25 -0
  24. package/dist/cjs/components/ToastUpload/helperComponents/LoadingStatus/styles.module.css +3 -0
  25. package/dist/cjs/components/ToastUpload/index.d.ts +1 -0
  26. package/dist/cjs/components/ToastUpload/index.js +25 -0
  27. package/dist/cjs/components/ToastUpload/styles.module.css +110 -0
  28. package/dist/cjs/components/ToastUpload/types.d.ts +59 -0
  29. package/dist/cjs/components/ToastUpload/types.js +5 -0
  30. package/dist/cjs/components/ToastUpload/utils/formatPercent.d.ts +1 -0
  31. package/dist/cjs/components/ToastUpload/utils/formatPercent.js +8 -0
  32. package/dist/cjs/components/ToastUpload/utils/index.d.ts +1 -0
  33. package/dist/cjs/components/ToastUpload/utils/index.js +25 -0
  34. package/dist/cjs/components/ToasterContainer/styles.module.css +9 -9
  35. package/dist/cjs/components/index.d.ts +1 -0
  36. package/dist/cjs/components/index.js +2 -1
  37. package/dist/cjs/constants.d.ts +10 -5
  38. package/dist/cjs/constants.js +77 -4
  39. package/dist/cjs/helperComponents/ButtonAction/styles.module.css +2 -2
  40. package/dist/cjs/helperComponents/ButtonTextNeutral/ButtonTextNeutral.d.ts +7 -0
  41. package/dist/cjs/helperComponents/ButtonTextNeutral/ButtonTextNeutral.js +28 -0
  42. package/dist/cjs/helperComponents/ButtonTextNeutral/index.d.ts +1 -0
  43. package/dist/cjs/helperComponents/ButtonTextNeutral/index.js +25 -0
  44. package/dist/cjs/helperComponents/ButtonTextNeutral/styles.module.css +32 -0
  45. package/dist/cjs/helpers.js +43 -1
  46. package/dist/cjs/index.d.ts +2 -2
  47. package/dist/cjs/testIds.d.ts +14 -0
  48. package/dist/cjs/testIds.js +16 -1
  49. package/dist/cjs/types.d.ts +9 -1
  50. package/dist/esm/components/ToastSystemEvent/styles.module.css +2 -3
  51. package/dist/esm/components/ToastUpload/ToastUpload.d.ts +60 -0
  52. package/dist/esm/components/ToastUpload/ToastUpload.js +36 -0
  53. package/dist/esm/components/ToastUpload/ToastUploadToaster.d.ts +3 -0
  54. package/dist/esm/components/ToastUpload/ToastUploadToaster.js +7 -0
  55. package/dist/esm/components/ToastUpload/constants.d.ts +16 -0
  56. package/dist/esm/components/ToastUpload/constants.js +20 -0
  57. package/dist/esm/components/ToastUpload/helperComponents/ButtonIcon/ButtonIcon.d.ts +3 -0
  58. package/dist/esm/components/ToastUpload/helperComponents/ButtonIcon/ButtonIcon.js +18 -0
  59. package/dist/esm/components/ToastUpload/helperComponents/ButtonIcon/index.d.ts +1 -0
  60. package/dist/esm/components/ToastUpload/helperComponents/ButtonIcon/index.js +1 -0
  61. package/dist/esm/components/ToastUpload/helperComponents/ButtonIcon/styles.module.css +30 -0
  62. package/dist/esm/components/ToastUpload/helperComponents/FileItem/FileItem.d.ts +5 -0
  63. package/dist/esm/components/ToastUpload/helperComponents/FileItem/FileItem.js +23 -0
  64. package/dist/esm/components/ToastUpload/helperComponents/FileItem/index.d.ts +1 -0
  65. package/dist/esm/components/ToastUpload/helperComponents/FileItem/index.js +1 -0
  66. package/dist/esm/components/ToastUpload/helperComponents/FileItem/styles.module.css +85 -0
  67. package/dist/esm/components/ToastUpload/helperComponents/LoadingStatus/LoadingStatus.d.ts +6 -0
  68. package/dist/esm/components/ToastUpload/helperComponents/LoadingStatus/LoadingStatus.js +16 -0
  69. package/dist/esm/components/ToastUpload/helperComponents/LoadingStatus/index.d.ts +1 -0
  70. package/dist/esm/components/ToastUpload/helperComponents/LoadingStatus/index.js +1 -0
  71. package/dist/esm/components/ToastUpload/helperComponents/LoadingStatus/styles.module.css +3 -0
  72. package/dist/esm/components/ToastUpload/index.d.ts +1 -0
  73. package/dist/esm/components/ToastUpload/index.js +1 -0
  74. package/dist/esm/components/ToastUpload/styles.module.css +110 -0
  75. package/dist/esm/components/ToastUpload/types.d.ts +59 -0
  76. package/dist/esm/components/ToastUpload/types.js +1 -0
  77. package/dist/esm/components/ToastUpload/utils/formatPercent.d.ts +1 -0
  78. package/dist/esm/components/ToastUpload/utils/formatPercent.js +1 -0
  79. package/dist/esm/components/ToastUpload/utils/index.d.ts +1 -0
  80. package/dist/esm/components/ToastUpload/utils/index.js +1 -0
  81. package/dist/esm/components/ToasterContainer/styles.module.css +9 -9
  82. package/dist/esm/components/index.d.ts +1 -0
  83. package/dist/esm/components/index.js +1 -0
  84. package/dist/esm/constants.d.ts +10 -5
  85. package/dist/esm/constants.js +76 -0
  86. package/dist/esm/helperComponents/ButtonAction/styles.module.css +2 -2
  87. package/dist/esm/helperComponents/ButtonTextNeutral/ButtonTextNeutral.d.ts +7 -0
  88. package/dist/esm/helperComponents/ButtonTextNeutral/ButtonTextNeutral.js +5 -0
  89. package/dist/esm/helperComponents/ButtonTextNeutral/index.d.ts +1 -0
  90. package/dist/esm/helperComponents/ButtonTextNeutral/index.js +1 -0
  91. package/dist/esm/helperComponents/ButtonTextNeutral/styles.module.css +32 -0
  92. package/dist/esm/helpers.js +38 -0
  93. package/dist/esm/index.d.ts +2 -2
  94. package/dist/esm/testIds.d.ts +14 -0
  95. package/dist/esm/testIds.js +15 -0
  96. package/dist/esm/types.d.ts +9 -1
  97. package/package.json +6 -5
  98. package/src/components/ToastSystemEvent/styles.module.scss +2 -2
  99. package/src/components/ToastUpload/ToastUpload.tsx +169 -0
  100. package/src/components/ToastUpload/ToastUploadToaster.tsx +11 -0
  101. package/src/components/ToastUpload/constants.ts +26 -0
  102. package/src/components/ToastUpload/helperComponents/ButtonIcon/ButtonIcon.tsx +10 -0
  103. package/src/components/ToastUpload/helperComponents/ButtonIcon/index.ts +1 -0
  104. package/src/components/ToastUpload/helperComponents/ButtonIcon/styles.module.scss +45 -0
  105. package/src/components/ToastUpload/helperComponents/FileItem/FileItem.tsx +76 -0
  106. package/src/components/ToastUpload/helperComponents/FileItem/index.ts +1 -0
  107. package/src/components/ToastUpload/helperComponents/FileItem/styles.module.scss +93 -0
  108. package/src/components/ToastUpload/helperComponents/LoadingStatus/LoadingStatus.tsx +38 -0
  109. package/src/components/ToastUpload/helperComponents/LoadingStatus/index.ts +1 -0
  110. package/src/components/ToastUpload/helperComponents/LoadingStatus/styles.module.scss +8 -0
  111. package/src/components/ToastUpload/index.ts +1 -0
  112. package/src/components/ToastUpload/styles.module.scss +123 -0
  113. package/src/components/ToastUpload/types.ts +67 -0
  114. package/src/components/ToastUpload/utils/formatPercent.ts +1 -0
  115. package/src/components/ToastUpload/utils/index.ts +1 -0
  116. package/src/components/ToasterContainer/styles.module.scss +1 -1
  117. package/src/components/index.ts +1 -0
  118. package/src/constants.ts +91 -2
  119. package/src/helperComponents/ButtonTextNeutral/ButtonTextNeutral.tsx +23 -0
  120. package/src/helperComponents/ButtonTextNeutral/index.ts +1 -0
  121. package/src/helperComponents/ButtonTextNeutral/styles.module.scss +42 -0
  122. package/src/helpers.tsx +35 -0
  123. package/src/index.ts +7 -1
  124. package/src/testIds.ts +17 -0
  125. package/src/types.ts +7 -1
@@ -0,0 +1,169 @@
1
+ import cn from 'classnames';
2
+ import { MouseEvent } from 'react';
3
+ import { ToastContentProps as RtToastContentProps } from 'react-toastify';
4
+
5
+ import { ChevronDownSVG, ChevronUpSVG, CrossSVG } from '@snack-uikit/icons';
6
+ import { ProgressBar } from '@snack-uikit/progress-bar';
7
+ import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
8
+
9
+ import { ButtonTextNeutral, ButtonTextNeutralProps } from '../../helperComponents/ButtonTextNeutral';
10
+ import { TOAST_UPLOAD_TEST_IDS } from '../../testIds';
11
+ import { progressBarAppearanceByStatus } from './constants';
12
+ import { ButtonIcon } from './helperComponents/ButtonIcon';
13
+ import { FileItem } from './helperComponents/FileItem';
14
+ import { LoadingStatus } from './helperComponents/LoadingStatus';
15
+ import styles from './styles.module.scss';
16
+ import { ToastUploadStatus, UploadActions, UploadItem } from './types';
17
+ import { formatPercent } from './utils';
18
+
19
+ export type ToastUploadProps = Partial<RtToastContentProps> &
20
+ WithSupportProps<{
21
+ /**
22
+ * Общий статус загрузки
23
+ */
24
+ status: ToastUploadStatus;
25
+ /**
26
+ * Заголовок тостера
27
+ */
28
+ title: string;
29
+ /**
30
+ * Описание статуса загрузки
31
+ */
32
+ description: string;
33
+ /**
34
+ * Каунтер общего прогресса
35
+ */
36
+ totalProgressCounter: string;
37
+ /**
38
+ * Процент прогресса
39
+ */
40
+ totalProgressPercentage: number;
41
+ /**
42
+ * Закрыть тостер
43
+ */
44
+ onCloseClick?(e: MouseEvent<HTMLButtonElement>, close?: () => void): void;
45
+ /**
46
+ * Показывать кнопку закрытия тостера
47
+ */
48
+ closable?: boolean;
49
+ /**
50
+ * CSS-класс контейнера
51
+ */
52
+ className?: string;
53
+ /**
54
+ * Загружаемые элементы
55
+ */
56
+ items: UploadItem[];
57
+ /**
58
+ * Тостер свернут/развернут
59
+ */
60
+ collapsed: boolean;
61
+ /**
62
+ * Развернуть/свернуть тостер
63
+ */
64
+ onCollapsed: (collapsed: boolean) => void;
65
+ /**
66
+ * Экшены для управления загрузкой
67
+ */
68
+ generalActions: UploadActions;
69
+ /**
70
+ * Отмена всей загрузки
71
+ */
72
+ cancelButton?: ButtonTextNeutralProps;
73
+ }>;
74
+
75
+ export function ToastUpload({
76
+ status,
77
+ title,
78
+ description,
79
+ totalProgressCounter,
80
+ totalProgressPercentage,
81
+ closeToast,
82
+ onCloseClick,
83
+ closable,
84
+ className,
85
+ items,
86
+ collapsed,
87
+ onCollapsed,
88
+ generalActions,
89
+ cancelButton,
90
+ ...rest
91
+ }: ToastUploadProps) {
92
+ const handleCloseClick = (e: MouseEvent<HTMLButtonElement>) => {
93
+ e.stopPropagation();
94
+ onCloseClick ? onCloseClick(e, closeToast) : closeToast?.();
95
+ };
96
+
97
+ const handleCollapseClick = (e: MouseEvent<HTMLButtonElement>) => {
98
+ e.stopPropagation();
99
+ onCollapsed(!collapsed);
100
+ };
101
+
102
+ return (
103
+ <div className={cn(styles.container, className)} {...extractSupportProps(rest)} data-collapsed={collapsed}>
104
+ <div className={styles.titleLine}>
105
+ <div className={styles.titleLineBody}>
106
+ <div className={styles.title} data-test-id={TOAST_UPLOAD_TEST_IDS.title}>
107
+ {title}
108
+ </div>
109
+
110
+ {cancelButton && <ButtonTextNeutral {...cancelButton} />}
111
+
112
+ <ButtonIcon onClick={handleCollapseClick} data-test-id={TOAST_UPLOAD_TEST_IDS.collapseButton}>
113
+ {collapsed ? <ChevronUpSVG /> : <ChevronDownSVG />}
114
+ </ButtonIcon>
115
+
116
+ {closable && (
117
+ <ButtonIcon
118
+ type='button'
119
+ className={styles.buttonAction}
120
+ onClick={handleCloseClick}
121
+ data-test-id={TOAST_UPLOAD_TEST_IDS.close}
122
+ >
123
+ <CrossSVG />
124
+ </ButtonIcon>
125
+ )}
126
+ </div>
127
+
128
+ <div className={styles.generalProgress}>
129
+ <div className={styles.statusLine}>
130
+ <div className={styles.statusWrap}>
131
+ <LoadingStatus status={status} actions={generalActions} />
132
+
133
+ <span
134
+ className={styles.description}
135
+ data-status={status}
136
+ data-test-id={TOAST_UPLOAD_TEST_IDS.description}
137
+ >
138
+ {description}
139
+ </span>
140
+ </div>
141
+
142
+ <span className={styles.totalCounter} data-test-id={TOAST_UPLOAD_TEST_IDS.counter}>
143
+ {totalProgressCounter}
144
+ </span>
145
+
146
+ <span className={styles.totalPercentage} data-test-id={TOAST_UPLOAD_TEST_IDS.progress}>
147
+ {formatPercent(totalProgressPercentage)}
148
+ </span>
149
+ </div>
150
+
151
+ {!collapsed && (
152
+ <ProgressBar
153
+ progress={totalProgressPercentage}
154
+ size='xs'
155
+ appearance={progressBarAppearanceByStatus[status]}
156
+ data-test-id={TOAST_UPLOAD_TEST_IDS.progressBar}
157
+ />
158
+ )}
159
+ </div>
160
+ </div>
161
+
162
+ <div className={styles.list} data-collapsed={collapsed} data-test-id={TOAST_UPLOAD_TEST_IDS.list}>
163
+ {items.map(item => (
164
+ <FileItem key={item.id} item={item} />
165
+ ))}
166
+ </div>
167
+ </div>
168
+ );
169
+ }
@@ -0,0 +1,11 @@
1
+ import { useState } from 'react';
2
+
3
+ import { ToastUpload, ToastUploadProps } from './ToastUpload';
4
+
5
+ export type ToastUploadToasterProps = Omit<ToastUploadProps, 'collapsed' | 'onCollapsed'>;
6
+
7
+ export function ToastUploadForToaster(props: ToastUploadToasterProps) {
8
+ const [collapsed, setCollapsed] = useState(true);
9
+
10
+ return <ToastUpload {...props} collapsed={collapsed} onCollapsed={setCollapsed} />;
11
+ }
@@ -0,0 +1,26 @@
1
+ import { ProgressBarProps } from '@snack-uikit/progress-bar';
2
+
3
+ import { ToastUploadStatus } from './types';
4
+
5
+ export const TOAST_UPLOAD_STATUS = {
6
+ Loading: 'loading',
7
+ Pause: 'pause',
8
+ Error: 'error',
9
+ Uploaded: 'uploaded',
10
+ ErrorUploaded: 'errorUploaded',
11
+ } as const;
12
+
13
+ export const TOAST_UPLOAD_ITEM_STATUS = {
14
+ Loading: 'loading',
15
+ Pause: 'pause',
16
+ Error: 'error',
17
+ Uploaded: 'uploaded',
18
+ } as const;
19
+
20
+ export const progressBarAppearanceByStatus: Record<ToastUploadStatus, ProgressBarProps['appearance']> = {
21
+ pause: 'neutral',
22
+ loading: 'green',
23
+ uploaded: 'green',
24
+ errorUploaded: 'red',
25
+ error: 'red',
26
+ };
@@ -0,0 +1,10 @@
1
+ import cn from 'classnames';
2
+ import { ButtonHTMLAttributes } from 'react';
3
+
4
+ import styles from './styles.module.scss';
5
+
6
+ export type ButtonIconProps = ButtonHTMLAttributes<HTMLButtonElement>;
7
+
8
+ export function ButtonIcon({ className, ...props }: ButtonIconProps) {
9
+ return <button type='button' className={cn(styles.buttonIcon, className)} {...props}></button>;
10
+ }
@@ -0,0 +1 @@
1
+ export * from './ButtonIcon';
@@ -0,0 +1,45 @@
1
+ /* stylelint-disable scss/operator-no-newline-after */
2
+
3
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-toaster-toasterSystemEvent';
4
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-toaster-toasterUpload';
5
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-element';
6
+ @use '@snack-uikit/figma-tokens/build/scss/styles-theme-variables';
7
+
8
+ .buttonIcon {
9
+ cursor: pointer;
10
+
11
+ display: flex;
12
+ align-items: center;
13
+ justify-content: center;
14
+
15
+ box-sizing: border-box;
16
+ margin: 0;
17
+ padding: 0;
18
+
19
+ color: styles-theme-variables.$sys-invert-neutral-text-light;
20
+
21
+ background-color: transparent;
22
+ border: none;
23
+
24
+ svg {
25
+ width: styles-tokens-element.$icon-s !important; /* stylelint-disable-line declaration-no-important */
26
+ height: styles-tokens-element.$icon-s !important; /* stylelint-disable-line declaration-no-important */
27
+ }
28
+
29
+ &:hover {
30
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
31
+ }
32
+
33
+ &:focus,
34
+ &:active {
35
+ color: styles-theme-variables.$sys-invert-neutral-accent-pressed;
36
+ }
37
+
38
+ &:focus-visible {
39
+ @include styles-theme-variables.outline-var(styles-tokens-element.$container-focused-s);
40
+
41
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
42
+ outline-color: styles-theme-variables.$sys-available-on-complementary;
43
+ outline-offset: styles-theme-variables.$spacing-state-focus-offset;
44
+ }
45
+ }
@@ -0,0 +1,76 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ import { CrossSVG } from '@snack-uikit/icons';
4
+ import { Link } from '@snack-uikit/link';
5
+ import { ProgressBar } from '@snack-uikit/progress-bar';
6
+
7
+ import { TOAST_UPLOAD_TEST_IDS } from '../../../../testIds';
8
+ import { progressBarAppearanceByStatus } from '../../constants';
9
+ import { UploadItem } from '../../types';
10
+ import { formatPercent } from '../../utils';
11
+ import { ButtonIcon } from '../ButtonIcon';
12
+ import { LoadingStatus } from '../LoadingStatus';
13
+ import styles from './styles.module.scss';
14
+
15
+ export type FileItemProps = { item: UploadItem };
16
+
17
+ export function FileItem({ item: initItem }: FileItemProps) {
18
+ const [item, setItem] = useState(initItem);
19
+
20
+ const showLink = item.status === 'uploaded' && item.link;
21
+
22
+ useEffect(() => {
23
+ if (initItem.subscribeToState) {
24
+ return initItem.subscribeToState(newValue => setItem(prev => ({ ...prev, ...newValue })));
25
+ }
26
+
27
+ return setItem(initItem);
28
+ }, [initItem]);
29
+
30
+ return (
31
+ <div className={styles.fileLine} key={item.id} data-test-id={TOAST_UPLOAD_TEST_IDS.uploadItem}>
32
+ <div className={styles.fileHeadLine}>
33
+ <span className={styles.fileTitle}>{item.title}</span>
34
+
35
+ {showLink && (
36
+ <Link
37
+ text={item.link?.text}
38
+ href={item.link?.href}
39
+ size='m'
40
+ truncateVariant='end'
41
+ onClick={item.link?.onClick}
42
+ appearance='invert-neutral'
43
+ textMode='accent'
44
+ data-test-id={TOAST_UPLOAD_TEST_IDS.uploadItemLink}
45
+ />
46
+ )}
47
+
48
+ {!showLink && (
49
+ <ButtonIcon onClick={item.actions.onCancel} data-test-id={TOAST_UPLOAD_TEST_IDS.uploadItemCancel}>
50
+ <CrossSVG />
51
+ </ButtonIcon>
52
+ )}
53
+ </div>
54
+
55
+ <ProgressBar progress={item.progress} size='xs' appearance={progressBarAppearanceByStatus[item.status]} />
56
+
57
+ <div className={styles.fileStatusLine}>
58
+ <div className={styles.fileStatusWrap}>
59
+ <LoadingStatus status={item.status} actions={item.actions} />
60
+
61
+ <span className={styles.fileStatusDescription} data-status={item.status}>
62
+ {item.statusLabel}
63
+ </span>
64
+ </div>
65
+
66
+ <span className={styles.fileSize} data-status={item.status}>
67
+ {item.size}
68
+ </span>
69
+
70
+ <span className={styles.fileStatusPercentage} data-status={item.status}>
71
+ {formatPercent(item.progress)}
72
+ </span>
73
+ </div>
74
+ </div>
75
+ );
76
+ }
@@ -0,0 +1 @@
1
+ export * from './FileItem';
@@ -0,0 +1,93 @@
1
+ /* stylelint-disable scss/operator-no-newline-after */
2
+
3
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-toaster-toasterSystemEvent';
4
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-toaster-toasterUpload';
5
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-element';
6
+ @use '@snack-uikit/figma-tokens/build/scss/styles-theme-variables';
7
+
8
+ .fileLine {
9
+ @include styles-theme-variables.composite-var(
10
+ styles-tokens-toaster-toasterUpload.$toaster-upload-file-line-container
11
+ );
12
+
13
+ display: flex;
14
+ flex-direction: column;
15
+ }
16
+
17
+ .fileHeadLine {
18
+ @include styles-theme-variables.composite-var(
19
+ styles-tokens-toaster-toasterUpload.$toaster-upload-file-line-headline
20
+ );
21
+
22
+ display: flex;
23
+ align-items: center;
24
+ }
25
+
26
+ .fileTitle {
27
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-body-s);
28
+
29
+ flex-grow: 1;
30
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
31
+ }
32
+
33
+
34
+ .fileStatusLine {
35
+ @include styles-theme-variables.composite-var(
36
+ styles-tokens-toaster-toasterUpload.$toaster-upload-status-line-container
37
+ );
38
+
39
+ display: flex;
40
+ align-items: center;
41
+ }
42
+
43
+ .fileStatusWrap {
44
+ @include styles-theme-variables.composite-var(
45
+ styles-tokens-toaster-toasterUpload.$toaster-upload-status-line-status-wrap
46
+ );
47
+
48
+ display: flex;
49
+ flex-grow: 1;
50
+ align-items: center;
51
+ }
52
+
53
+ .fileStatusDescription {
54
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-body-s);
55
+
56
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
57
+
58
+ &[data-status='loading'] {
59
+ color: styles-theme-variables.$sys-invert-neutral-text-disabled;
60
+ }
61
+
62
+ &[data-status='uploaded'] {
63
+ color: styles-theme-variables.$sys-invert-neutral-text-disabled;
64
+ }
65
+ }
66
+
67
+ .fileSize {
68
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-body-s);
69
+
70
+ color: styles-theme-variables.$sys-invert-neutral-text-disabled;
71
+
72
+ &[data-status='loading'] {
73
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
74
+ }
75
+
76
+ &[data-status='uploaded'] {
77
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
78
+ }
79
+ }
80
+
81
+ .fileStatusPercentage {
82
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-body-s);
83
+
84
+ color: styles-theme-variables.$sys-invert-neutral-text-disabled;
85
+
86
+ &[data-status='loading'] {
87
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
88
+ }
89
+
90
+ &[data-status='uploaded'] {
91
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
92
+ }
93
+ }
@@ -0,0 +1,38 @@
1
+ import { CheckFilledSVG, PauseSVG, PlaySVG, UpdateSVG } from '@snack-uikit/icons';
2
+
3
+ import { ToastUploadStatus, UploadActions } from '../../types';
4
+ import { ButtonIcon } from '../ButtonIcon';
5
+ import styles from './styles.module.scss';
6
+
7
+ export type LoadingStatusProps = {
8
+ status: ToastUploadStatus;
9
+ actions: UploadActions;
10
+ };
11
+
12
+ export function LoadingStatus({ status, actions }: LoadingStatusProps) {
13
+ if (status === 'loading') {
14
+ return (
15
+ <ButtonIcon onClick={actions.onPause}>
16
+ <PauseSVG />
17
+ </ButtonIcon>
18
+ );
19
+ }
20
+
21
+ if (status === 'pause') {
22
+ return (
23
+ <ButtonIcon onClick={actions.onContinue}>
24
+ <PlaySVG />
25
+ </ButtonIcon>
26
+ );
27
+ }
28
+
29
+ if (status === 'uploaded') {
30
+ return <CheckFilledSVG className={styles.successIcon} />;
31
+ }
32
+
33
+ return (
34
+ <ButtonIcon onClick={actions.onRetry}>
35
+ <UpdateSVG />
36
+ </ButtonIcon>
37
+ );
38
+ }
@@ -0,0 +1 @@
1
+ export * from './LoadingStatus';
@@ -0,0 +1,8 @@
1
+ /* stylelint-disable scss/operator-no-newline-after */
2
+
3
+ @use '@snack-uikit/figma-tokens/build/scss/styles-theme-variables';
4
+
5
+
6
+ .successIcon {
7
+ color: styles-theme-variables.$sys-green-accent-default;
8
+ }
@@ -0,0 +1 @@
1
+ export * from './ToastUpload';
@@ -0,0 +1,123 @@
1
+ /* stylelint-disable scss/operator-no-newline-after */
2
+
3
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-toaster-toasterSystemEvent';
4
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-toaster-toasterUpload';
5
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-element';
6
+ @use '@snack-uikit/figma-tokens/build/scss/styles-theme-variables';
7
+
8
+ .container {
9
+ @include styles-theme-variables.composite-var(styles-tokens-toaster-toasterUpload.$toaster-upload-toast-container);
10
+
11
+ cursor: default;
12
+
13
+ position: relative;
14
+
15
+ overflow: hidden;
16
+ display: flex;
17
+ flex-direction: column;
18
+
19
+ box-sizing: border-box;
20
+ width: calc(
21
+ styles-tokens-toaster-toasterSystemEvent.$size-toaster-toast-system-event-container -
22
+ (2 * styles-tokens-toaster-toasterUpload.$space-toaster-toast-system-event-container-padding)
23
+ );
24
+ max-width: 100%;
25
+ max-height: 386px;
26
+ padding: styles-tokens-toaster-toasterUpload.$space-toaster-toast-system-event-container-padding 0;
27
+
28
+ background-color: styles-theme-variables.$sys-invert-neutral-background;
29
+
30
+ &[data-collapsed='false'] {
31
+ gap: 0;
32
+ }
33
+ }
34
+
35
+ .titleLine {
36
+ display: flex;
37
+ flex-direction: column;
38
+ padding: 0 styles-tokens-toaster-toasterUpload.$space-toaster-toast-system-event-container-padding;
39
+ }
40
+
41
+ .titleLineBody {
42
+ @include styles-theme-variables.composite-var(styles-tokens-toaster-toasterUpload.$toaster-upload-title-line-body);
43
+
44
+ display: flex;
45
+ align-items: center;
46
+ }
47
+
48
+ .title {
49
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-title-s);
50
+
51
+ flex-grow: 1;
52
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
53
+ }
54
+
55
+ .generalProgress {
56
+ @include styles-theme-variables.composite-var(
57
+ styles-tokens-toaster-toasterUpload.$toaster-upload-title-line-general-progress
58
+ );
59
+
60
+ display: flex;
61
+ flex-direction: column;
62
+ align-self: stretch;
63
+ }
64
+
65
+ .statusLine {
66
+ @include styles-theme-variables.composite-var(
67
+ styles-tokens-toaster-toasterUpload.$toaster-upload-status-line-container
68
+ );
69
+
70
+ display: flex;
71
+ align-items: center;
72
+ }
73
+
74
+ .statusWrap {
75
+ @include styles-theme-variables.composite-var(
76
+ styles-tokens-toaster-toasterUpload.$toaster-upload-status-line-status-wrap
77
+ );
78
+
79
+ display: flex;
80
+ flex-grow: 1;
81
+ align-items: center;
82
+ }
83
+
84
+ .description {
85
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-body-m);
86
+
87
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
88
+
89
+ &[data-status='loading'] {
90
+ color: styles-theme-variables.$sys-invert-neutral-text-light;
91
+ }
92
+
93
+ &[data-status='uploaded'] {
94
+ color: styles-theme-variables.$sys-invert-neutral-text-light;
95
+ }
96
+ }
97
+
98
+ .totalCounter {
99
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-body-m);
100
+
101
+ color: styles-theme-variables.$sys-invert-neutral-text-support;
102
+ }
103
+
104
+ .totalPercentage {
105
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-body-m);
106
+
107
+ color: styles-theme-variables.$sys-invert-neutral-text-support;
108
+ }
109
+
110
+ .list {
111
+ overflow: scroll;
112
+ display: flex;
113
+ flex-direction: column;
114
+
115
+ max-height: 280px;
116
+ padding: 0 styles-tokens-toaster-toasterUpload.$space-toaster-toast-system-event-container-padding;
117
+
118
+ transition: all 0.1s;
119
+
120
+ &[data-collapsed='false'] {
121
+ max-height: 0;
122
+ }
123
+ }
@@ -0,0 +1,67 @@
1
+ import { MouseEvent } from 'react';
2
+
3
+ import { ProgressBarProps } from '@snack-uikit/progress-bar';
4
+ import { ValueOf } from '@snack-uikit/utils';
5
+
6
+ import { TOAST_UPLOAD_ITEM_STATUS, TOAST_UPLOAD_STATUS } from './constants';
7
+
8
+ export type ToastUploadStatus = ValueOf<typeof TOAST_UPLOAD_STATUS>;
9
+
10
+ export type ToastUploadItemStatus = ValueOf<typeof TOAST_UPLOAD_ITEM_STATUS>;
11
+
12
+ export type ToastUploadStateSubscription<T> = (subscription: (newValue: T) => void) => () => void;
13
+ export type WithStateSubscription<T> = {
14
+ /**Позволяет подписываться на изменения процесса загрузки файла внутри конпонента,
15
+ * тем самым обновляет элементы не зависимо от всего списка
16
+ * (можно использовать для улучшения производительности из-за частых обновлений)
17
+ */
18
+ subscribeToState?: ToastUploadStateSubscription<Partial<T>>;
19
+ } & T;
20
+
21
+ export type ToastUploadItemLink = {
22
+ text: string;
23
+ href: string;
24
+ onClick?(e: MouseEvent<HTMLAnchorElement>): void;
25
+ };
26
+
27
+ export type UploadActions = {
28
+ onCancel?: () => void;
29
+ onPause?: () => void;
30
+ onRetry?: () => void;
31
+ onContinue?: () => void;
32
+ };
33
+
34
+ export type UploadItem = WithStateSubscription<{
35
+ /**
36
+ * Уникальный id элемента
37
+ */
38
+ id: string;
39
+ /**
40
+ * Название элемента
41
+ */
42
+ title: string;
43
+ /**
44
+ * Статус загрузки
45
+ */
46
+ status: ToastUploadItemStatus;
47
+ /**
48
+ * Описание статуса загрузки
49
+ */
50
+ statusLabel: string;
51
+ /**
52
+ * Процент прогресса
53
+ */
54
+ progress: ProgressBarProps['progress'];
55
+ /**
56
+ * Размер файла
57
+ */
58
+ size: string;
59
+ /**
60
+ * Экшены для управления загрузкой
61
+ */
62
+ actions: UploadActions;
63
+ /**
64
+ * Ссылка на файл
65
+ */
66
+ link?: ToastUploadItemLink;
67
+ }>;
@@ -0,0 +1 @@
1
+ export const formatPercent = (value: number) => `${value}%`;
@@ -0,0 +1 @@
1
+ export * from './formatPercent';