@snack-uikit/toaster 0.8.16 → 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 (124) hide show
  1. package/README.md +9 -3
  2. package/dist/cjs/components/ToastSystemEvent/styles.module.css +2 -3
  3. package/dist/cjs/components/ToastUpload/ToastUpload.d.ts +60 -0
  4. package/dist/cjs/components/ToastUpload/ToastUpload.js +122 -0
  5. package/dist/cjs/components/ToastUpload/ToastUploadToaster.d.ts +3 -0
  6. package/dist/cjs/components/ToastUpload/ToastUploadToaster.js +16 -0
  7. package/dist/cjs/components/ToastUpload/constants.d.ts +16 -0
  8. package/dist/cjs/components/ToastUpload/constants.js +26 -0
  9. package/dist/cjs/components/ToastUpload/helperComponents/ButtonIcon/ButtonIcon.d.ts +3 -0
  10. package/dist/cjs/components/ToastUpload/helperComponents/ButtonIcon/ButtonIcon.js +32 -0
  11. package/dist/cjs/components/ToastUpload/helperComponents/ButtonIcon/index.d.ts +1 -0
  12. package/dist/cjs/components/ToastUpload/helperComponents/ButtonIcon/index.js +25 -0
  13. package/dist/cjs/components/ToastUpload/helperComponents/ButtonIcon/styles.module.css +30 -0
  14. package/dist/cjs/components/ToastUpload/helperComponents/FileItem/FileItem.d.ts +5 -0
  15. package/dist/cjs/components/ToastUpload/helperComponents/FileItem/FileItem.js +85 -0
  16. package/dist/cjs/components/ToastUpload/helperComponents/FileItem/index.d.ts +1 -0
  17. package/dist/cjs/components/ToastUpload/helperComponents/FileItem/index.js +25 -0
  18. package/dist/cjs/components/ToastUpload/helperComponents/FileItem/styles.module.css +85 -0
  19. package/dist/cjs/components/ToastUpload/helperComponents/LoadingStatus/LoadingStatus.d.ts +6 -0
  20. package/dist/cjs/components/ToastUpload/helperComponents/LoadingStatus/LoadingStatus.js +42 -0
  21. package/dist/cjs/components/ToastUpload/helperComponents/LoadingStatus/index.d.ts +1 -0
  22. package/dist/cjs/components/ToastUpload/helperComponents/LoadingStatus/index.js +25 -0
  23. package/dist/cjs/components/ToastUpload/helperComponents/LoadingStatus/styles.module.css +3 -0
  24. package/dist/cjs/components/ToastUpload/index.d.ts +1 -0
  25. package/dist/cjs/components/ToastUpload/index.js +25 -0
  26. package/dist/cjs/components/ToastUpload/styles.module.css +110 -0
  27. package/dist/cjs/components/ToastUpload/types.d.ts +59 -0
  28. package/dist/cjs/components/ToastUpload/types.js +5 -0
  29. package/dist/cjs/components/ToastUpload/utils/formatPercent.d.ts +1 -0
  30. package/dist/cjs/components/ToastUpload/utils/formatPercent.js +8 -0
  31. package/dist/cjs/components/ToastUpload/utils/index.d.ts +1 -0
  32. package/dist/cjs/components/ToastUpload/utils/index.js +25 -0
  33. package/dist/cjs/components/ToasterContainer/styles.module.css +9 -9
  34. package/dist/cjs/components/index.d.ts +1 -0
  35. package/dist/cjs/components/index.js +2 -1
  36. package/dist/cjs/constants.d.ts +10 -5
  37. package/dist/cjs/constants.js +77 -4
  38. package/dist/cjs/helperComponents/ButtonAction/styles.module.css +2 -2
  39. package/dist/cjs/helperComponents/ButtonTextNeutral/ButtonTextNeutral.d.ts +7 -0
  40. package/dist/cjs/helperComponents/ButtonTextNeutral/ButtonTextNeutral.js +28 -0
  41. package/dist/cjs/helperComponents/ButtonTextNeutral/index.d.ts +1 -0
  42. package/dist/cjs/helperComponents/ButtonTextNeutral/index.js +25 -0
  43. package/dist/cjs/helperComponents/ButtonTextNeutral/styles.module.css +32 -0
  44. package/dist/cjs/helpers.js +43 -1
  45. package/dist/cjs/index.d.ts +2 -2
  46. package/dist/cjs/testIds.d.ts +14 -0
  47. package/dist/cjs/testIds.js +16 -1
  48. package/dist/cjs/types.d.ts +9 -1
  49. package/dist/esm/components/ToastSystemEvent/styles.module.css +2 -3
  50. package/dist/esm/components/ToastUpload/ToastUpload.d.ts +60 -0
  51. package/dist/esm/components/ToastUpload/ToastUpload.js +36 -0
  52. package/dist/esm/components/ToastUpload/ToastUploadToaster.d.ts +3 -0
  53. package/dist/esm/components/ToastUpload/ToastUploadToaster.js +7 -0
  54. package/dist/esm/components/ToastUpload/constants.d.ts +16 -0
  55. package/dist/esm/components/ToastUpload/constants.js +20 -0
  56. package/dist/esm/components/ToastUpload/helperComponents/ButtonIcon/ButtonIcon.d.ts +3 -0
  57. package/dist/esm/components/ToastUpload/helperComponents/ButtonIcon/ButtonIcon.js +18 -0
  58. package/dist/esm/components/ToastUpload/helperComponents/ButtonIcon/index.d.ts +1 -0
  59. package/dist/esm/components/ToastUpload/helperComponents/ButtonIcon/index.js +1 -0
  60. package/dist/esm/components/ToastUpload/helperComponents/ButtonIcon/styles.module.css +30 -0
  61. package/dist/esm/components/ToastUpload/helperComponents/FileItem/FileItem.d.ts +5 -0
  62. package/dist/esm/components/ToastUpload/helperComponents/FileItem/FileItem.js +23 -0
  63. package/dist/esm/components/ToastUpload/helperComponents/FileItem/index.d.ts +1 -0
  64. package/dist/esm/components/ToastUpload/helperComponents/FileItem/index.js +1 -0
  65. package/dist/esm/components/ToastUpload/helperComponents/FileItem/styles.module.css +85 -0
  66. package/dist/esm/components/ToastUpload/helperComponents/LoadingStatus/LoadingStatus.d.ts +6 -0
  67. package/dist/esm/components/ToastUpload/helperComponents/LoadingStatus/LoadingStatus.js +16 -0
  68. package/dist/esm/components/ToastUpload/helperComponents/LoadingStatus/index.d.ts +1 -0
  69. package/dist/esm/components/ToastUpload/helperComponents/LoadingStatus/index.js +1 -0
  70. package/dist/esm/components/ToastUpload/helperComponents/LoadingStatus/styles.module.css +3 -0
  71. package/dist/esm/components/ToastUpload/index.d.ts +1 -0
  72. package/dist/esm/components/ToastUpload/index.js +1 -0
  73. package/dist/esm/components/ToastUpload/styles.module.css +110 -0
  74. package/dist/esm/components/ToastUpload/types.d.ts +59 -0
  75. package/dist/esm/components/ToastUpload/types.js +1 -0
  76. package/dist/esm/components/ToastUpload/utils/formatPercent.d.ts +1 -0
  77. package/dist/esm/components/ToastUpload/utils/formatPercent.js +1 -0
  78. package/dist/esm/components/ToastUpload/utils/index.d.ts +1 -0
  79. package/dist/esm/components/ToastUpload/utils/index.js +1 -0
  80. package/dist/esm/components/ToasterContainer/styles.module.css +9 -9
  81. package/dist/esm/components/index.d.ts +1 -0
  82. package/dist/esm/components/index.js +1 -0
  83. package/dist/esm/constants.d.ts +10 -5
  84. package/dist/esm/constants.js +76 -0
  85. package/dist/esm/helperComponents/ButtonAction/styles.module.css +2 -2
  86. package/dist/esm/helperComponents/ButtonTextNeutral/ButtonTextNeutral.d.ts +7 -0
  87. package/dist/esm/helperComponents/ButtonTextNeutral/ButtonTextNeutral.js +5 -0
  88. package/dist/esm/helperComponents/ButtonTextNeutral/index.d.ts +1 -0
  89. package/dist/esm/helperComponents/ButtonTextNeutral/index.js +1 -0
  90. package/dist/esm/helperComponents/ButtonTextNeutral/styles.module.css +32 -0
  91. package/dist/esm/helpers.js +38 -0
  92. package/dist/esm/index.d.ts +2 -2
  93. package/dist/esm/testIds.d.ts +14 -0
  94. package/dist/esm/testIds.js +15 -0
  95. package/dist/esm/types.d.ts +9 -1
  96. package/package.json +6 -5
  97. package/src/components/ToastSystemEvent/styles.module.scss +2 -2
  98. package/src/components/ToastUpload/ToastUpload.tsx +169 -0
  99. package/src/components/ToastUpload/ToastUploadToaster.tsx +11 -0
  100. package/src/components/ToastUpload/constants.ts +26 -0
  101. package/src/components/ToastUpload/helperComponents/ButtonIcon/ButtonIcon.tsx +10 -0
  102. package/src/components/ToastUpload/helperComponents/ButtonIcon/index.ts +1 -0
  103. package/src/components/ToastUpload/helperComponents/ButtonIcon/styles.module.scss +45 -0
  104. package/src/components/ToastUpload/helperComponents/FileItem/FileItem.tsx +76 -0
  105. package/src/components/ToastUpload/helperComponents/FileItem/index.ts +1 -0
  106. package/src/components/ToastUpload/helperComponents/FileItem/styles.module.scss +93 -0
  107. package/src/components/ToastUpload/helperComponents/LoadingStatus/LoadingStatus.tsx +38 -0
  108. package/src/components/ToastUpload/helperComponents/LoadingStatus/index.ts +1 -0
  109. package/src/components/ToastUpload/helperComponents/LoadingStatus/styles.module.scss +8 -0
  110. package/src/components/ToastUpload/index.ts +1 -0
  111. package/src/components/ToastUpload/styles.module.scss +123 -0
  112. package/src/components/ToastUpload/types.ts +67 -0
  113. package/src/components/ToastUpload/utils/formatPercent.ts +1 -0
  114. package/src/components/ToastUpload/utils/index.ts +1 -0
  115. package/src/components/ToasterContainer/styles.module.scss +1 -1
  116. package/src/components/index.ts +1 -0
  117. package/src/constants.ts +91 -2
  118. package/src/helperComponents/ButtonTextNeutral/ButtonTextNeutral.tsx +23 -0
  119. package/src/helperComponents/ButtonTextNeutral/index.ts +1 -0
  120. package/src/helperComponents/ButtonTextNeutral/styles.module.scss +42 -0
  121. package/src/helpers.tsx +35 -0
  122. package/src/index.ts +7 -1
  123. package/src/testIds.ts +17 -0
  124. package/src/types.ts +7 -1
@@ -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';
@@ -61,7 +61,7 @@
61
61
  }
62
62
 
63
63
  .containerWithCloseAllButton {
64
- margin-bottom: calc(styles-theme-variables.$size-toaster-button-close-column + styles-theme-variables.$space-toaster-system-event-gap);
64
+ margin-bottom: calc(styles-theme-variables.$size-toaster-button-close-column + styles-theme-variables.$space-toaster-toast-system-event-gap);
65
65
  }
66
66
 
67
67
  @media only screen and (max-width: 480px) {
@@ -1,3 +1,4 @@
1
1
  export * from './ToastSystemEvent';
2
2
  export * from './ToastUserAction';
3
3
  export * from './ToasterContainer';
4
+ export * from './ToastUpload';
package/src/constants.ts CHANGED
@@ -1,9 +1,11 @@
1
- import { ToasterContainerProps } from './components';
1
+ import { ToasterContainerProps, ToastUploadProps } from './components';
2
+ import { UploadItem } from './components/ToastUpload/types';
2
3
  import { ToasterType } from './types';
3
4
 
4
5
  export const TOASTER_TYPE = {
5
6
  SystemEvent: 'system-event',
6
7
  UserAction: 'user-action',
8
+ Upload: 'upload',
7
9
  } as const;
8
10
 
9
11
  export const TOASTER_CONTAINER_DEFAULT_PROPS: Record<ToasterType, ToasterContainerProps> = {
@@ -19,12 +21,99 @@ export const TOASTER_CONTAINER_DEFAULT_PROPS: Record<ToasterType, ToasterContain
19
21
  displayCloseAllButton: false,
20
22
  type: TOASTER_TYPE.UserAction,
21
23
  },
24
+ [TOASTER_TYPE.Upload]: {
25
+ limit: 5,
26
+ position: 'bottom-right',
27
+ displayCloseAllButton: true,
28
+ type: TOASTER_TYPE.SystemEvent,
29
+ },
22
30
  };
23
31
 
24
- export const AUTO_CLOSE_TIME = {
32
+ export const AUTO_CLOSE_TIME: Record<ToasterType, number | false> = {
25
33
  [TOASTER_TYPE.SystemEvent]: 5000,
26
34
  [TOASTER_TYPE.UserAction]: 2000,
35
+ [TOASTER_TYPE.Upload]: false,
27
36
  };
28
37
 
29
38
  export const TOASTER_ROOT_ID = 'toaster-root';
30
39
  export const TOASTER_CONTAINER_PREFIX = 'toaster-container__';
40
+
41
+ export const MOCK_TOAST_LOADING_ITEM: UploadItem = {
42
+ id: '1',
43
+ progress: 10,
44
+ size: '45 MB',
45
+ title: 'file name.extensions',
46
+ status: 'loading',
47
+ statusLabel: 'Loading...',
48
+ actions: {},
49
+ };
50
+
51
+ export const MOCK_TOAST_PAUSED_ITEM: UploadItem = {
52
+ id: '2',
53
+ progress: 20,
54
+ size: '45 MB',
55
+ title: 'file name.extensions',
56
+ status: 'pause',
57
+ statusLabel: 'Paused',
58
+ actions: {},
59
+ };
60
+
61
+ export const MOCK_TOAST_ERROR_ITEM: UploadItem = {
62
+ id: '3',
63
+ progress: 20,
64
+ size: '45 MB',
65
+ title: 'file name.extensions',
66
+ status: 'error',
67
+ statusLabel: 'Error',
68
+ actions: {},
69
+ };
70
+
71
+ export const MOCK_TOAST_UPLOADED_ITEM: UploadItem = {
72
+ id: '4',
73
+ progress: 100,
74
+ size: '45 MB',
75
+ title: 'file name.extensions',
76
+ status: 'uploaded',
77
+ statusLabel: 'Uploaded',
78
+ actions: {},
79
+ link: {
80
+ href: '#',
81
+ text: 'Show',
82
+ },
83
+ };
84
+
85
+ export const MOCK_TOAST_PROPS: Partial<ToastUploadProps> = {
86
+ title: 'Loading...',
87
+ description: '3 minutes left',
88
+ status: 'loading',
89
+ closable: true,
90
+ collapsed: true,
91
+ totalProgressCounter: '10/15',
92
+ totalProgressPercentage: 30,
93
+ cancelButton: {
94
+ label: 'Cancel all',
95
+ onClick: () => {},
96
+ },
97
+ generalActions: {
98
+ onCancel: () => {},
99
+ onContinue: () => {},
100
+ onPause: () => {},
101
+ onRetry: () => {},
102
+ },
103
+ onCollapsed: () => {},
104
+ };
105
+
106
+ export const MOCK_UPLOAD_ITEMS_LIST = [
107
+ MOCK_TOAST_LOADING_ITEM,
108
+ MOCK_TOAST_PAUSED_ITEM,
109
+ MOCK_TOAST_ERROR_ITEM,
110
+ MOCK_TOAST_UPLOADED_ITEM,
111
+ {
112
+ ...MOCK_TOAST_UPLOADED_ITEM,
113
+ id: '5',
114
+ },
115
+ {
116
+ ...MOCK_TOAST_UPLOADED_ITEM,
117
+ id: '6',
118
+ },
119
+ ];
@@ -0,0 +1,23 @@
1
+ import { MouseEvent } from 'react';
2
+
3
+ import styles from './styles.module.scss';
4
+
5
+ export type ButtonTextNeutralProps = {
6
+ label: string;
7
+ onClick(e: MouseEvent<HTMLButtonElement>): void;
8
+ critical?: boolean;
9
+ };
10
+
11
+ export function ButtonTextNeutral({ label, onClick, critical }: ButtonTextNeutralProps) {
12
+ return (
13
+ <button
14
+ type='button'
15
+ className={styles.buttonTextNeutral}
16
+ onClick={onClick}
17
+ aria-label='action'
18
+ data-critical={critical || undefined}
19
+ >
20
+ {label}
21
+ </button>
22
+ );
23
+ }
@@ -0,0 +1 @@
1
+ export * from './ButtonTextNeutral';
@@ -0,0 +1,42 @@
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
+ .buttonTextNeutral {
9
+ @include styles-theme-variables.composite-var(styles-theme-variables.$sans-body-m);
10
+
11
+ cursor: pointer;
12
+
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+
17
+ box-sizing: border-box;
18
+ margin: 0;
19
+ padding: 0;
20
+
21
+ color: styles-theme-variables.$sys-invert-neutral-text-light;
22
+
23
+ background-color: transparent;
24
+ border: none;
25
+
26
+ &:hover {
27
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
28
+ }
29
+
30
+ &:focus,
31
+ &:active {
32
+ color: styles-theme-variables.$sys-invert-neutral-accent-pressed;
33
+ }
34
+
35
+ &:focus-visible {
36
+ @include styles-theme-variables.outline-var(styles-tokens-element.$container-focused-s);
37
+
38
+ color: styles-theme-variables.$sys-invert-neutral-text-main;
39
+ outline-color: styles-theme-variables.$sys-available-on-complementary;
40
+ outline-offset: styles-theme-variables.$spacing-state-focus-offset;
41
+ }
42
+ }