@snack-uikit/notification 0.13.30 → 0.13.31-preview-7cd3a502.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 +9 -0
- package/dist/cjs/components/NotificationCard/NotificationCard.js +5 -0
- package/dist/cjs/components/NotificationCard/styles.module.css +6 -0
- package/dist/cjs/components/NotificationPanel/NotificationPanel.d.ts +11 -2
- package/dist/cjs/components/NotificationPanel/NotificationPanel.js +20 -6
- package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.d.ts +5 -1
- package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.js +7 -5
- package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/utils.d.ts +3 -1
- package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/utils.js +1 -1
- package/dist/cjs/components/NotificationPanel/components/NotificationPanelBlank/NotificationPanelBlank.js +2 -1
- package/dist/cjs/components/NotificationPanel/components/NotificationPanelBlank/styles.module.css +7 -0
- package/dist/cjs/components/NotificationPanel/components/NotificationPanelGroup/NotificationPanelGroup.d.ts +12 -0
- package/dist/cjs/components/NotificationPanel/components/NotificationPanelGroup/NotificationPanelGroup.js +51 -0
- package/dist/cjs/components/NotificationPanel/components/NotificationPanelGroup/index.d.ts +1 -0
- package/dist/cjs/components/NotificationPanel/components/NotificationPanelGroup/index.js +13 -0
- package/dist/cjs/components/NotificationPanel/components/NotificationPanelGroup/styles.module.css +34 -0
- package/dist/cjs/components/NotificationPanel/components/index.d.ts +1 -0
- package/dist/cjs/components/NotificationPanel/components/index.js +2 -1
- package/dist/cjs/components/NotificationPanel/styles.module.css +8 -0
- package/dist/esm/components/NotificationCard/NotificationCard.js +2 -1
- package/dist/esm/components/NotificationCard/styles.module.css +6 -0
- package/dist/esm/components/NotificationPanel/NotificationPanel.d.ts +11 -2
- package/dist/esm/components/NotificationPanel/NotificationPanel.js +9 -3
- package/dist/esm/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.d.ts +5 -1
- package/dist/esm/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.js +4 -2
- package/dist/esm/components/NotificationPanel/components/NotificationCardStack/utils.d.ts +3 -1
- package/dist/esm/components/NotificationPanel/components/NotificationCardStack/utils.js +1 -1
- package/dist/esm/components/NotificationPanel/components/NotificationPanelBlank/NotificationPanelBlank.js +2 -2
- package/dist/esm/components/NotificationPanel/components/NotificationPanelBlank/styles.module.css +7 -0
- package/dist/esm/components/NotificationPanel/components/NotificationPanelGroup/NotificationPanelGroup.d.ts +12 -0
- package/dist/esm/components/NotificationPanel/components/NotificationPanelGroup/NotificationPanelGroup.js +22 -0
- package/dist/esm/components/NotificationPanel/components/NotificationPanelGroup/index.d.ts +1 -0
- package/dist/esm/components/NotificationPanel/components/NotificationPanelGroup/index.js +1 -0
- package/dist/esm/components/NotificationPanel/components/NotificationPanelGroup/styles.module.css +34 -0
- package/dist/esm/components/NotificationPanel/components/index.d.ts +1 -0
- package/dist/esm/components/NotificationPanel/components/index.js +1 -0
- package/dist/esm/components/NotificationPanel/styles.module.css +8 -0
- package/package.json +4 -2
- package/src/components/NotificationCard/NotificationCard.tsx +3 -0
- package/src/components/NotificationCard/styles.module.scss +6 -0
- package/src/components/NotificationPanel/NotificationPanel.tsx +28 -2
- package/src/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.tsx +12 -1
- package/src/components/NotificationPanel/components/NotificationCardStack/utils.ts +4 -5
- package/src/components/NotificationPanel/components/NotificationPanelBlank/NotificationPanelBlank.tsx +2 -2
- package/src/components/NotificationPanel/components/NotificationPanelBlank/styles.module.scss +7 -0
- package/src/components/NotificationPanel/components/NotificationPanelGroup/NotificationPanelGroup.tsx +31 -0
- package/src/components/NotificationPanel/components/NotificationPanelGroup/index.ts +1 -0
- package/src/components/NotificationPanel/components/NotificationPanelGroup/styles.module.scss +39 -0
- package/src/components/NotificationPanel/components/index.ts +1 -0
- package/src/components/NotificationPanel/styles.module.scss +8 -1
package/README.md
CHANGED
|
@@ -261,6 +261,7 @@ function NotificationPanelStackExample() {
|
|
|
261
261
|
| title* | `string` | - | Заголовок панели |
|
|
262
262
|
| settings | `NotificationPanelSettingsProps` | - | Кнопка настроек и выпадающий список |
|
|
263
263
|
| segments | `Omit<SegmentedControlProps, "data-test-id" \| "size">` | - | Сегменты для фильтрации |
|
|
264
|
+
| chipToggle | `{ label: string; checked: boolean; defaultChecked?: boolean; onChange: (checked: boolean) => void; }` | { label: 'Label', checked: false, onChange: () => {}, } | Переключатель для фильтрации |
|
|
264
265
|
| readAllButton | `Omit<ButtonFunctionProps, "data-test-id"> & { tooltip?: TooltipProps; }` | - | Кнопка в "шапке" панели |
|
|
265
266
|
| footerButton | `{ label: string; onClick: MouseEventHandler<HTMLButtonElement>; }` | - | Кнопка внизу панели |
|
|
266
267
|
| className | `string` | - | CSS-класс |
|
|
@@ -292,6 +293,14 @@ function NotificationPanelStackExample() {
|
|
|
292
293
|
| defaultOpen | `boolean` | false | Состояние открыт/закрыт по умолчанию |
|
|
293
294
|
| onOpenChanged | `(open: boolean) => void` | - | Колбек смены состояния открыт/закрыт |
|
|
294
295
|
| actions | `Action[]` | - | Список действий в выпадающем меню |
|
|
296
|
+
| unread | `boolean` | - | Состояние непрочитанных карточек |
|
|
297
|
+
## NotificationPanel.Group
|
|
298
|
+
### Props
|
|
299
|
+
| name | type | default value | description |
|
|
300
|
+
|------|------|---------------|-------------|
|
|
301
|
+
| children* | `ReactNode` | - | Содержимое группы |
|
|
302
|
+
| title* | `string` | - | Заголовок группы |
|
|
303
|
+
| className | `string` | - | CSS-класс |
|
|
295
304
|
## NotificationPanelPopover
|
|
296
305
|
Компонент-обёртка для NotificationPanel для использования как выпадающий элемент
|
|
297
306
|
### Props
|
|
@@ -23,6 +23,7 @@ const react_1 = require("react");
|
|
|
23
23
|
const button_1 = require("@snack-uikit/button");
|
|
24
24
|
const icons_1 = require("@snack-uikit/icons");
|
|
25
25
|
const link_1 = require("@snack-uikit/link");
|
|
26
|
+
const status_1 = require("@snack-uikit/status");
|
|
26
27
|
const truncate_string_1 = require("@snack-uikit/truncate-string");
|
|
27
28
|
const typography_1 = require("@snack-uikit/typography");
|
|
28
29
|
const utils_1 = require("@snack-uikit/utils");
|
|
@@ -150,6 +151,10 @@ function NotificationCard(_a) {
|
|
|
150
151
|
"data-test-id": constants_1.TEST_IDS.date,
|
|
151
152
|
children: date
|
|
152
153
|
})]
|
|
154
|
+
}), unread && (0, jsx_runtime_1.jsx)(status_1.StatusIndicator, {
|
|
155
|
+
className: styles_module_scss_1.default.statusIndicator,
|
|
156
|
+
size: 'xs',
|
|
157
|
+
appearance: 'primary'
|
|
153
158
|
})]
|
|
154
159
|
}));
|
|
155
160
|
}
|
|
@@ -23,6 +23,12 @@
|
|
|
23
23
|
box-sizing:border-box;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
.statusIndicator{
|
|
27
|
+
position:absolute;
|
|
28
|
+
top:4px;
|
|
29
|
+
right:4px;
|
|
30
|
+
}
|
|
31
|
+
|
|
26
32
|
.notificationCard{
|
|
27
33
|
padding-left:var(--space-notification-panel-card-padding-horizontal, 12px);
|
|
28
34
|
padding-right:var(--space-notification-panel-card-padding-horizontal, 12px);
|
|
@@ -3,7 +3,7 @@ import { ButtonFunctionProps } from '@snack-uikit/button';
|
|
|
3
3
|
import { SegmentedControlProps } from '@snack-uikit/segmented-control';
|
|
4
4
|
import { TooltipProps } from '@snack-uikit/tooltip';
|
|
5
5
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
6
|
-
import { NotificationCardStack, NotificationCardStackProps, NotificationPanelBlank, NotificationPanelBlankProps, NotificationPanelSettingsProps } from './components';
|
|
6
|
+
import { NotificationCardStack, NotificationCardStackProps, NotificationPanelBlank, NotificationPanelBlankProps, NotificationPanelGroup, NotificationPanelGroupProps, NotificationPanelSettingsProps } from './components';
|
|
7
7
|
import { NotificationPanelDivider, NotificationPanelDividerProps } from './components/NotificationPanelDivider';
|
|
8
8
|
export type { NotificationPanelBlankProps };
|
|
9
9
|
export type NotificationPanelProps = WithSupportProps<{
|
|
@@ -13,6 +13,13 @@ export type NotificationPanelProps = WithSupportProps<{
|
|
|
13
13
|
settings?: NotificationPanelSettingsProps;
|
|
14
14
|
/** Сегменты для фильтрации */
|
|
15
15
|
segments?: Omit<SegmentedControlProps, 'size' | 'data-test-id'>;
|
|
16
|
+
/** Переключатель для фильтрации */
|
|
17
|
+
chipToggle?: {
|
|
18
|
+
label: string;
|
|
19
|
+
checked: boolean;
|
|
20
|
+
defaultChecked?: boolean;
|
|
21
|
+
onChange: (checked: boolean) => void;
|
|
22
|
+
};
|
|
16
23
|
/** Кнопка в "шапке" панели */
|
|
17
24
|
readAllButton?: Omit<ButtonFunctionProps, 'data-test-id'> & {
|
|
18
25
|
tooltip?: TooltipProps;
|
|
@@ -35,7 +42,7 @@ export type NotificationPanelProps = WithSupportProps<{
|
|
|
35
42
|
scrollContainerRef?: RefObject<HTMLElement>;
|
|
36
43
|
}>;
|
|
37
44
|
/** Компонент панели для уведомлений */
|
|
38
|
-
export declare function NotificationPanel({ title, settings, segments, readAllButton, footerButton, content, loading, skeletonsAmount, scrollEndRef, scrollContainerRef, className, ...rest }: NotificationPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
45
|
+
export declare function NotificationPanel({ title, settings, segments, readAllButton, footerButton, content, loading, skeletonsAmount, scrollEndRef, scrollContainerRef, className, chipToggle, ...rest }: NotificationPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
39
46
|
export declare namespace NotificationPanel {
|
|
40
47
|
const Blank: typeof NotificationPanelBlank;
|
|
41
48
|
type BlankProps = NotificationPanelBlankProps;
|
|
@@ -43,4 +50,6 @@ export declare namespace NotificationPanel {
|
|
|
43
50
|
type DividerProps = NotificationPanelDividerProps;
|
|
44
51
|
const Stack: typeof NotificationCardStack;
|
|
45
52
|
type StackProps = NotificationCardStackProps;
|
|
53
|
+
const Group: typeof NotificationPanelGroup;
|
|
54
|
+
type GroupProps = NotificationPanelGroupProps;
|
|
46
55
|
}
|
|
@@ -21,6 +21,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
21
21
|
const classnames_1 = __importDefault(require("classnames"));
|
|
22
22
|
const react_1 = require("react");
|
|
23
23
|
const button_1 = require("@snack-uikit/button");
|
|
24
|
+
const chips_1 = require("@snack-uikit/chips");
|
|
24
25
|
const scroll_1 = require("@snack-uikit/scroll");
|
|
25
26
|
const segmented_control_1 = require("@snack-uikit/segmented-control");
|
|
26
27
|
const skeleton_1 = require("@snack-uikit/skeleton");
|
|
@@ -46,9 +47,14 @@ function NotificationPanel(_a) {
|
|
|
46
47
|
skeletonsAmount = 2,
|
|
47
48
|
scrollEndRef,
|
|
48
49
|
scrollContainerRef,
|
|
49
|
-
className
|
|
50
|
+
className,
|
|
51
|
+
chipToggle = {
|
|
52
|
+
label: 'Label',
|
|
53
|
+
checked: false,
|
|
54
|
+
onChange: () => {}
|
|
55
|
+
}
|
|
50
56
|
} = _a,
|
|
51
|
-
rest = __rest(_a, ["title", "settings", "segments", "readAllButton", "footerButton", "content", "loading", "skeletonsAmount", "scrollEndRef", "scrollContainerRef", "className"]);
|
|
57
|
+
rest = __rest(_a, ["title", "settings", "segments", "readAllButton", "footerButton", "content", "loading", "skeletonsAmount", "scrollEndRef", "scrollContainerRef", "className", "chipToggle"]);
|
|
52
58
|
const skeletons = (0, react_1.useMemo)(() => Array.from({
|
|
53
59
|
length: skeletonsAmount
|
|
54
60
|
}, (_, i) => i), [skeletonsAmount]);
|
|
@@ -77,14 +83,21 @@ function NotificationPanel(_a) {
|
|
|
77
83
|
}))
|
|
78
84
|
}), settings && (0, jsx_runtime_1.jsx)(components_2.NotificationPanelSettings, Object.assign({}, settings))]
|
|
79
85
|
})]
|
|
80
|
-
}), (0, jsx_runtime_1.
|
|
81
|
-
|
|
82
|
-
|
|
86
|
+
}), (0, jsx_runtime_1.jsxs)("div", {
|
|
87
|
+
className: styles_module_scss_1.default.actionsRow,
|
|
88
|
+
children: [segments && (0, jsx_runtime_1.jsx)(segmented_control_1.SegmentedControl, Object.assign({}, segments, {
|
|
89
|
+
size: 'xs',
|
|
83
90
|
items: segments.items.map(item => Object.assign(Object.assign({}, item), {
|
|
84
91
|
disabled: item.disabled || loading
|
|
85
92
|
})),
|
|
86
93
|
"data-test-id": constants_1.TEST_IDS.segments
|
|
87
|
-
}))
|
|
94
|
+
})), chipToggle && (0, jsx_runtime_1.jsx)(chips_1.ChipToggle, {
|
|
95
|
+
size: 'xs',
|
|
96
|
+
disabled: loading,
|
|
97
|
+
label: chipToggle.label,
|
|
98
|
+
onChange: chipToggle.onChange,
|
|
99
|
+
checked: chipToggle.checked
|
|
100
|
+
})]
|
|
88
101
|
})]
|
|
89
102
|
}), (0, jsx_runtime_1.jsx)(scroll_1.Scroll, {
|
|
90
103
|
size: 'm',
|
|
@@ -116,4 +129,5 @@ function NotificationPanel(_a) {
|
|
|
116
129
|
NotificationPanel.Blank = components_2.NotificationPanelBlank;
|
|
117
130
|
NotificationPanel.Divider = NotificationPanelDivider_1.NotificationPanelDivider;
|
|
118
131
|
NotificationPanel.Stack = components_2.NotificationCardStack;
|
|
132
|
+
NotificationPanel.Group = components_2.NotificationPanelGroup;
|
|
119
133
|
})(NotificationPanel || (exports.NotificationPanel = NotificationPanel = {}));
|
|
@@ -23,5 +23,9 @@ export type NotificationCardStackProps = {
|
|
|
23
23
|
* Список действий в выпадающем меню
|
|
24
24
|
*/
|
|
25
25
|
actions?: Action[];
|
|
26
|
+
/**
|
|
27
|
+
* Состояние непрочитанных карточек
|
|
28
|
+
*/
|
|
29
|
+
unread?: boolean;
|
|
26
30
|
};
|
|
27
|
-
export declare function NotificationCardStack({ children, defaultOpen, onOpenChanged, title, actions, }: NotificationCardStackProps): import("react/jsx-runtime").JSX.Element | null;
|
|
31
|
+
export declare function NotificationCardStack({ children, defaultOpen, onOpenChanged, title, actions, unread, }: NotificationCardStackProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -26,7 +26,8 @@ function NotificationCardStack(_ref) {
|
|
|
26
26
|
defaultOpen,
|
|
27
27
|
onOpenChanged,
|
|
28
28
|
title,
|
|
29
|
-
actions
|
|
29
|
+
actions,
|
|
30
|
+
unread
|
|
30
31
|
} = _ref;
|
|
31
32
|
const [actionsOpen, setActionsOpen] = (0, react_1.useState)(false);
|
|
32
33
|
const {
|
|
@@ -47,13 +48,14 @@ function NotificationCardStack(_ref) {
|
|
|
47
48
|
children: first
|
|
48
49
|
});
|
|
49
50
|
}
|
|
50
|
-
const firstCardElement = open ? first : (0, utils_1.cloneCard)(first, {
|
|
51
|
-
onClick: toggleOpen
|
|
52
|
-
|
|
51
|
+
const firstCardElement = open ? first : (0, utils_1.cloneCard)(first, componentProps => Object.assign(Object.assign({}, componentProps), {
|
|
52
|
+
onClick: toggleOpen,
|
|
53
|
+
unread: unread || componentProps.unread
|
|
54
|
+
}));
|
|
53
55
|
return (0, jsx_runtime_1.jsxs)("div", {
|
|
54
56
|
className: styles_module_scss_1.default.container,
|
|
55
57
|
style: {
|
|
56
|
-
'--snack-notification-stack-animation-duration':
|
|
58
|
+
'--snack-notification-stack-animation-duration': `${ANIMATION_DURATION}s`
|
|
57
59
|
},
|
|
58
60
|
"data-test-id": constants_1.TEST_IDS.cardStack.wrapper,
|
|
59
61
|
children: [(0, jsx_runtime_1.jsxs)("div", {
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
|
|
2
|
+
type ComponentProps = Record<string, unknown>;
|
|
3
|
+
export declare const cloneCard: (element: ReactNode, props: (componentProps: ComponentProps) => ComponentProps) => string | number | boolean | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined;
|
|
4
|
+
export {};
|
|
@@ -9,6 +9,6 @@ const cloneCard = (element, props) => {
|
|
|
9
9
|
if (!(0, react_1.isValidElement)(element)) {
|
|
10
10
|
return element;
|
|
11
11
|
}
|
|
12
|
-
return (0, react_1.cloneElement)(element,
|
|
12
|
+
return (0, react_1.cloneElement)(element, props(element.props));
|
|
13
13
|
};
|
|
14
14
|
exports.cloneCard = cloneCard;
|
|
@@ -29,7 +29,8 @@ function NotificationPanelBlank(_a) {
|
|
|
29
29
|
className
|
|
30
30
|
} = _a,
|
|
31
31
|
props = __rest(_a, ["icon", "className"]);
|
|
32
|
-
return (0, jsx_runtime_1.jsx)(
|
|
32
|
+
return (0, jsx_runtime_1.jsx)("div", {
|
|
33
|
+
className: styles_module_scss_1.default.wrapper,
|
|
33
34
|
children: (0, jsx_runtime_1.jsx)(info_block_1.InfoBlock, Object.assign({}, props, {
|
|
34
35
|
icon: icon ? Object.assign(Object.assign({}, icon), {
|
|
35
36
|
appearance: (_b = icon.appearance) !== null && _b !== void 0 ? _b : 'neutral'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { WithSupportProps } from '@snack-uikit/utils';
|
|
3
|
+
export type NotificationPanelGroupProps = WithSupportProps<{
|
|
4
|
+
/** Заголовок группы */
|
|
5
|
+
title: string;
|
|
6
|
+
/** Содержимое группы */
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/** CSS-класс */
|
|
9
|
+
className?: string;
|
|
10
|
+
}>;
|
|
11
|
+
/** Группа уведомлений с заголовком внутри панели */
|
|
12
|
+
export declare function NotificationPanelGroup({ title, children, className, ...rest }: NotificationPanelGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __rest = void 0 && (void 0).__rest || function (s, e) {
|
|
4
|
+
var t = {};
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
12
|
+
return mod && mod.__esModule ? mod : {
|
|
13
|
+
"default": mod
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", {
|
|
17
|
+
value: true
|
|
18
|
+
});
|
|
19
|
+
exports.NotificationPanelGroup = NotificationPanelGroup;
|
|
20
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
21
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
22
|
+
const truncate_string_1 = require("@snack-uikit/truncate-string");
|
|
23
|
+
const typography_1 = require("@snack-uikit/typography");
|
|
24
|
+
const utils_1 = require("@snack-uikit/utils");
|
|
25
|
+
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
26
|
+
/** Группа уведомлений с заголовком внутри панели */
|
|
27
|
+
function NotificationPanelGroup(_a) {
|
|
28
|
+
var {
|
|
29
|
+
title,
|
|
30
|
+
children,
|
|
31
|
+
className
|
|
32
|
+
} = _a,
|
|
33
|
+
rest = __rest(_a, ["title", "children", "className"]);
|
|
34
|
+
return (0, jsx_runtime_1.jsxs)("div", Object.assign({
|
|
35
|
+
className: (0, classnames_1.default)(styles_module_scss_1.default.root, className)
|
|
36
|
+
}, (0, utils_1.extractSupportProps)(rest), {
|
|
37
|
+
children: [(0, jsx_runtime_1.jsx)("div", {
|
|
38
|
+
className: styles_module_scss_1.default.title,
|
|
39
|
+
children: (0, jsx_runtime_1.jsx)(typography_1.Typography.LightLabelS, {
|
|
40
|
+
className: styles_module_scss_1.default.text,
|
|
41
|
+
tag: 'span',
|
|
42
|
+
children: (0, jsx_runtime_1.jsx)(truncate_string_1.TruncateString, {
|
|
43
|
+
text: title
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
}), (0, jsx_runtime_1.jsx)("div", {
|
|
47
|
+
className: styles_module_scss_1.default.content,
|
|
48
|
+
children: children
|
|
49
|
+
})]
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NotificationPanelGroup, type NotificationPanelGroupProps } from './NotificationPanelGroup';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.NotificationPanelGroup = void 0;
|
|
7
|
+
var NotificationPanelGroup_1 = require("./NotificationPanelGroup");
|
|
8
|
+
Object.defineProperty(exports, "NotificationPanelGroup", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () {
|
|
11
|
+
return NotificationPanelGroup_1.NotificationPanelGroup;
|
|
12
|
+
}
|
|
13
|
+
});
|
package/dist/cjs/components/NotificationPanel/components/NotificationPanelGroup/styles.module.css
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
.root{
|
|
2
|
+
position:relative;
|
|
3
|
+
display:flex;
|
|
4
|
+
flex-direction:column;
|
|
5
|
+
gap:var(--space-notification-panel-container-body-gap, 16px);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.title{
|
|
9
|
+
position:sticky;
|
|
10
|
+
z-index:1;
|
|
11
|
+
top:4px;
|
|
12
|
+
display:flex;
|
|
13
|
+
justify-content:center;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.text{
|
|
17
|
+
padding-left:var(--space-notification-panel-date-horizontal-padding, 8px);
|
|
18
|
+
padding-right:var(--space-notification-panel-date-horizontal-padding, 8px);
|
|
19
|
+
height:var(--size-notification-panel-date-height, 20px);
|
|
20
|
+
border-radius:var(--radius-chips-m, 20px);
|
|
21
|
+
display:inline-flex;
|
|
22
|
+
align-items:center;
|
|
23
|
+
justify-content:center;
|
|
24
|
+
color:var(--sys-neutral-text-disabled, #aaaebd);
|
|
25
|
+
background-color:var(--sys-neutral-background1-level, #fdfdfd);
|
|
26
|
+
border-color:var(--sys-neutral-decor-default, #dde0ea);
|
|
27
|
+
border-style:solid;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.content{
|
|
31
|
+
display:flex;
|
|
32
|
+
flex-direction:column;
|
|
33
|
+
gap:var(--space-notification-panel-container-body-gap, 16px);
|
|
34
|
+
}
|
|
@@ -24,4 +24,5 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
24
24
|
});
|
|
25
25
|
__exportStar(require("./NotificationPanelSettings"), exports);
|
|
26
26
|
__exportStar(require("./NotificationPanelBlank"), exports);
|
|
27
|
-
__exportStar(require("./NotificationCardStack"), exports);
|
|
27
|
+
__exportStar(require("./NotificationCardStack"), exports);
|
|
28
|
+
__exportStar(require("./NotificationPanelGroup"), exports);
|
|
@@ -101,4 +101,12 @@
|
|
|
101
101
|
-moz-column-gap:var(--dimension-1m, 8px);
|
|
102
102
|
column-gap:var(--dimension-1m, 8px);
|
|
103
103
|
align-items:center;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.actionsRow{
|
|
107
|
+
display:flex;
|
|
108
|
+
-moz-column-gap:var(--dimension-1m, 8px);
|
|
109
|
+
column-gap:var(--dimension-1m, 8px);
|
|
110
|
+
align-items:center;
|
|
111
|
+
justify-content:space-between;
|
|
104
112
|
}
|
|
@@ -15,6 +15,7 @@ import { useEffect, useMemo, useRef, useState } from 'react';
|
|
|
15
15
|
import { ButtonSimple, ButtonTonal } from '@snack-uikit/button';
|
|
16
16
|
import { KebabSVG } from '@snack-uikit/icons';
|
|
17
17
|
import { Link } from '@snack-uikit/link';
|
|
18
|
+
import { StatusIndicator } from '@snack-uikit/status';
|
|
18
19
|
import { TruncateString } from '@snack-uikit/truncate-string';
|
|
19
20
|
import { Typography } from '@snack-uikit/typography';
|
|
20
21
|
import { extractSupportProps } from '@snack-uikit/utils';
|
|
@@ -56,5 +57,5 @@ export function NotificationCard(_a) {
|
|
|
56
57
|
};
|
|
57
58
|
return (_jsxs("div", Object.assign({ ref: cardRef, role: 'button', onClick: onClick, tabIndex: 0 }, extractSupportProps(rest), { "data-appearance": appearance, "data-unread": unread || undefined, "data-clickable": Boolean(onClick) || undefined, "data-droplist-open": isDroplistOpen || undefined, className: cn(styles.notificationCard, className), children: [(actions === null || actions === void 0 ? void 0 : actions.length) && (_jsx(ActionsButton, { className: styles.notificationCardFunction, actions: actions, open: isDroplistOpen, setDroplistOpen: setDroplistOpen, size: 's', icon: _jsx(KebabSVG, {}) })), label && (_jsx(Typography.LightLabelS, { tag: 'div', className: styles.notificationCardLabel, children: _jsx(TruncateString, { maxLines: 1, text: label, "data-test-id": TEST_IDS.label }) })), _jsxs("div", { className: styles.notificationCardTitle, children: [_jsx("div", { className: styles.notificationCardTitleIcon, children: icon }), _jsx(Typography.SansTitleS, { tag: 'div', className: styles.notificationCardTitleText, children: _jsx(TruncateString, { maxLines: 2, text: title, "data-test-id": TEST_IDS.title }) })] }), content && (_jsx(Typography.SansBodyS, { tag: 'div', className: styles.notificationCardContent, "data-test-id": TEST_IDS.content, children: content })), (primaryButton || secondaryButton) && (
|
|
58
59
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
59
|
-
_jsxs("div", { className: styles.notificationCardButtons, onClick: stopPropagationClick, children: [secondaryButton && (_jsx(ButtonSimple, Object.assign({}, secondaryButton, { appearance: 'neutral', size: 's', "data-test-id": TEST_IDS.primaryButton }))), primaryButton && (_jsx(ButtonTonal, Object.assign({}, primaryButton, { appearance: 'neutral', size: 's', "data-test-id": TEST_IDS.secondaryButton })))] })), showFooter && (_jsxs("div", { className: styles.notificationCardFooter, children: [link && (_jsx(Link, Object.assign({}, link, { onClick: handleLinkClick, appearance: 'primary', textMode: 'accent', size: 's', "data-test-id": TEST_IDS.link }))), date && (_jsx(Typography.LightLabelS, { className: styles.notificationCardDate, "data-test-id": TEST_IDS.date, children: date }))] }))] })));
|
|
60
|
+
_jsxs("div", { className: styles.notificationCardButtons, onClick: stopPropagationClick, children: [secondaryButton && (_jsx(ButtonSimple, Object.assign({}, secondaryButton, { appearance: 'neutral', size: 's', "data-test-id": TEST_IDS.primaryButton }))), primaryButton && (_jsx(ButtonTonal, Object.assign({}, primaryButton, { appearance: 'neutral', size: 's', "data-test-id": TEST_IDS.secondaryButton })))] })), showFooter && (_jsxs("div", { className: styles.notificationCardFooter, children: [link && (_jsx(Link, Object.assign({}, link, { onClick: handleLinkClick, appearance: 'primary', textMode: 'accent', size: 's', "data-test-id": TEST_IDS.link }))), date && (_jsx(Typography.LightLabelS, { className: styles.notificationCardDate, "data-test-id": TEST_IDS.date, children: date }))] })), unread && _jsx(StatusIndicator, { className: styles.statusIndicator, size: 'xs', appearance: 'primary' })] })));
|
|
60
61
|
}
|
|
@@ -23,6 +23,12 @@
|
|
|
23
23
|
box-sizing:border-box;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
.statusIndicator{
|
|
27
|
+
position:absolute;
|
|
28
|
+
top:4px;
|
|
29
|
+
right:4px;
|
|
30
|
+
}
|
|
31
|
+
|
|
26
32
|
.notificationCard{
|
|
27
33
|
padding-left:var(--space-notification-panel-card-padding-horizontal, 12px);
|
|
28
34
|
padding-right:var(--space-notification-panel-card-padding-horizontal, 12px);
|
|
@@ -3,7 +3,7 @@ import { ButtonFunctionProps } from '@snack-uikit/button';
|
|
|
3
3
|
import { SegmentedControlProps } from '@snack-uikit/segmented-control';
|
|
4
4
|
import { TooltipProps } from '@snack-uikit/tooltip';
|
|
5
5
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
6
|
-
import { NotificationCardStack, NotificationCardStackProps, NotificationPanelBlank, NotificationPanelBlankProps, NotificationPanelSettingsProps } from './components';
|
|
6
|
+
import { NotificationCardStack, NotificationCardStackProps, NotificationPanelBlank, NotificationPanelBlankProps, NotificationPanelGroup, NotificationPanelGroupProps, NotificationPanelSettingsProps } from './components';
|
|
7
7
|
import { NotificationPanelDivider, NotificationPanelDividerProps } from './components/NotificationPanelDivider';
|
|
8
8
|
export type { NotificationPanelBlankProps };
|
|
9
9
|
export type NotificationPanelProps = WithSupportProps<{
|
|
@@ -13,6 +13,13 @@ export type NotificationPanelProps = WithSupportProps<{
|
|
|
13
13
|
settings?: NotificationPanelSettingsProps;
|
|
14
14
|
/** Сегменты для фильтрации */
|
|
15
15
|
segments?: Omit<SegmentedControlProps, 'size' | 'data-test-id'>;
|
|
16
|
+
/** Переключатель для фильтрации */
|
|
17
|
+
chipToggle?: {
|
|
18
|
+
label: string;
|
|
19
|
+
checked: boolean;
|
|
20
|
+
defaultChecked?: boolean;
|
|
21
|
+
onChange: (checked: boolean) => void;
|
|
22
|
+
};
|
|
16
23
|
/** Кнопка в "шапке" панели */
|
|
17
24
|
readAllButton?: Omit<ButtonFunctionProps, 'data-test-id'> & {
|
|
18
25
|
tooltip?: TooltipProps;
|
|
@@ -35,7 +42,7 @@ export type NotificationPanelProps = WithSupportProps<{
|
|
|
35
42
|
scrollContainerRef?: RefObject<HTMLElement>;
|
|
36
43
|
}>;
|
|
37
44
|
/** Компонент панели для уведомлений */
|
|
38
|
-
export declare function NotificationPanel({ title, settings, segments, readAllButton, footerButton, content, loading, skeletonsAmount, scrollEndRef, scrollContainerRef, className, ...rest }: NotificationPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
45
|
+
export declare function NotificationPanel({ title, settings, segments, readAllButton, footerButton, content, loading, skeletonsAmount, scrollEndRef, scrollContainerRef, className, chipToggle, ...rest }: NotificationPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
39
46
|
export declare namespace NotificationPanel {
|
|
40
47
|
const Blank: typeof NotificationPanelBlank;
|
|
41
48
|
type BlankProps = NotificationPanelBlankProps;
|
|
@@ -43,4 +50,6 @@ export declare namespace NotificationPanel {
|
|
|
43
50
|
type DividerProps = NotificationPanelDividerProps;
|
|
44
51
|
const Stack: typeof NotificationCardStack;
|
|
45
52
|
type StackProps = NotificationCardStackProps;
|
|
53
|
+
const Group: typeof NotificationPanelGroup;
|
|
54
|
+
type GroupProps = NotificationPanelGroupProps;
|
|
46
55
|
}
|
|
@@ -13,6 +13,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
13
13
|
import cn from 'classnames';
|
|
14
14
|
import { useMemo } from 'react';
|
|
15
15
|
import { ButtonFunction } from '@snack-uikit/button';
|
|
16
|
+
import { ChipToggle } from '@snack-uikit/chips';
|
|
16
17
|
import { Scroll } from '@snack-uikit/scroll';
|
|
17
18
|
import { SegmentedControl } from '@snack-uikit/segmented-control';
|
|
18
19
|
import { SkeletonContextProvider, WithSkeleton } from '@snack-uikit/skeleton';
|
|
@@ -20,19 +21,24 @@ import { TruncateString } from '@snack-uikit/truncate-string';
|
|
|
20
21
|
import { Typography } from '@snack-uikit/typography';
|
|
21
22
|
import { extractSupportProps } from '@snack-uikit/utils';
|
|
22
23
|
import { NotificationCardSkeleton } from '../NotificationCard/components';
|
|
23
|
-
import { NotificationCardStack, NotificationPanelBlank, NotificationPanelSettings, } from './components';
|
|
24
|
+
import { NotificationCardStack, NotificationPanelBlank, NotificationPanelGroup, NotificationPanelSettings, } from './components';
|
|
24
25
|
import { NotificationPanelDivider } from './components/NotificationPanelDivider';
|
|
25
26
|
import { TEST_IDS } from './constants';
|
|
26
27
|
import { WithTooltip } from './helperComponents';
|
|
27
28
|
import styles from './styles.module.css';
|
|
28
29
|
/** Компонент панели для уведомлений */
|
|
29
30
|
export function NotificationPanel(_a) {
|
|
30
|
-
var { title, settings, segments, readAllButton, footerButton, content, loading, skeletonsAmount = 2, scrollEndRef, scrollContainerRef, className
|
|
31
|
+
var { title, settings, segments, readAllButton, footerButton, content, loading, skeletonsAmount = 2, scrollEndRef, scrollContainerRef, className, chipToggle = {
|
|
32
|
+
label: 'Label',
|
|
33
|
+
checked: false,
|
|
34
|
+
onChange: () => { },
|
|
35
|
+
} } = _a, rest = __rest(_a, ["title", "settings", "segments", "readAllButton", "footerButton", "content", "loading", "skeletonsAmount", "scrollEndRef", "scrollContainerRef", "className", "chipToggle"]);
|
|
31
36
|
const skeletons = useMemo(() => Array.from({ length: skeletonsAmount }, (_, i) => i), [skeletonsAmount]);
|
|
32
|
-
return (_jsxs("div", Object.assign({ className: cn(styles.wrapper, className) }, extractSupportProps(rest), { children: [_jsxs("div", { className: styles.notificationPanelHeader, children: [_jsxs("div", { className: styles.notificationPanelHeadline, children: [_jsx(Typography.SansHeadlineS, { className: styles.notificationPanelTitle, children: _jsx(TruncateString, { text: title, "data-test-id": TEST_IDS.title }) }), _jsxs("div", { className: styles.notificationPanelHeaderActions, children: [readAllButton && (_jsx(WithTooltip, { tooltip: readAllButton.tooltip, children: _jsx(ButtonFunction, Object.assign({}, readAllButton, { onClick: readAllButton.onClick, size: 'xs', disabled: readAllButton.disabled || loading, "data-test-id": TEST_IDS.readAll })) })), settings && _jsx(NotificationPanelSettings, Object.assign({}, settings))] })] }),
|
|
37
|
+
return (_jsxs("div", Object.assign({ className: cn(styles.wrapper, className) }, extractSupportProps(rest), { children: [_jsxs("div", { className: styles.notificationPanelHeader, children: [_jsxs("div", { className: styles.notificationPanelHeadline, children: [_jsx(Typography.SansHeadlineS, { className: styles.notificationPanelTitle, children: _jsx(TruncateString, { text: title, "data-test-id": TEST_IDS.title }) }), _jsxs("div", { className: styles.notificationPanelHeaderActions, children: [readAllButton && (_jsx(WithTooltip, { tooltip: readAllButton.tooltip, children: _jsx(ButtonFunction, Object.assign({}, readAllButton, { onClick: readAllButton.onClick, size: 'xs', disabled: readAllButton.disabled || loading, "data-test-id": TEST_IDS.readAll })) })), settings && _jsx(NotificationPanelSettings, Object.assign({}, settings))] })] }), _jsxs("div", { className: styles.actionsRow, children: [segments && (_jsx(SegmentedControl, Object.assign({}, segments, { size: 'xs', items: segments.items.map(item => (Object.assign(Object.assign({}, item), { disabled: item.disabled || loading }))), "data-test-id": TEST_IDS.segments }))), chipToggle && (_jsx(ChipToggle, { size: 'xs', disabled: loading, label: chipToggle.label, onChange: chipToggle.onChange, checked: chipToggle.checked }))] })] }), _jsx(Scroll, { size: 'm', ref: scrollContainerRef, children: _jsxs("div", { className: styles.notificationPanelBody, children: [content, loading && (_jsx(SkeletonContextProvider, { loading: loading || false, children: skeletons.map(skeleton => (_jsx(WithSkeleton, { skeleton: _jsx(NotificationCardSkeleton, {}) }, skeleton))) })), _jsx("div", { className: styles.scrollStub, ref: scrollEndRef })] }) }), footerButton && (_jsx("button", { type: 'button', onClick: footerButton.onClick, className: styles.notificationPanelFooterButton, "data-test-id": TEST_IDS.footerButton, children: _jsx(Typography.SansLabelS, { children: footerButton.label }) }))] })));
|
|
33
38
|
}
|
|
34
39
|
(function (NotificationPanel) {
|
|
35
40
|
NotificationPanel.Blank = NotificationPanelBlank;
|
|
36
41
|
NotificationPanel.Divider = NotificationPanelDivider;
|
|
37
42
|
NotificationPanel.Stack = NotificationCardStack;
|
|
43
|
+
NotificationPanel.Group = NotificationPanelGroup;
|
|
38
44
|
})(NotificationPanel || (NotificationPanel = {}));
|
|
@@ -23,5 +23,9 @@ export type NotificationCardStackProps = {
|
|
|
23
23
|
* Список действий в выпадающем меню
|
|
24
24
|
*/
|
|
25
25
|
actions?: Action[];
|
|
26
|
+
/**
|
|
27
|
+
* Состояние непрочитанных карточек
|
|
28
|
+
*/
|
|
29
|
+
unread?: boolean;
|
|
26
30
|
};
|
|
27
|
-
export declare function NotificationCardStack({ children, defaultOpen, onOpenChanged, title, actions, }: NotificationCardStackProps): import("react/jsx-runtime").JSX.Element | null;
|
|
31
|
+
export declare function NotificationCardStack({ children, defaultOpen, onOpenChanged, title, actions, unread, }: NotificationCardStackProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -9,7 +9,7 @@ import { useAnimatedOpening } from './hooks';
|
|
|
9
9
|
import styles from './styles.module.css';
|
|
10
10
|
import { cloneCard } from './utils';
|
|
11
11
|
const ANIMATION_DURATION = 0.3;
|
|
12
|
-
export function NotificationCardStack({ children, defaultOpen, onOpenChanged, title, actions, }) {
|
|
12
|
+
export function NotificationCardStack({ children, defaultOpen, onOpenChanged, title, actions, unread, }) {
|
|
13
13
|
const [actionsOpen, setActionsOpen] = useState(false);
|
|
14
14
|
const { open, toggleOpen, isVisible } = useAnimatedOpening({
|
|
15
15
|
defaultOpen,
|
|
@@ -23,6 +23,8 @@ export function NotificationCardStack({ children, defaultOpen, onOpenChanged, ti
|
|
|
23
23
|
if (!stack.length) {
|
|
24
24
|
return _jsx(_Fragment, { children: first });
|
|
25
25
|
}
|
|
26
|
-
const firstCardElement = open
|
|
26
|
+
const firstCardElement = open
|
|
27
|
+
? first
|
|
28
|
+
: cloneCard(first, componentProps => (Object.assign(Object.assign({}, componentProps), { onClick: toggleOpen, unread: unread || componentProps.unread })));
|
|
27
29
|
return (_jsxs("div", { className: styles.container, style: { '--snack-notification-stack-animation-duration': `${ANIMATION_DURATION}s` }, "data-test-id": TEST_IDS.cardStack.wrapper, children: [_jsxs("div", { className: styles.header, "data-test-id": TEST_IDS.cardStack.headline, children: [_jsx("label", { className: styles.title, onClick: toggleOpen, "data-test-id": TEST_IDS.cardStack.title, children: title }), _jsxs("div", { className: styles.right, children: [actions && actions.length > 0 && (_jsx(ActionsButton, { actions: actions, open: actionsOpen, setDroplistOpen: setActionsOpen, size: 'xs', icon: _jsx(KebabSVG, {}) })), _jsx(ButtonFunction, { size: 'xs', onClick: toggleOpen, "data-test-id": TEST_IDS.cardStack.openButton, icon: open ? _jsx(ChevronUpSVG, {}) : _jsx(ChevronDownSVG, {}) })] })] }), _jsxs("div", { className: styles.cards, children: [_jsxs("div", { className: styles.first, children: [_jsx(StackTail, { open: open, count: stack.length }), firstCardElement] }), _jsx("div", { className: styles.stack, "data-open": open || undefined, "data-tail-size": stack.length, children: _jsx("div", { className: styles.animationContainer, children: isVisible ? stack : [] }) })] })] }));
|
|
28
30
|
}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
|
|
2
|
+
type ComponentProps = Record<string, unknown>;
|
|
3
|
+
export declare const cloneCard: (element: ReactNode, props: (componentProps: ComponentProps) => ComponentProps) => string | number | boolean | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined;
|
|
4
|
+
export {};
|
|
@@ -9,7 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import { jsx as _jsx
|
|
12
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
13
|
import cn from 'classnames';
|
|
14
14
|
import { InfoBlock } from '@snack-uikit/info-block';
|
|
15
15
|
import styles from './styles.module.css';
|
|
@@ -17,5 +17,5 @@ import styles from './styles.module.css';
|
|
|
17
17
|
export function NotificationPanelBlank(_a) {
|
|
18
18
|
var _b;
|
|
19
19
|
var { icon, className } = _a, props = __rest(_a, ["icon", "className"]);
|
|
20
|
-
return (_jsx(
|
|
20
|
+
return (_jsx("div", { className: styles.wrapper, children: _jsx(InfoBlock, Object.assign({}, props, { icon: icon ? Object.assign(Object.assign({}, icon), { appearance: (_b = icon.appearance) !== null && _b !== void 0 ? _b : 'neutral' }) : undefined, size: 'l', align: 'vertical', className: cn(styles.notificationPanelBlank, className) })) }));
|
|
21
21
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { WithSupportProps } from '@snack-uikit/utils';
|
|
3
|
+
export type NotificationPanelGroupProps = WithSupportProps<{
|
|
4
|
+
/** Заголовок группы */
|
|
5
|
+
title: string;
|
|
6
|
+
/** Содержимое группы */
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/** CSS-класс */
|
|
9
|
+
className?: string;
|
|
10
|
+
}>;
|
|
11
|
+
/** Группа уведомлений с заголовком внутри панели */
|
|
12
|
+
export declare function NotificationPanelGroup({ title, children, className, ...rest }: NotificationPanelGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
import cn from 'classnames';
|
|
14
|
+
import { TruncateString } from '@snack-uikit/truncate-string';
|
|
15
|
+
import { Typography } from '@snack-uikit/typography';
|
|
16
|
+
import { extractSupportProps } from '@snack-uikit/utils';
|
|
17
|
+
import styles from './styles.module.css';
|
|
18
|
+
/** Группа уведомлений с заголовком внутри панели */
|
|
19
|
+
export function NotificationPanelGroup(_a) {
|
|
20
|
+
var { title, children, className } = _a, rest = __rest(_a, ["title", "children", "className"]);
|
|
21
|
+
return (_jsxs("div", Object.assign({ className: cn(styles.root, className) }, extractSupportProps(rest), { children: [_jsx("div", { className: styles.title, children: _jsx(Typography.LightLabelS, { className: styles.text, tag: 'span', children: _jsx(TruncateString, { text: title }) }) }), _jsx("div", { className: styles.content, children: children })] })));
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NotificationPanelGroup, type NotificationPanelGroupProps } from './NotificationPanelGroup';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NotificationPanelGroup } from './NotificationPanelGroup';
|
package/dist/esm/components/NotificationPanel/components/NotificationPanelGroup/styles.module.css
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
.root{
|
|
2
|
+
position:relative;
|
|
3
|
+
display:flex;
|
|
4
|
+
flex-direction:column;
|
|
5
|
+
gap:var(--space-notification-panel-container-body-gap, 16px);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.title{
|
|
9
|
+
position:sticky;
|
|
10
|
+
z-index:1;
|
|
11
|
+
top:4px;
|
|
12
|
+
display:flex;
|
|
13
|
+
justify-content:center;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.text{
|
|
17
|
+
padding-left:var(--space-notification-panel-date-horizontal-padding, 8px);
|
|
18
|
+
padding-right:var(--space-notification-panel-date-horizontal-padding, 8px);
|
|
19
|
+
height:var(--size-notification-panel-date-height, 20px);
|
|
20
|
+
border-radius:var(--radius-chips-m, 20px);
|
|
21
|
+
display:inline-flex;
|
|
22
|
+
align-items:center;
|
|
23
|
+
justify-content:center;
|
|
24
|
+
color:var(--sys-neutral-text-disabled, #aaaebd);
|
|
25
|
+
background-color:var(--sys-neutral-background1-level, #fdfdfd);
|
|
26
|
+
border-color:var(--sys-neutral-decor-default, #dde0ea);
|
|
27
|
+
border-style:solid;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.content{
|
|
31
|
+
display:flex;
|
|
32
|
+
flex-direction:column;
|
|
33
|
+
gap:var(--space-notification-panel-container-body-gap, 16px);
|
|
34
|
+
}
|
|
@@ -101,4 +101,12 @@
|
|
|
101
101
|
-moz-column-gap:var(--dimension-1m, 8px);
|
|
102
102
|
column-gap:var(--dimension-1m, 8px);
|
|
103
103
|
align-items:center;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.actionsRow{
|
|
107
|
+
display:flex;
|
|
108
|
+
-moz-column-gap:var(--dimension-1m, 8px);
|
|
109
|
+
column-gap:var(--dimension-1m, 8px);
|
|
110
|
+
align-items:center;
|
|
111
|
+
justify-content:space-between;
|
|
104
112
|
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "Notification",
|
|
7
|
-
"version": "0.13.
|
|
7
|
+
"version": "0.13.31-preview-7cd3a502.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"scripts": {},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@snack-uikit/button": "0.19.17",
|
|
40
|
+
"@snack-uikit/chips": "0.28.17",
|
|
40
41
|
"@snack-uikit/icons": "0.27.7",
|
|
41
42
|
"@snack-uikit/info-block": "0.6.39",
|
|
42
43
|
"@snack-uikit/link": "0.17.19",
|
|
@@ -45,6 +46,7 @@
|
|
|
45
46
|
"@snack-uikit/scroll": "0.10.8",
|
|
46
47
|
"@snack-uikit/segmented-control": "0.6.19",
|
|
47
48
|
"@snack-uikit/skeleton": "0.6.10",
|
|
49
|
+
"@snack-uikit/status": "0.10.11",
|
|
48
50
|
"@snack-uikit/tag": "0.15.17",
|
|
49
51
|
"@snack-uikit/tooltip": "0.18.11",
|
|
50
52
|
"@snack-uikit/truncate-string": "0.7.10",
|
|
@@ -53,5 +55,5 @@
|
|
|
53
55
|
"classnames": "2.5.1",
|
|
54
56
|
"uncontrollable": "9.0.0"
|
|
55
57
|
},
|
|
56
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "32e4b2dbb52e9da27a48b5bee0e238a0ab785b1d"
|
|
57
59
|
}
|
|
@@ -4,6 +4,7 @@ import { ElementType, MouseEventHandler, ReactNode, useEffect, useMemo, useRef,
|
|
|
4
4
|
import { ButtonSimple, ButtonSimpleProps, ButtonTonal, ButtonTonalProps } from '@snack-uikit/button';
|
|
5
5
|
import { KebabSVG } from '@snack-uikit/icons';
|
|
6
6
|
import { Link, PickLinkProps } from '@snack-uikit/link';
|
|
7
|
+
import { StatusIndicator } from '@snack-uikit/status';
|
|
7
8
|
import { TruncateString } from '@snack-uikit/truncate-string';
|
|
8
9
|
import { Typography } from '@snack-uikit/typography';
|
|
9
10
|
import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
|
|
@@ -180,6 +181,8 @@ export function NotificationCard<LinkElement extends ElementType = 'a'>({
|
|
|
180
181
|
)}
|
|
181
182
|
</div>
|
|
182
183
|
)}
|
|
184
|
+
|
|
185
|
+
{unread && <StatusIndicator className={styles.statusIndicator} size='xs' appearance='primary' />}
|
|
183
186
|
</div>
|
|
184
187
|
);
|
|
185
188
|
}
|
|
@@ -29,6 +29,12 @@
|
|
|
29
29
|
box-sizing: border-box;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
.statusIndicator {
|
|
33
|
+
position: absolute;
|
|
34
|
+
top: 4px;
|
|
35
|
+
right: 4px;
|
|
36
|
+
}
|
|
37
|
+
|
|
32
38
|
.notificationCard {
|
|
33
39
|
@include styles-tokens-notification-notificationCard.composite-var(styles-tokens-notification-notificationCard.$notification-card-container);
|
|
34
40
|
|
|
@@ -2,6 +2,7 @@ import cn from 'classnames';
|
|
|
2
2
|
import { MouseEventHandler, ReactNode, RefObject, useMemo } from 'react';
|
|
3
3
|
|
|
4
4
|
import { ButtonFunction, ButtonFunctionProps } from '@snack-uikit/button';
|
|
5
|
+
import { ChipToggle } from '@snack-uikit/chips';
|
|
5
6
|
import { Scroll } from '@snack-uikit/scroll';
|
|
6
7
|
import { SegmentedControl, SegmentedControlProps } from '@snack-uikit/segmented-control';
|
|
7
8
|
import { SkeletonContextProvider, WithSkeleton } from '@snack-uikit/skeleton';
|
|
@@ -16,6 +17,8 @@ import {
|
|
|
16
17
|
NotificationCardStackProps,
|
|
17
18
|
NotificationPanelBlank,
|
|
18
19
|
NotificationPanelBlankProps,
|
|
20
|
+
NotificationPanelGroup,
|
|
21
|
+
NotificationPanelGroupProps,
|
|
19
22
|
NotificationPanelSettings,
|
|
20
23
|
NotificationPanelSettingsProps,
|
|
21
24
|
} from './components';
|
|
@@ -33,6 +36,13 @@ export type NotificationPanelProps = WithSupportProps<{
|
|
|
33
36
|
settings?: NotificationPanelSettingsProps;
|
|
34
37
|
/** Сегменты для фильтрации */
|
|
35
38
|
segments?: Omit<SegmentedControlProps, 'size' | 'data-test-id'>;
|
|
39
|
+
/** Переключатель для фильтрации */
|
|
40
|
+
chipToggle?: {
|
|
41
|
+
label: string;
|
|
42
|
+
checked: boolean;
|
|
43
|
+
defaultChecked?: boolean;
|
|
44
|
+
onChange: (checked: boolean) => void;
|
|
45
|
+
};
|
|
36
46
|
/** Кнопка в "шапке" панели */
|
|
37
47
|
readAllButton?: Omit<ButtonFunctionProps, 'data-test-id'> & {
|
|
38
48
|
tooltip?: TooltipProps;
|
|
@@ -68,6 +78,11 @@ export function NotificationPanel({
|
|
|
68
78
|
scrollEndRef,
|
|
69
79
|
scrollContainerRef,
|
|
70
80
|
className,
|
|
81
|
+
chipToggle = {
|
|
82
|
+
label: 'Label',
|
|
83
|
+
checked: false,
|
|
84
|
+
onChange: () => {},
|
|
85
|
+
},
|
|
71
86
|
...rest
|
|
72
87
|
}: NotificationPanelProps) {
|
|
73
88
|
const skeletons = useMemo(() => Array.from({ length: skeletonsAmount }, (_, i) => i), [skeletonsAmount]);
|
|
@@ -97,11 +112,11 @@ export function NotificationPanel({
|
|
|
97
112
|
</div>
|
|
98
113
|
</div>
|
|
99
114
|
|
|
100
|
-
<div>
|
|
115
|
+
<div className={styles.actionsRow}>
|
|
101
116
|
{segments && (
|
|
102
117
|
<SegmentedControl
|
|
103
118
|
{...segments}
|
|
104
|
-
size='
|
|
119
|
+
size='xs'
|
|
105
120
|
items={segments.items.map(item => ({
|
|
106
121
|
...item,
|
|
107
122
|
disabled: item.disabled || loading,
|
|
@@ -109,6 +124,15 @@ export function NotificationPanel({
|
|
|
109
124
|
data-test-id={TEST_IDS.segments}
|
|
110
125
|
/>
|
|
111
126
|
)}
|
|
127
|
+
{chipToggle && (
|
|
128
|
+
<ChipToggle
|
|
129
|
+
size='xs'
|
|
130
|
+
disabled={loading}
|
|
131
|
+
label={chipToggle.label}
|
|
132
|
+
onChange={chipToggle.onChange}
|
|
133
|
+
checked={chipToggle.checked}
|
|
134
|
+
/>
|
|
135
|
+
)}
|
|
112
136
|
</div>
|
|
113
137
|
</div>
|
|
114
138
|
|
|
@@ -148,4 +172,6 @@ export namespace NotificationPanel {
|
|
|
148
172
|
export type DividerProps = NotificationPanelDividerProps;
|
|
149
173
|
export const Stack: typeof NotificationCardStack = NotificationCardStack;
|
|
150
174
|
export type StackProps = NotificationCardStackProps;
|
|
175
|
+
export const Group: typeof NotificationPanelGroup = NotificationPanelGroup;
|
|
176
|
+
export type GroupProps = NotificationPanelGroupProps;
|
|
151
177
|
}
|
package/src/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.tsx
CHANGED
|
@@ -33,6 +33,10 @@ export type NotificationCardStackProps = {
|
|
|
33
33
|
* Список действий в выпадающем меню
|
|
34
34
|
*/
|
|
35
35
|
actions?: Action[];
|
|
36
|
+
/**
|
|
37
|
+
* Состояние непрочитанных карточек
|
|
38
|
+
*/
|
|
39
|
+
unread?: boolean;
|
|
36
40
|
};
|
|
37
41
|
|
|
38
42
|
const ANIMATION_DURATION = 0.3;
|
|
@@ -43,6 +47,7 @@ export function NotificationCardStack({
|
|
|
43
47
|
onOpenChanged,
|
|
44
48
|
title,
|
|
45
49
|
actions,
|
|
50
|
+
unread,
|
|
46
51
|
}: NotificationCardStackProps) {
|
|
47
52
|
const [actionsOpen, setActionsOpen] = useState(false);
|
|
48
53
|
const { open, toggleOpen, isVisible } = useAnimatedOpening({
|
|
@@ -61,7 +66,13 @@ export function NotificationCardStack({
|
|
|
61
66
|
return <>{first}</>;
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
const firstCardElement = open
|
|
69
|
+
const firstCardElement = open
|
|
70
|
+
? first
|
|
71
|
+
: cloneCard(first, componentProps => ({
|
|
72
|
+
...componentProps,
|
|
73
|
+
onClick: toggleOpen,
|
|
74
|
+
unread: unread || componentProps.unread,
|
|
75
|
+
}));
|
|
65
76
|
|
|
66
77
|
return (
|
|
67
78
|
<div
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { cloneElement, isValidElement, ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
type ComponentProps = Record<string, unknown>;
|
|
4
|
+
|
|
5
|
+
export const cloneCard = (element: ReactNode, props: (componentProps: ComponentProps) => ComponentProps) => {
|
|
4
6
|
if (!isValidElement(element)) {
|
|
5
7
|
return element;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
return cloneElement(element,
|
|
9
|
-
...element.props,
|
|
10
|
-
...props,
|
|
11
|
-
});
|
|
10
|
+
return cloneElement(element, props(element.props));
|
|
12
11
|
};
|
|
@@ -9,7 +9,7 @@ export type NotificationPanelBlankProps = Omit<InfoBlockProps, 'footer' | 'align
|
|
|
9
9
|
/** Компонента для "заглушки" вместо карточек в панели */
|
|
10
10
|
export function NotificationPanelBlank({ icon, className, ...props }: NotificationPanelBlankProps) {
|
|
11
11
|
return (
|
|
12
|
-
|
|
12
|
+
<div className={styles.wrapper}>
|
|
13
13
|
<InfoBlock
|
|
14
14
|
{...props}
|
|
15
15
|
icon={icon ? { ...icon, appearance: icon.appearance ?? 'neutral' } : undefined}
|
|
@@ -17,6 +17,6 @@ export function NotificationPanelBlank({ icon, className, ...props }: Notificati
|
|
|
17
17
|
align='vertical'
|
|
18
18
|
className={cn(styles.notificationPanelBlank, className)}
|
|
19
19
|
/>
|
|
20
|
-
|
|
20
|
+
</div>
|
|
21
21
|
);
|
|
22
22
|
}
|
package/src/components/NotificationPanel/components/NotificationPanelBlank/styles.module.scss
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
@use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-notification-notificationPanel';
|
|
2
2
|
|
|
3
|
+
.wrapper {
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
min-height: 316px; // two skeleton cards height
|
|
8
|
+
}
|
|
9
|
+
|
|
3
10
|
.notificationPanelBlank {
|
|
4
11
|
@include styles-tokens-notification-notificationPanel.composite-var(styles-tokens-notification-notificationPanel.$notification-panel-body-info-container);
|
|
5
12
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import cn from 'classnames';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
import { TruncateString } from '@snack-uikit/truncate-string';
|
|
5
|
+
import { Typography } from '@snack-uikit/typography';
|
|
6
|
+
import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
|
|
7
|
+
|
|
8
|
+
import styles from './styles.module.scss';
|
|
9
|
+
|
|
10
|
+
export type NotificationPanelGroupProps = WithSupportProps<{
|
|
11
|
+
/** Заголовок группы */
|
|
12
|
+
title: string;
|
|
13
|
+
/** Содержимое группы */
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
/** CSS-класс */
|
|
16
|
+
className?: string;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
/** Группа уведомлений с заголовком внутри панели */
|
|
20
|
+
export function NotificationPanelGroup({ title, children, className, ...rest }: NotificationPanelGroupProps) {
|
|
21
|
+
return (
|
|
22
|
+
<div className={cn(styles.root, className)} {...extractSupportProps(rest)}>
|
|
23
|
+
<div className={styles.title}>
|
|
24
|
+
<Typography.LightLabelS className={styles.text} tag='span'>
|
|
25
|
+
<TruncateString text={title} />
|
|
26
|
+
</Typography.LightLabelS>
|
|
27
|
+
</div>
|
|
28
|
+
<div className={styles.content}>{children}</div>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NotificationPanelGroup, type NotificationPanelGroupProps } from './NotificationPanelGroup';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
@use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-notification-notificationPanel' as panel;
|
|
2
|
+
@use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-element' as element;
|
|
3
|
+
|
|
4
|
+
.root {
|
|
5
|
+
position: relative;
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
gap: element.$space-notification-panel-container-body-gap;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.title {
|
|
12
|
+
position: sticky;
|
|
13
|
+
z-index: 1; /* stylelint-disable-line declaration-property-value-allowed-list */
|
|
14
|
+
top: 4px;
|
|
15
|
+
|
|
16
|
+
display: flex;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.text {
|
|
22
|
+
@include element.composite-var(panel.$notification-panel-date-container);
|
|
23
|
+
|
|
24
|
+
display: inline-flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: center;
|
|
27
|
+
|
|
28
|
+
color: panel.$sys-neutral-text-disabled;
|
|
29
|
+
|
|
30
|
+
background-color: panel.$sys-neutral-background1-level;
|
|
31
|
+
border-color: panel.$sys-neutral-decor-default;
|
|
32
|
+
border-style: solid;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.content {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
gap: element.$space-notification-panel-container-body-gap;
|
|
39
|
+
}
|
|
@@ -106,4 +106,11 @@
|
|
|
106
106
|
display: flex;
|
|
107
107
|
column-gap: styles-tokens-notification-notificationPanel.$dimension-1m;
|
|
108
108
|
align-items: center;
|
|
109
|
-
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.actionsRow {
|
|
112
|
+
display: flex;
|
|
113
|
+
column-gap: styles-tokens-notification-notificationPanel.$dimension-1m;
|
|
114
|
+
align-items: center;
|
|
115
|
+
justify-content: space-between;
|
|
116
|
+
}
|