@snack-uikit/toaster 0.9.4 → 0.9.5-preview-960d787f.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.
package/README.md CHANGED
@@ -102,6 +102,8 @@ toaster.upload.dismiss(uploadToastId);
102
102
  | collapsed | `boolean` | - | Тостер свернут/развернут |
103
103
  | onCollapsed | `(collapsed: boolean) => void` | - | Развернуть/свернуть тостер |
104
104
  | cancelButton | `ButtonTextNeutralProps` | - | Отмена всей загрузки |
105
+ | draggable | `boolean` | - | Перемещение тостера |
106
+ | draggableBounds | `string \| false \| DraggableBounds` | - | Ограничения перемещения тостера |
105
107
 
106
108
 
107
109
  [//]: DOCUMENTATION_SECTION_END
@@ -1,4 +1,5 @@
1
1
  import { MouseEvent } from 'react';
2
+ import { DraggableProps } from 'react-draggable';
2
3
  import { ToastContentProps as RtToastContentProps } from 'react-toastify';
3
4
  import { WithSupportProps } from '@snack-uikit/utils';
4
5
  import { ButtonTextNeutralProps } from './helperComponents/ButtonTextNeutral';
@@ -55,5 +56,13 @@ export type ToastUploadProps = Partial<RtToastContentProps> & WithSupportProps<{
55
56
  * Отмена всей загрузки
56
57
  */
57
58
  cancelButton?: ButtonTextNeutralProps;
59
+ /**
60
+ * Перемещение тостера
61
+ */
62
+ draggable?: boolean;
63
+ /**
64
+ * Ограничения перемещения тостера
65
+ */
66
+ draggableBounds?: DraggableProps['bounds'];
58
67
  }>;
59
- export declare function ToastUpload({ status, title, description, closeToast, onCloseClick, closable, className, files, collapsed, onCollapsed, generalActions, cancelButton, progress, ...rest }: ToastUploadProps): import("react/jsx-runtime").JSX.Element;
68
+ export declare function ToastUpload({ status, title, description, closeToast, onCloseClick, closable, className, files, collapsed, onCollapsed, generalActions, cancelButton, progress, draggable, draggableBounds, ...rest }: ToastUploadProps): import("react/jsx-runtime").JSX.Element;
@@ -19,6 +19,7 @@ Object.defineProperty(exports, "__esModule", {
19
19
  exports.ToastUpload = ToastUpload;
20
20
  const jsx_runtime_1 = require("react/jsx-runtime");
21
21
  const classnames_1 = __importDefault(require("classnames"));
22
+ const react_draggable_1 = __importDefault(require("react-draggable"));
22
23
  const uncontrollable_1 = require("uncontrollable");
23
24
  const icons_1 = require("@snack-uikit/icons");
24
25
  const locale_1 = require("@snack-uikit/locale");
@@ -48,9 +49,11 @@ function ToastUpload(_a) {
48
49
  onCollapsed,
49
50
  generalActions,
50
51
  cancelButton,
51
- progress
52
+ progress,
53
+ draggable = false,
54
+ draggableBounds
52
55
  } = _a,
53
- rest = __rest(_a, ["status", "title", "description", "closeToast", "onCloseClick", "closable", "className", "files", "collapsed", "onCollapsed", "generalActions", "cancelButton", "progress"]);
56
+ rest = __rest(_a, ["status", "title", "description", "closeToast", "onCloseClick", "closable", "className", "files", "collapsed", "onCollapsed", "generalActions", "cancelButton", "progress", "draggable", "draggableBounds"]);
54
57
  const [isCollapsed, setIsCollapsed] = (0, uncontrollable_1.useUncontrolledProp)(collapsed, false, onCollapsed);
55
58
  const {
56
59
  t
@@ -66,67 +69,72 @@ function ToastUpload(_a) {
66
69
  };
67
70
  const progressPercent = Math.round(progress.current / progress.total * 100);
68
71
  const isErrorUploaded = status === 'errorUploaded';
69
- return (0, jsx_runtime_1.jsxs)("div", Object.assign({
70
- className: (0, classnames_1.default)(styles_module_scss_1.default.container, className)
71
- }, (0, utils_1.extractSupportProps)(rest), {
72
- "data-collapsed": isCollapsed || undefined,
73
- children: [(0, jsx_runtime_1.jsxs)("div", {
74
- className: styles_module_scss_1.default.titleLine,
72
+ return (0, jsx_runtime_1.jsx)(react_draggable_1.default, {
73
+ bounds: draggableBounds,
74
+ disabled: !draggable,
75
+ children: (0, jsx_runtime_1.jsxs)("div", Object.assign({
76
+ className: (0, classnames_1.default)(styles_module_scss_1.default.container, className)
77
+ }, (0, utils_1.extractSupportProps)(rest), {
78
+ "data-collapsed": isCollapsed || undefined,
79
+ "data-draggable": draggable || undefined,
75
80
  children: [(0, jsx_runtime_1.jsxs)("div", {
76
- className: styles_module_scss_1.default.titleLineBody,
77
- children: [(0, jsx_runtime_1.jsx)("div", {
78
- className: styles_module_scss_1.default.title,
79
- "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.title,
80
- children: showingTitle
81
- }), cancelButton && (0, jsx_runtime_1.jsx)(ButtonTextNeutral_1.ButtonTextNeutral, Object.assign({}, cancelButton)), (0, jsx_runtime_1.jsx)(ButtonIcon_1.ButtonIcon, {
82
- onClick: handleCollapseClick,
83
- "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.collapseButton,
84
- children: !isCollapsed ? (0, jsx_runtime_1.jsx)(icons_1.ChevronUpSVG, {}) : (0, jsx_runtime_1.jsx)(icons_1.ChevronDownSVG, {})
85
- }), closable && (0, jsx_runtime_1.jsx)(ButtonIcon_1.ButtonIcon, {
86
- className: styles_module_scss_1.default.buttonAction,
87
- onClick: handleCloseClick,
88
- "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.close,
89
- children: (0, jsx_runtime_1.jsx)(icons_1.CrossSVG, {})
90
- })]
91
- }), (0, jsx_runtime_1.jsxs)("div", {
92
- className: styles_module_scss_1.default.generalProgress,
81
+ className: styles_module_scss_1.default.titleLine,
93
82
  children: [(0, jsx_runtime_1.jsxs)("div", {
94
- className: styles_module_scss_1.default.statusLine,
83
+ className: styles_module_scss_1.default.titleLineBody,
84
+ children: [(0, jsx_runtime_1.jsx)("div", {
85
+ className: styles_module_scss_1.default.title,
86
+ "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.title,
87
+ children: showingTitle
88
+ }), cancelButton && (0, jsx_runtime_1.jsx)(ButtonTextNeutral_1.ButtonTextNeutral, Object.assign({}, cancelButton)), (0, jsx_runtime_1.jsx)(ButtonIcon_1.ButtonIcon, {
89
+ onClick: handleCollapseClick,
90
+ "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.collapseButton,
91
+ children: !isCollapsed ? (0, jsx_runtime_1.jsx)(icons_1.ChevronUpSVG, {}) : (0, jsx_runtime_1.jsx)(icons_1.ChevronDownSVG, {})
92
+ }), closable && (0, jsx_runtime_1.jsx)(ButtonIcon_1.ButtonIcon, {
93
+ className: styles_module_scss_1.default.buttonAction,
94
+ onClick: handleCloseClick,
95
+ "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.close,
96
+ children: (0, jsx_runtime_1.jsx)(icons_1.CrossSVG, {})
97
+ })]
98
+ }), (0, jsx_runtime_1.jsxs)("div", {
99
+ className: styles_module_scss_1.default.generalProgress,
95
100
  children: [(0, jsx_runtime_1.jsxs)("div", {
96
- className: styles_module_scss_1.default.statusWrap,
97
- children: [(0, jsx_runtime_1.jsx)(LoadingStatus_1.LoadingStatus, {
98
- status: status,
99
- actions: generalActions
100
- }), (0, jsx_runtime_1.jsx)(truncate_string_1.TruncateString, {
101
- className: styles_module_scss_1.default.description,
102
- "data-status": status,
103
- text: description,
104
- "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.description
101
+ className: styles_module_scss_1.default.statusLine,
102
+ children: [(0, jsx_runtime_1.jsxs)("div", {
103
+ className: styles_module_scss_1.default.statusWrap,
104
+ children: [(0, jsx_runtime_1.jsx)(LoadingStatus_1.LoadingStatus, {
105
+ status: status,
106
+ actions: generalActions
107
+ }), (0, jsx_runtime_1.jsx)(truncate_string_1.TruncateString, {
108
+ className: styles_module_scss_1.default.description,
109
+ "data-status": status,
110
+ text: description,
111
+ "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.description
112
+ })]
113
+ }), (0, jsx_runtime_1.jsx)("span", {
114
+ className: styles_module_scss_1.default.totalCounter,
115
+ "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.counter,
116
+ children: `${progress.current}/${progress.total}`
117
+ }), (0, jsx_runtime_1.jsx)("span", {
118
+ className: styles_module_scss_1.default.totalPercentage,
119
+ "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.progress,
120
+ children: (0, utils_2.formatPercent)(isErrorUploaded ? 0 : progressPercent)
105
121
  })]
106
- }), (0, jsx_runtime_1.jsx)("span", {
107
- className: styles_module_scss_1.default.totalCounter,
108
- "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.counter,
109
- children: `${progress.current}/${progress.total}`
110
- }), (0, jsx_runtime_1.jsx)("span", {
111
- className: styles_module_scss_1.default.totalPercentage,
112
- "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.progress,
113
- children: (0, utils_2.formatPercent)(isErrorUploaded ? 0 : progressPercent)
122
+ }), isCollapsed && (0, jsx_runtime_1.jsx)(progress_bar_1.ProgressBar, {
123
+ progress: isErrorUploaded ? 100 : progressPercent,
124
+ size: 'xs',
125
+ appearance: constants_1.progressBarAppearanceByStatus[status],
126
+ "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.progressBar
114
127
  })]
115
- }), isCollapsed && (0, jsx_runtime_1.jsx)(progress_bar_1.ProgressBar, {
116
- progress: isErrorUploaded ? 100 : progressPercent,
117
- size: 'xs',
118
- appearance: constants_1.progressBarAppearanceByStatus[status],
119
- "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.progressBar
120
128
  })]
129
+ }), (0, jsx_runtime_1.jsx)(scroll_1.Scroll, {
130
+ className: styles_module_scss_1.default.list,
131
+ size: 's',
132
+ "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.list,
133
+ barHideStrategy: 'never',
134
+ children: files.map(item => (0, jsx_runtime_1.jsx)(FileItem_1.FileItem, {
135
+ item: item
136
+ }, item.id || item.title))
121
137
  })]
122
- }), (0, jsx_runtime_1.jsx)(scroll_1.Scroll, {
123
- className: styles_module_scss_1.default.list,
124
- size: 's',
125
- "data-test-id": testIds_1.TOAST_UPLOAD_TEST_IDS.list,
126
- barHideStrategy: 'never',
127
- children: files.map(item => (0, jsx_runtime_1.jsx)(FileItem_1.FileItem, {
128
- item: item
129
- }, item.id || item.title))
130
- })]
131
- }));
138
+ }))
139
+ });
132
140
  }
@@ -1,7 +1,5 @@
1
1
  .container{
2
- padding:var(--space-toaster-toast-system-event-container-padding, 16px);
3
- border-radius:var(--radius-toaster-toast-system-event-container, 16px);
4
- gap:var(--space-toaster-toast-system-event-container-gap, 16px);
2
+ pointer-events:all;
5
3
  cursor:default;
6
4
  position:relative;
7
5
  overflow:hidden;
@@ -12,10 +10,19 @@
12
10
  max-width:100%;
13
11
  max-height:386px;
14
12
  background-color:var(--sys-invert-neutral-background, #30303c);
13
+ padding:var(--space-toaster-toast-system-event-container-padding, 16px);
14
+ border-radius:var(--radius-toaster-toast-system-event-container, 16px);
15
+ gap:var(--space-toaster-toast-system-event-container-gap, 16px);
15
16
  }
16
17
  .container[data-collapsed]{
17
18
  gap:0;
18
19
  }
20
+ .container[data-draggable]{
21
+ cursor:grab;
22
+ }
23
+ .container[data-draggable]:active{
24
+ cursor:grabbing;
25
+ }
19
26
 
20
27
  .titleLine{
21
28
  display:flex;
@@ -60,7 +60,8 @@ function ToasterContainer(_ref) {
60
60
  className: (0, classnames_1.default)('osThemeSnack', styles_module_scss_1.default[position], {
61
61
  [styles_module_scss_1.default.containerWithCloseAllButton]: hasCloseAllButton,
62
62
  'osThemeSnack__toast-container__system-event': type === constants_1.TOASTER_TYPE.SystemEvent,
63
- 'osThemeSnack__toast-container__user-action': type === constants_1.TOASTER_TYPE.UserAction
63
+ 'osThemeSnack__toast-container__user-action': type === constants_1.TOASTER_TYPE.UserAction,
64
+ 'osThemeSnack__toast-container__upload': type === constants_1.TOASTER_TYPE.Upload
64
65
  }),
65
66
  toastClassName: styles_module_scss_1.default.toaster,
66
67
  bodyClassName: styles_module_scss_1.default.toaster,
@@ -154,6 +154,23 @@
154
154
  width:-moz-fit-content;
155
155
  width:fit-content;
156
156
  }
157
+ :global .osThemeSnack.Toastify__toast-container.osThemeSnack__toast-container__upload{
158
+ pointer-events:none;
159
+ z-index:1;
160
+ top:var(--space-toaster-toast-system-event-container-padding, 16px);
161
+ right:var(--space-toaster-toast-system-event-container-padding, 16px);
162
+ bottom:var(--space-toaster-toast-system-event-container-padding, 16px);
163
+ left:var(--space-toaster-toast-system-event-container-padding, 16px);
164
+ display:flex;
165
+ flex-direction:column;
166
+ }
167
+ :global .osThemeSnack.Toastify__toast-container.osThemeSnack__toast-container__upload > div{
168
+ display:flex;
169
+ align-items:flex-end;
170
+ justify-content:flex-start;
171
+ width:100%;
172
+ height:100%;
173
+ }
157
174
  :global .osThemeSnack.Toastify__toast-container--bottom-right{
158
175
  right:0;
159
176
  bottom:0;
@@ -23,10 +23,10 @@ exports.TOASTER_CONTAINER_DEFAULT_PROPS = {
23
23
  type: exports.TOASTER_TYPE.UserAction
24
24
  },
25
25
  [exports.TOASTER_TYPE.Upload]: {
26
- limit: 5,
26
+ limit: 1,
27
27
  position: 'bottom-right',
28
- displayCloseAllButton: true,
29
- type: exports.TOASTER_TYPE.SystemEvent
28
+ displayCloseAllButton: false,
29
+ type: exports.TOASTER_TYPE.Upload
30
30
  }
31
31
  };
32
32
  exports.AUTO_CLOSE_TIME = {
@@ -69,7 +69,10 @@ function getToastComponent(_ref3) {
69
69
  case constants_1.TOASTER_TYPE.SystemEvent:
70
70
  return (0, jsx_runtime_1.jsx)(components_1.ToastSystemEvent, Object.assign({}, toasterProps));
71
71
  case constants_1.TOASTER_TYPE.Upload:
72
- return (0, jsx_runtime_1.jsx)(components_1.ToastUpload, Object.assign({}, toasterProps));
72
+ return (0, jsx_runtime_1.jsx)(components_1.ToastUpload, Object.assign({
73
+ draggable: true,
74
+ draggableBounds: '.Toastify__toast-container'
75
+ }, toasterProps));
73
76
  default:
74
77
  return undefined;
75
78
  }
@@ -1,4 +1,5 @@
1
1
  import { MouseEvent } from 'react';
2
+ import { DraggableProps } from 'react-draggable';
2
3
  import { ToastContentProps as RtToastContentProps } from 'react-toastify';
3
4
  import { WithSupportProps } from '@snack-uikit/utils';
4
5
  import { ButtonTextNeutralProps } from './helperComponents/ButtonTextNeutral';
@@ -55,5 +56,13 @@ export type ToastUploadProps = Partial<RtToastContentProps> & WithSupportProps<{
55
56
  * Отмена всей загрузки
56
57
  */
57
58
  cancelButton?: ButtonTextNeutralProps;
59
+ /**
60
+ * Перемещение тостера
61
+ */
62
+ draggable?: boolean;
63
+ /**
64
+ * Ограничения перемещения тостера
65
+ */
66
+ draggableBounds?: DraggableProps['bounds'];
58
67
  }>;
59
- export declare function ToastUpload({ status, title, description, closeToast, onCloseClick, closable, className, files, collapsed, onCollapsed, generalActions, cancelButton, progress, ...rest }: ToastUploadProps): import("react/jsx-runtime").JSX.Element;
68
+ export declare function ToastUpload({ status, title, description, closeToast, onCloseClick, closable, className, files, collapsed, onCollapsed, generalActions, cancelButton, progress, draggable, draggableBounds, ...rest }: ToastUploadProps): import("react/jsx-runtime").JSX.Element;
@@ -11,6 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import cn from 'classnames';
14
+ import Draggable from 'react-draggable';
14
15
  import { useUncontrolledProp } from 'uncontrollable';
15
16
  import { ChevronDownSVG, ChevronUpSVG, CrossSVG } from '@snack-uikit/icons';
16
17
  import { useLocale } from '@snack-uikit/locale';
@@ -27,7 +28,7 @@ import { LoadingStatus } from './helperComponents/LoadingStatus';
27
28
  import styles from './styles.module.css';
28
29
  import { formatPercent } from './utils';
29
30
  export function ToastUpload(_a) {
30
- var { status, title, description, closeToast, onCloseClick, closable, className, files, collapsed, onCollapsed, generalActions, cancelButton, progress } = _a, rest = __rest(_a, ["status", "title", "description", "closeToast", "onCloseClick", "closable", "className", "files", "collapsed", "onCollapsed", "generalActions", "cancelButton", "progress"]);
31
+ var { status, title, description, closeToast, onCloseClick, closable, className, files, collapsed, onCollapsed, generalActions, cancelButton, progress, draggable = false, draggableBounds } = _a, rest = __rest(_a, ["status", "title", "description", "closeToast", "onCloseClick", "closable", "className", "files", "collapsed", "onCollapsed", "generalActions", "cancelButton", "progress", "draggable", "draggableBounds"]);
31
32
  const [isCollapsed, setIsCollapsed] = useUncontrolledProp(collapsed, false, onCollapsed);
32
33
  const { t } = useLocale('ToastUpload');
33
34
  const showingTitle = title || t(`title.${status}`);
@@ -41,5 +42,5 @@ export function ToastUpload(_a) {
41
42
  };
42
43
  const progressPercent = Math.round((progress.current / progress.total) * 100);
43
44
  const isErrorUploaded = status === 'errorUploaded';
44
- return (_jsxs("div", Object.assign({ className: cn(styles.container, className) }, extractSupportProps(rest), { "data-collapsed": isCollapsed || undefined, children: [_jsxs("div", { className: styles.titleLine, children: [_jsxs("div", { className: styles.titleLineBody, children: [_jsx("div", { className: styles.title, "data-test-id": TOAST_UPLOAD_TEST_IDS.title, children: showingTitle }), cancelButton && _jsx(ButtonTextNeutral, Object.assign({}, cancelButton)), _jsx(ButtonIcon, { onClick: handleCollapseClick, "data-test-id": TOAST_UPLOAD_TEST_IDS.collapseButton, children: !isCollapsed ? _jsx(ChevronUpSVG, {}) : _jsx(ChevronDownSVG, {}) }), closable && (_jsx(ButtonIcon, { className: styles.buttonAction, onClick: handleCloseClick, "data-test-id": TOAST_UPLOAD_TEST_IDS.close, children: _jsx(CrossSVG, {}) }))] }), _jsxs("div", { className: styles.generalProgress, children: [_jsxs("div", { className: styles.statusLine, children: [_jsxs("div", { className: styles.statusWrap, children: [_jsx(LoadingStatus, { status: status, actions: generalActions }), _jsx(TruncateString, { className: styles.description, "data-status": status, text: description, "data-test-id": TOAST_UPLOAD_TEST_IDS.description })] }), _jsx("span", { className: styles.totalCounter, "data-test-id": TOAST_UPLOAD_TEST_IDS.counter, children: `${progress.current}/${progress.total}` }), _jsx("span", { className: styles.totalPercentage, "data-test-id": TOAST_UPLOAD_TEST_IDS.progress, children: formatPercent(isErrorUploaded ? 0 : progressPercent) })] }), isCollapsed && (_jsx(ProgressBar, { progress: isErrorUploaded ? 100 : progressPercent, size: 'xs', appearance: progressBarAppearanceByStatus[status], "data-test-id": TOAST_UPLOAD_TEST_IDS.progressBar }))] })] }), _jsx(Scroll, { className: styles.list, size: 's', "data-test-id": TOAST_UPLOAD_TEST_IDS.list, barHideStrategy: 'never', children: files.map(item => (_jsx(FileItem, { item: item }, item.id || item.title))) })] })));
45
+ return (_jsx(Draggable, { bounds: draggableBounds, disabled: !draggable, children: _jsxs("div", Object.assign({ className: cn(styles.container, className) }, extractSupportProps(rest), { "data-collapsed": isCollapsed || undefined, "data-draggable": draggable || undefined, children: [_jsxs("div", { className: styles.titleLine, children: [_jsxs("div", { className: styles.titleLineBody, children: [_jsx("div", { className: styles.title, "data-test-id": TOAST_UPLOAD_TEST_IDS.title, children: showingTitle }), cancelButton && _jsx(ButtonTextNeutral, Object.assign({}, cancelButton)), _jsx(ButtonIcon, { onClick: handleCollapseClick, "data-test-id": TOAST_UPLOAD_TEST_IDS.collapseButton, children: !isCollapsed ? _jsx(ChevronUpSVG, {}) : _jsx(ChevronDownSVG, {}) }), closable && (_jsx(ButtonIcon, { className: styles.buttonAction, onClick: handleCloseClick, "data-test-id": TOAST_UPLOAD_TEST_IDS.close, children: _jsx(CrossSVG, {}) }))] }), _jsxs("div", { className: styles.generalProgress, children: [_jsxs("div", { className: styles.statusLine, children: [_jsxs("div", { className: styles.statusWrap, children: [_jsx(LoadingStatus, { status: status, actions: generalActions }), _jsx(TruncateString, { className: styles.description, "data-status": status, text: description, "data-test-id": TOAST_UPLOAD_TEST_IDS.description })] }), _jsx("span", { className: styles.totalCounter, "data-test-id": TOAST_UPLOAD_TEST_IDS.counter, children: `${progress.current}/${progress.total}` }), _jsx("span", { className: styles.totalPercentage, "data-test-id": TOAST_UPLOAD_TEST_IDS.progress, children: formatPercent(isErrorUploaded ? 0 : progressPercent) })] }), isCollapsed && (_jsx(ProgressBar, { progress: isErrorUploaded ? 100 : progressPercent, size: 'xs', appearance: progressBarAppearanceByStatus[status], "data-test-id": TOAST_UPLOAD_TEST_IDS.progressBar }))] })] }), _jsx(Scroll, { className: styles.list, size: 's', "data-test-id": TOAST_UPLOAD_TEST_IDS.list, barHideStrategy: 'never', children: files.map(item => (_jsx(FileItem, { item: item }, item.id || item.title))) })] })) }));
45
46
  }
@@ -1,7 +1,5 @@
1
1
  .container{
2
- padding:var(--space-toaster-toast-system-event-container-padding, 16px);
3
- border-radius:var(--radius-toaster-toast-system-event-container, 16px);
4
- gap:var(--space-toaster-toast-system-event-container-gap, 16px);
2
+ pointer-events:all;
5
3
  cursor:default;
6
4
  position:relative;
7
5
  overflow:hidden;
@@ -12,10 +10,19 @@
12
10
  max-width:100%;
13
11
  max-height:386px;
14
12
  background-color:var(--sys-invert-neutral-background, #30303c);
13
+ padding:var(--space-toaster-toast-system-event-container-padding, 16px);
14
+ border-radius:var(--radius-toaster-toast-system-event-container, 16px);
15
+ gap:var(--space-toaster-toast-system-event-container-gap, 16px);
15
16
  }
16
17
  .container[data-collapsed]{
17
18
  gap:0;
18
19
  }
20
+ .container[data-draggable]{
21
+ cursor:grab;
22
+ }
23
+ .container[data-draggable]:active{
24
+ cursor:grabbing;
25
+ }
19
26
 
20
27
  .titleLine{
21
28
  display:flex;
@@ -32,5 +32,6 @@ export function ToasterContainer({ position = 'bottom-right', limit = 5, contain
32
32
  [styles.containerWithCloseAllButton]: hasCloseAllButton,
33
33
  'osThemeSnack__toast-container__system-event': type === TOASTER_TYPE.SystemEvent,
34
34
  'osThemeSnack__toast-container__user-action': type === TOASTER_TYPE.UserAction,
35
+ 'osThemeSnack__toast-container__upload': type === TOASTER_TYPE.Upload,
35
36
  }), toastClassName: styles.toaster, bodyClassName: styles.toaster, position: position, limit: limit, containerId: containerId }), hasCloseAllButton && (_jsx("div", { className: cn(styles.buttonCloseColumnWrapper, styles[position]), children: _jsx("button", { type: 'button', className: styles.buttonCloseColumn, onClick: closeAll, "data-test-id": TOAST_SYSTEM_EVENT_TEST_IDS.buttonCloseColumn, children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C \u0432\u0441\u0435" }) }))] }));
36
37
  }
@@ -154,6 +154,23 @@
154
154
  width:-moz-fit-content;
155
155
  width:fit-content;
156
156
  }
157
+ :global .osThemeSnack.Toastify__toast-container.osThemeSnack__toast-container__upload{
158
+ pointer-events:none;
159
+ z-index:1;
160
+ top:var(--space-toaster-toast-system-event-container-padding, 16px);
161
+ right:var(--space-toaster-toast-system-event-container-padding, 16px);
162
+ bottom:var(--space-toaster-toast-system-event-container-padding, 16px);
163
+ left:var(--space-toaster-toast-system-event-container-padding, 16px);
164
+ display:flex;
165
+ flex-direction:column;
166
+ }
167
+ :global .osThemeSnack.Toastify__toast-container.osThemeSnack__toast-container__upload > div{
168
+ display:flex;
169
+ align-items:flex-end;
170
+ justify-content:flex-start;
171
+ width:100%;
172
+ height:100%;
173
+ }
157
174
  :global .osThemeSnack.Toastify__toast-container--bottom-right{
158
175
  right:0;
159
176
  bottom:0;
@@ -17,10 +17,10 @@ export const TOASTER_CONTAINER_DEFAULT_PROPS = {
17
17
  type: TOASTER_TYPE.UserAction,
18
18
  },
19
19
  [TOASTER_TYPE.Upload]: {
20
- limit: 5,
20
+ limit: 1,
21
21
  position: 'bottom-right',
22
- displayCloseAllButton: true,
23
- type: TOASTER_TYPE.SystemEvent,
22
+ displayCloseAllButton: false,
23
+ type: TOASTER_TYPE.Upload,
24
24
  },
25
25
  };
26
26
  export const AUTO_CLOSE_TIME = {
@@ -49,7 +49,7 @@ function getToastComponent({ type, toasterProps, }) {
49
49
  case TOASTER_TYPE.SystemEvent:
50
50
  return _jsx(ToastSystemEvent, Object.assign({}, toasterProps));
51
51
  case TOASTER_TYPE.Upload:
52
- return _jsx(ToastUpload, Object.assign({}, toasterProps));
52
+ return (_jsx(ToastUpload, Object.assign({ draggable: true, draggableBounds: '.Toastify__toast-container' }, toasterProps)));
53
53
  default:
54
54
  return undefined;
55
55
  }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Toaster",
7
- "version": "0.9.4",
7
+ "version": "0.9.5-preview-960d787f.0",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -45,8 +45,9 @@
45
45
  "@snack-uikit/truncate-string": "0.6.18",
46
46
  "@snack-uikit/utils": "3.8.1",
47
47
  "classnames": "2.5.1",
48
+ "react-draggable": "4.4.6",
48
49
  "react-toastify": "10.0.5",
49
50
  "uncontrollable": "9.0.0"
50
51
  },
51
- "gitHead": "2c50d707746c6aeab336e4097df6e4c8494d67a4"
52
+ "gitHead": "561faf69684b4958bf5cf41950a7e530e5564509"
52
53
  }
@@ -1,5 +1,6 @@
1
1
  import cn from 'classnames';
2
2
  import { MouseEvent } from 'react';
3
+ import Draggable, { DraggableProps } from 'react-draggable';
3
4
  import { ToastContentProps as RtToastContentProps } from 'react-toastify';
4
5
  import { useUncontrolledProp } from 'uncontrollable';
5
6
 
@@ -73,6 +74,14 @@ export type ToastUploadProps = Partial<RtToastContentProps> &
73
74
  * Отмена всей загрузки
74
75
  */
75
76
  cancelButton?: ButtonTextNeutralProps;
77
+ /**
78
+ * Перемещение тостера
79
+ */
80
+ draggable?: boolean;
81
+ /**
82
+ * Ограничения перемещения тостера
83
+ */
84
+ draggableBounds?: DraggableProps['bounds'];
76
85
  }>;
77
86
 
78
87
  export function ToastUpload({
@@ -89,6 +98,8 @@ export function ToastUpload({
89
98
  generalActions,
90
99
  cancelButton,
91
100
  progress,
101
+ draggable = false,
102
+ draggableBounds,
92
103
  ...rest
93
104
  }: ToastUploadProps) {
94
105
  const [isCollapsed, setIsCollapsed] = useUncontrolledProp(collapsed, false, onCollapsed);
@@ -111,72 +122,75 @@ export function ToastUpload({
111
122
  const isErrorUploaded = status === 'errorUploaded';
112
123
 
113
124
  return (
114
- <div
115
- className={cn(styles.container, className)}
116
- {...extractSupportProps(rest)}
117
- data-collapsed={isCollapsed || undefined}
118
- >
119
- <div className={styles.titleLine}>
120
- <div className={styles.titleLineBody}>
121
- <div className={styles.title} data-test-id={TOAST_UPLOAD_TEST_IDS.title}>
122
- {showingTitle}
123
- </div>
124
-
125
- {cancelButton && <ButtonTextNeutral {...cancelButton} />}
125
+ <Draggable bounds={draggableBounds} disabled={!draggable}>
126
+ <div
127
+ className={cn(styles.container, className)}
128
+ {...extractSupportProps(rest)}
129
+ data-collapsed={isCollapsed || undefined}
130
+ data-draggable={draggable || undefined}
131
+ >
132
+ <div className={styles.titleLine}>
133
+ <div className={styles.titleLineBody}>
134
+ <div className={styles.title} data-test-id={TOAST_UPLOAD_TEST_IDS.title}>
135
+ {showingTitle}
136
+ </div>
126
137
 
127
- <ButtonIcon onClick={handleCollapseClick} data-test-id={TOAST_UPLOAD_TEST_IDS.collapseButton}>
128
- {!isCollapsed ? <ChevronUpSVG /> : <ChevronDownSVG />}
129
- </ButtonIcon>
138
+ {cancelButton && <ButtonTextNeutral {...cancelButton} />}
130
139
 
131
- {closable && (
132
- <ButtonIcon
133
- className={styles.buttonAction}
134
- onClick={handleCloseClick}
135
- data-test-id={TOAST_UPLOAD_TEST_IDS.close}
136
- >
137
- <CrossSVG />
140
+ <ButtonIcon onClick={handleCollapseClick} data-test-id={TOAST_UPLOAD_TEST_IDS.collapseButton}>
141
+ {!isCollapsed ? <ChevronUpSVG /> : <ChevronDownSVG />}
138
142
  </ButtonIcon>
139
- )}
140
- </div>
141
143
 
142
- <div className={styles.generalProgress}>
143
- <div className={styles.statusLine}>
144
- <div className={styles.statusWrap}>
145
- <LoadingStatus status={status} actions={generalActions} />
144
+ {closable && (
145
+ <ButtonIcon
146
+ className={styles.buttonAction}
147
+ onClick={handleCloseClick}
148
+ data-test-id={TOAST_UPLOAD_TEST_IDS.close}
149
+ >
150
+ <CrossSVG />
151
+ </ButtonIcon>
152
+ )}
153
+ </div>
146
154
 
147
- <TruncateString
148
- className={styles.description}
149
- data-status={status}
150
- text={description}
151
- data-test-id={TOAST_UPLOAD_TEST_IDS.description}
152
- />
155
+ <div className={styles.generalProgress}>
156
+ <div className={styles.statusLine}>
157
+ <div className={styles.statusWrap}>
158
+ <LoadingStatus status={status} actions={generalActions} />
159
+
160
+ <TruncateString
161
+ className={styles.description}
162
+ data-status={status}
163
+ text={description}
164
+ data-test-id={TOAST_UPLOAD_TEST_IDS.description}
165
+ />
166
+ </div>
167
+
168
+ <span className={styles.totalCounter} data-test-id={TOAST_UPLOAD_TEST_IDS.counter}>
169
+ {`${progress.current}/${progress.total}`}
170
+ </span>
171
+
172
+ <span className={styles.totalPercentage} data-test-id={TOAST_UPLOAD_TEST_IDS.progress}>
173
+ {formatPercent(isErrorUploaded ? 0 : progressPercent)}
174
+ </span>
153
175
  </div>
154
176
 
155
- <span className={styles.totalCounter} data-test-id={TOAST_UPLOAD_TEST_IDS.counter}>
156
- {`${progress.current}/${progress.total}`}
157
- </span>
158
-
159
- <span className={styles.totalPercentage} data-test-id={TOAST_UPLOAD_TEST_IDS.progress}>
160
- {formatPercent(isErrorUploaded ? 0 : progressPercent)}
161
- </span>
177
+ {isCollapsed && (
178
+ <ProgressBar
179
+ progress={isErrorUploaded ? 100 : progressPercent}
180
+ size='xs'
181
+ appearance={progressBarAppearanceByStatus[status]}
182
+ data-test-id={TOAST_UPLOAD_TEST_IDS.progressBar}
183
+ />
184
+ )}
162
185
  </div>
163
-
164
- {isCollapsed && (
165
- <ProgressBar
166
- progress={isErrorUploaded ? 100 : progressPercent}
167
- size='xs'
168
- appearance={progressBarAppearanceByStatus[status]}
169
- data-test-id={TOAST_UPLOAD_TEST_IDS.progressBar}
170
- />
171
- )}
172
186
  </div>
173
- </div>
174
187
 
175
- <Scroll className={styles.list} size='s' data-test-id={TOAST_UPLOAD_TEST_IDS.list} barHideStrategy='never'>
176
- {files.map(item => (
177
- <FileItem key={item.id || item.title} item={item} />
178
- ))}
179
- </Scroll>
180
- </div>
188
+ <Scroll className={styles.list} size='s' data-test-id={TOAST_UPLOAD_TEST_IDS.list} barHideStrategy='never'>
189
+ {files.map(item => (
190
+ <FileItem key={item.id || item.title} item={item} />
191
+ ))}
192
+ </Scroll>
193
+ </div>
194
+ </Draggable>
181
195
  );
182
196
  }
@@ -3,8 +3,7 @@
3
3
  @use '@snack-uikit/figma-tokens/build/scss/styles-theme-variables';
4
4
 
5
5
  .container {
6
- @include styles-theme-variables.composite-var(styles-tokens-toaster-toasterUpload.$toaster-upload-toast-container);
7
-
6
+ pointer-events: all;
8
7
  cursor: default;
9
8
 
10
9
  position: relative;
@@ -25,6 +24,16 @@
25
24
  &[data-collapsed] {
26
25
  gap: 0;
27
26
  }
27
+
28
+ &[data-draggable] {
29
+ cursor: grab;
30
+ }
31
+
32
+ &[data-draggable]:active {
33
+ cursor: grabbing;
34
+ }
35
+
36
+ @include styles-theme-variables.composite-var(styles-tokens-toaster-toasterUpload.$toaster-upload-toast-container);
28
37
  }
29
38
 
30
39
  .titleLine {
@@ -67,6 +67,7 @@ export function ToasterContainer({
67
67
  [styles.containerWithCloseAllButton]: hasCloseAllButton,
68
68
  'osThemeSnack__toast-container__system-event': type === TOASTER_TYPE.SystemEvent,
69
69
  'osThemeSnack__toast-container__user-action': type === TOASTER_TYPE.UserAction,
70
+ 'osThemeSnack__toast-container__upload': type === TOASTER_TYPE.Upload,
70
71
  })}
71
72
  toastClassName={styles.toaster}
72
73
  bodyClassName={styles.toaster}
@@ -183,6 +183,30 @@ $theme-name: osThemeSnack;
183
183
  width: fit-content;
184
184
  }
185
185
 
186
+ .#{$theme-name}.Toastify__toast-container.osThemeSnack__toast-container__upload {
187
+ pointer-events: none;
188
+
189
+ // Необходимо, чтобы тостер с загрузкой был всегда выше остальных тостеров
190
+ /* stylelint-disable-next-line declaration-property-value-allowed-list */
191
+ z-index: 1;
192
+ top: styles-theme-variables.$space-toaster-toast-system-event-container-padding;
193
+ right: styles-theme-variables.$space-toaster-toast-system-event-container-padding;
194
+ bottom: styles-theme-variables.$space-toaster-toast-system-event-container-padding;
195
+ left: styles-theme-variables.$space-toaster-toast-system-event-container-padding;
196
+
197
+ display: flex;
198
+ flex-direction: column;
199
+
200
+ > div {
201
+ display: flex;
202
+ align-items: flex-end;
203
+ justify-content: flex-start;
204
+
205
+ width: 100%;
206
+ height: 100%;
207
+ }
208
+ }
209
+
186
210
  .#{$theme-name}.Toastify__toast-container--bottom-right {
187
211
  right: 0;
188
212
  bottom: 0;
package/src/constants.ts CHANGED
@@ -21,10 +21,10 @@ export const TOASTER_CONTAINER_DEFAULT_PROPS: Record<ToasterType, ToasterContain
21
21
  type: TOASTER_TYPE.UserAction,
22
22
  },
23
23
  [TOASTER_TYPE.Upload]: {
24
- limit: 5,
24
+ limit: 1,
25
25
  position: 'bottom-right',
26
- displayCloseAllButton: true,
27
- type: TOASTER_TYPE.SystemEvent,
26
+ displayCloseAllButton: false,
27
+ type: TOASTER_TYPE.Upload,
28
28
  },
29
29
  };
30
30
 
package/src/helpers.tsx CHANGED
@@ -101,7 +101,9 @@ function getToastComponent<T extends keyof ToasterPropsMap>({
101
101
  case TOASTER_TYPE.SystemEvent:
102
102
  return <ToastSystemEvent {...(toasterProps as ToastSystemEventProps)} />;
103
103
  case TOASTER_TYPE.Upload:
104
- return <ToastUpload {...(toasterProps as ToastUploadProps)} />;
104
+ return (
105
+ <ToastUpload draggable draggableBounds='.Toastify__toast-container' {...(toasterProps as ToastUploadProps)} />
106
+ );
105
107
  default:
106
108
  return undefined;
107
109
  }