@snack-uikit/notification 0.13.25 → 0.13.26

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 (101) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +70 -0
  3. package/dist/cjs/components/NotificationCard/NotificationCard.d.ts +2 -7
  4. package/dist/cjs/components/NotificationCard/NotificationCard.js +11 -4
  5. package/dist/cjs/components/NotificationCard/components/index.d.ts +0 -1
  6. package/dist/cjs/components/NotificationCard/components/index.js +0 -1
  7. package/dist/cjs/components/NotificationCard/helpers.d.ts +2 -0
  8. package/dist/cjs/components/NotificationCard/helpers.js +4 -0
  9. package/dist/cjs/components/NotificationCard/styles.module.css +10 -9
  10. package/dist/cjs/components/NotificationPanel/NotificationPanel.d.ts +3 -1
  11. package/dist/cjs/components/NotificationPanel/NotificationPanel.js +14 -11
  12. package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.d.ts +27 -0
  13. package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.js +101 -0
  14. package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/hooks.d.ts +12 -0
  15. package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/hooks.js +36 -0
  16. package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/index.d.ts +1 -0
  17. package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/index.js +25 -0
  18. package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/styles.module.css +74 -0
  19. package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/utils.d.ts +2 -0
  20. package/dist/cjs/components/NotificationPanel/components/NotificationCardStack/utils.js +14 -0
  21. package/dist/cjs/components/NotificationPanel/components/NotificationPanelDivider/NotificationPanelDivider.js +10 -3
  22. package/dist/cjs/components/NotificationPanel/components/NotificationPanelDivider/styles.module.css +12 -3
  23. package/dist/cjs/components/NotificationPanel/components/index.d.ts +1 -0
  24. package/dist/cjs/components/NotificationPanel/components/index.js +2 -1
  25. package/dist/cjs/components/NotificationPanel/constants.d.ts +6 -0
  26. package/dist/cjs/components/NotificationPanel/constants.js +7 -1
  27. package/dist/cjs/components/NotificationPanel/helperComponents/StackTail/StackTail.d.ts +6 -0
  28. package/dist/cjs/components/NotificationPanel/helperComponents/StackTail/StackTail.js +33 -0
  29. package/dist/cjs/components/NotificationPanel/helperComponents/StackTail/index.d.ts +1 -0
  30. package/dist/cjs/components/NotificationPanel/helperComponents/StackTail/index.js +25 -0
  31. package/dist/cjs/components/NotificationPanel/helperComponents/StackTail/styles.module.css +53 -0
  32. package/dist/cjs/components/NotificationPanel/helperComponents/WithTooltip/WithTooltip.d.ts +1 -1
  33. package/dist/cjs/components/NotificationPanel/styles.module.css +7 -4
  34. package/dist/cjs/helperComponents/ActionsButton/ActionsButton.d.ts +16 -0
  35. package/dist/cjs/helperComponents/ActionsButton/ActionsButton.js +72 -0
  36. package/dist/cjs/helperComponents/ActionsButton/index.d.ts +1 -0
  37. package/dist/cjs/helperComponents/ActionsButton/index.js +25 -0
  38. package/dist/cjs/helperComponents/ActionsButton/styles.module.css +3 -0
  39. package/dist/esm/components/NotificationCard/NotificationCard.d.ts +2 -7
  40. package/dist/esm/components/NotificationCard/NotificationCard.js +6 -3
  41. package/dist/esm/components/NotificationCard/components/index.d.ts +0 -1
  42. package/dist/esm/components/NotificationCard/components/index.js +0 -1
  43. package/dist/esm/components/NotificationCard/helpers.d.ts +2 -0
  44. package/dist/esm/components/NotificationCard/helpers.js +3 -0
  45. package/dist/esm/components/NotificationCard/styles.module.css +10 -9
  46. package/dist/esm/components/NotificationPanel/NotificationPanel.d.ts +3 -1
  47. package/dist/esm/components/NotificationPanel/NotificationPanel.js +3 -2
  48. package/dist/esm/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.d.ts +27 -0
  49. package/dist/esm/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.js +28 -0
  50. package/dist/esm/components/NotificationPanel/components/NotificationCardStack/hooks.d.ts +12 -0
  51. package/dist/esm/components/NotificationPanel/components/NotificationCardStack/hooks.js +26 -0
  52. package/dist/esm/components/NotificationPanel/components/NotificationCardStack/index.d.ts +1 -0
  53. package/dist/esm/components/NotificationPanel/components/NotificationCardStack/index.js +1 -0
  54. package/dist/esm/components/NotificationPanel/components/NotificationCardStack/styles.module.css +74 -0
  55. package/dist/esm/components/NotificationPanel/components/NotificationCardStack/utils.d.ts +2 -0
  56. package/dist/esm/components/NotificationPanel/components/NotificationCardStack/utils.js +7 -0
  57. package/dist/esm/components/NotificationPanel/components/NotificationPanelDivider/NotificationPanelDivider.js +2 -2
  58. package/dist/esm/components/NotificationPanel/components/NotificationPanelDivider/styles.module.css +12 -3
  59. package/dist/esm/components/NotificationPanel/components/index.d.ts +1 -0
  60. package/dist/esm/components/NotificationPanel/components/index.js +1 -0
  61. package/dist/esm/components/NotificationPanel/constants.d.ts +6 -0
  62. package/dist/esm/components/NotificationPanel/constants.js +6 -0
  63. package/dist/esm/components/NotificationPanel/helperComponents/StackTail/StackTail.d.ts +6 -0
  64. package/dist/esm/components/NotificationPanel/helperComponents/StackTail/StackTail.js +5 -0
  65. package/dist/esm/components/NotificationPanel/helperComponents/StackTail/index.d.ts +1 -0
  66. package/dist/esm/components/NotificationPanel/helperComponents/StackTail/index.js +1 -0
  67. package/dist/esm/components/NotificationPanel/helperComponents/StackTail/styles.module.css +53 -0
  68. package/dist/esm/components/NotificationPanel/helperComponents/WithTooltip/WithTooltip.d.ts +1 -1
  69. package/dist/esm/components/NotificationPanel/styles.module.css +7 -4
  70. package/dist/esm/helperComponents/ActionsButton/ActionsButton.d.ts +16 -0
  71. package/dist/esm/helperComponents/ActionsButton/ActionsButton.js +23 -0
  72. package/dist/esm/helperComponents/ActionsButton/index.d.ts +1 -0
  73. package/dist/esm/helperComponents/ActionsButton/index.js +1 -0
  74. package/dist/esm/helperComponents/ActionsButton/styles.module.css +3 -0
  75. package/package.json +4 -3
  76. package/src/components/NotificationCard/NotificationCard.tsx +14 -11
  77. package/src/components/NotificationCard/components/index.ts +0 -1
  78. package/src/components/NotificationCard/helpers.tsx +6 -0
  79. package/src/components/NotificationCard/styles.module.scss +3 -3
  80. package/src/components/NotificationPanel/NotificationPanel.tsx +16 -10
  81. package/src/components/NotificationPanel/components/NotificationCardStack/NotificationCardStack.tsx +107 -0
  82. package/src/components/NotificationPanel/components/NotificationCardStack/hooks.ts +45 -0
  83. package/src/components/NotificationPanel/components/NotificationCardStack/index.ts +1 -0
  84. package/src/components/NotificationPanel/components/NotificationCardStack/styles.module.scss +89 -0
  85. package/src/components/NotificationPanel/components/NotificationCardStack/utils.ts +12 -0
  86. package/src/components/NotificationPanel/components/NotificationPanelDivider/NotificationPanelDivider.tsx +5 -3
  87. package/src/components/NotificationPanel/components/NotificationPanelDivider/styles.module.scss +15 -7
  88. package/src/components/NotificationPanel/components/index.ts +1 -0
  89. package/src/components/NotificationPanel/constants.ts +6 -0
  90. package/src/components/NotificationPanel/helperComponents/StackTail/StackTail.tsx +17 -0
  91. package/src/components/NotificationPanel/helperComponents/StackTail/index.ts +1 -0
  92. package/src/components/NotificationPanel/helperComponents/StackTail/styles.module.scss +77 -0
  93. package/src/components/NotificationPanel/styles.module.scss +6 -6
  94. package/src/helperComponents/ActionsButton/ActionsButton.tsx +65 -0
  95. package/src/helperComponents/ActionsButton/index.ts +1 -0
  96. package/src/helperComponents/ActionsButton/styles.module.scss +3 -0
  97. package/dist/cjs/components/NotificationCard/components/NotificationCardFunction.d.ts +0 -7
  98. package/dist/cjs/components/NotificationCard/components/NotificationCardFunction.js +0 -64
  99. package/dist/esm/components/NotificationCard/components/NotificationCardFunction.d.ts +0 -7
  100. package/dist/esm/components/NotificationCard/components/NotificationCardFunction.js +0 -20
  101. package/src/components/NotificationCard/components/NotificationCardFunction.tsx +0 -43
@@ -9,4 +9,10 @@ export declare const TEST_IDS: {
9
9
  readAll: string;
10
10
  footerButton: string;
11
11
  skeleton: string;
12
+ cardStack: {
13
+ headline: string;
14
+ wrapper: string;
15
+ title: string;
16
+ openButton: string;
17
+ };
12
18
  };
@@ -14,5 +14,11 @@ exports.TEST_IDS = {
14
14
  },
15
15
  readAll: 'notification-panel__readAll',
16
16
  footerButton: 'notification-panel__footerButton',
17
- skeleton: 'notification-panel__skeleton'
17
+ skeleton: 'notification-panel__skeleton',
18
+ cardStack: {
19
+ headline: 'notification-panel__card-stack__headline',
20
+ wrapper: 'notification-panel__card-stack__wrapper',
21
+ title: 'notification-panel__card-stack__title',
22
+ openButton: 'notification-panel__card-stack__open-button'
23
+ }
18
24
  };
@@ -0,0 +1,6 @@
1
+ type StackTailProps = {
2
+ open: boolean;
3
+ count: number;
4
+ };
5
+ export declare function StackTail({ open, count }: StackTailProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
4
+ return mod && mod.__esModule ? mod : {
5
+ "default": mod
6
+ };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", {
9
+ value: true
10
+ });
11
+ exports.StackTail = StackTail;
12
+ const jsx_runtime_1 = require("react/jsx-runtime");
13
+ const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
14
+ function StackTail(_ref) {
15
+ let {
16
+ open,
17
+ count
18
+ } = _ref;
19
+ return (0, jsx_runtime_1.jsx)("div", {
20
+ className: styles_module_scss_1.default.container,
21
+ "data-open": open || undefined,
22
+ children: (0, jsx_runtime_1.jsxs)("div", {
23
+ className: styles_module_scss_1.default.animationContainer,
24
+ children: [count > 1 && (0, jsx_runtime_1.jsx)("div", {
25
+ className: styles_module_scss_1.default.card,
26
+ "data-level": '3'
27
+ }), (0, jsx_runtime_1.jsx)("div", {
28
+ className: styles_module_scss_1.default.card,
29
+ "data-level": '2'
30
+ })]
31
+ })
32
+ });
33
+ }
@@ -0,0 +1 @@
1
+ export * from './StackTail';
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = {
8
+ enumerable: true,
9
+ get: function () {
10
+ return m[k];
11
+ }
12
+ };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ } : function (o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ });
19
+ var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
20
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
+ };
22
+ Object.defineProperty(exports, "__esModule", {
23
+ value: true
24
+ });
25
+ __exportStar(require("./StackTail"), exports);
@@ -0,0 +1,53 @@
1
+ .container{
2
+ position:relative;
3
+ height:0;
4
+ }
5
+
6
+ .animationContainer{
7
+ position:absolute;
8
+ top:0;
9
+ bottom:calc(-1 * var(--space-notification-panel-card-stack-stack3-level-horizontal-padding, 8px));
10
+ overflow:hidden;
11
+ width:100%;
12
+ transition:bottom calc(var(--snack-notification-stack-animation-duration) / 2) calc(var(--snack-notification-stack-animation-duration) / 2 / 1.7) ease-out;
13
+ }
14
+ [data-open] .animationContainer{
15
+ bottom:-416px;
16
+ transition:bottom calc(var(--snack-notification-stack-animation-duration) / 2) ease-out;
17
+ }
18
+
19
+ .card{
20
+ position:absolute;
21
+ overflow:hidden;
22
+ height:200px;
23
+ background-color:var(--sys-neutral-background2-level, #ffffff);
24
+ border:var(--border-width-notification-panel-card, 1px) solid var(--sys-neutral-decor-default, #dde0ea);
25
+ border-radius:var(--radius-notification-panel-card, 4px);
26
+ transition:left calc(var(--snack-notification-stack-animation-duration) / 2) calc(var(--snack-notification-stack-animation-duration) / 2) ease, right calc(var(--snack-notification-stack-animation-duration) / 2) calc(var(--snack-notification-stack-animation-duration) / 2) ease, opacity calc(var(--snack-notification-stack-animation-duration) / 2) calc(var(--snack-notification-stack-animation-duration) / 2) ease;
27
+ }
28
+ .card::after{
29
+ content:"";
30
+ position:absolute;
31
+ top:0;
32
+ right:0;
33
+ bottom:0;
34
+ left:0;
35
+ opacity:var(--opacity-a008, 0.08);
36
+ background-color:var(--sys-neutral-accent-default, #787b8a);
37
+ }
38
+ [data-open] .card{
39
+ right:0;
40
+ left:0;
41
+ opacity:0;
42
+ transition:left calc(var(--snack-notification-stack-animation-duration) / 2) ease, right calc(var(--snack-notification-stack-animation-duration) / 2) ease, opacity calc(var(--snack-notification-stack-animation-duration) / 2) ease;
43
+ }
44
+ .card[data-level="2"]{
45
+ right:var(--space-notification-panel-card-stack-stack2-level-horizontal-padding, 4px);
46
+ bottom:50%;
47
+ left:var(--space-notification-panel-card-stack-stack2-level-horizontal-padding, 4px);
48
+ }
49
+ .card[data-level="3"]{
50
+ right:var(--space-notification-panel-card-stack-stack3-level-horizontal-padding, 8px);
51
+ bottom:0;
52
+ left:var(--space-notification-panel-card-stack-stack3-level-horizontal-padding, 8px);
53
+ }
@@ -3,5 +3,5 @@ import { TooltipProps } from '@snack-uikit/tooltip';
3
3
  type WithTooltipProps = PropsWithChildren<{
4
4
  tooltip?: TooltipProps;
5
5
  }>;
6
- export declare function WithTooltip({ tooltip, children }: WithTooltipProps): string | number | boolean | Iterable<import("react").ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
6
+ export declare function WithTooltip({ tooltip, children }: WithTooltipProps): string | number | boolean | import("react/jsx-runtime").JSX.Element | Iterable<import("react").ReactNode> | null | undefined;
7
7
  export {};
@@ -32,14 +32,17 @@
32
32
  }
33
33
 
34
34
  .notificationPanelBody{
35
+ padding-top:var(--space-notification-panel-body-vertical-padding, 16px);
36
+ padding-bottom:var(--space-notification-panel-body-vertical-padding, 16px);
37
+ padding-left:var(--space-notification-panel-body-horizontal-padding, 16px);
38
+ padding-right:var(--space-notification-panel-body-horizontal-padding, 16px);
39
+ display:flex;
35
40
  flex:1 1 auto;
41
+ flex-direction:column;
42
+ gap:var(--space-notification-panel-container-body-gap, 16px);
36
43
  min-height:0;
37
44
  }
38
45
 
39
- .notificationPanelCard:last-of-type{
40
- border-bottom:none;
41
- }
42
-
43
46
  .notificationPanelFooterButton{
44
47
  border-top-width:var(--border-width-notification-panel-container, 1px);
45
48
  border-bottom-right-radius:var(--radius-notification-panel-footer-radius-bottom, 4px);
@@ -0,0 +1,16 @@
1
+ import { Dispatch, ReactElement, SetStateAction } from 'react';
2
+ import { BaseItemProps } from '@snack-uikit/list';
3
+ import { NotificationCardProps } from '../../components/NotificationCard/NotificationCard';
4
+ export type Action = {
5
+ icon?: ReactElement;
6
+ tagLabel?: string;
7
+ } & Pick<BaseItemProps, 'content' | 'onClick' | 'disabled'>;
8
+ export type NotificationCardFunctionProps = Required<Pick<NotificationCardProps, 'actions'>> & {
9
+ actions: Action[];
10
+ open: boolean;
11
+ setDroplistOpen: Dispatch<SetStateAction<boolean>>;
12
+ size: 's' | 'xs';
13
+ icon: ReactElement;
14
+ className?: string;
15
+ };
16
+ export declare function ActionsButton({ actions, open, setDroplistOpen, size, icon, className, }: NotificationCardFunctionProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+
3
+ var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
4
+ return mod && mod.__esModule ? mod : {
5
+ "default": mod
6
+ };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", {
9
+ value: true
10
+ });
11
+ exports.ActionsButton = ActionsButton;
12
+ const jsx_runtime_1 = require("react/jsx-runtime");
13
+ const classnames_1 = __importDefault(require("classnames"));
14
+ const button_1 = require("@snack-uikit/button");
15
+ const list_1 = require("@snack-uikit/list");
16
+ const tag_1 = require("@snack-uikit/tag");
17
+ const constants_1 = require("../../components/NotificationCard/constants");
18
+ const helpers_1 = require("../../components/NotificationCard/helpers");
19
+ const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
20
+ function ActionsButton(_ref) {
21
+ let {
22
+ actions,
23
+ open,
24
+ setDroplistOpen,
25
+ size,
26
+ icon,
27
+ className
28
+ } = _ref;
29
+ return (
30
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions
31
+ (0, jsx_runtime_1.jsx)("div", {
32
+ className: (0, classnames_1.default)(styles_module_scss_1.default.container, className),
33
+ "data-test-id": constants_1.TEST_IDS.actions.wrapper,
34
+ onClick: helpers_1.stopPropagationClick,
35
+ children: (0, jsx_runtime_1.jsx)(list_1.Droplist, {
36
+ trigger: 'clickAndFocusVisible',
37
+ open: open,
38
+ onOpenChange: setDroplistOpen,
39
+ placement: 'bottom-end',
40
+ scroll: true,
41
+ "data-test-id": constants_1.TEST_IDS.actions.droplist,
42
+ items: actions.map(_ref2 => {
43
+ let {
44
+ onClick,
45
+ disabled,
46
+ content,
47
+ tagLabel,
48
+ icon
49
+ } = _ref2;
50
+ return {
51
+ onClick: e => {
52
+ setDroplistOpen(false);
53
+ onClick === null || onClick === void 0 ? void 0 : onClick(e);
54
+ },
55
+ disabled,
56
+ content,
57
+ beforeContent: icon,
58
+ afterContent: tagLabel ? (0, jsx_runtime_1.jsx)(tag_1.Tag, {
59
+ label: tagLabel
60
+ }) : undefined,
61
+ 'data-test-id': constants_1.TEST_IDS.actions.droplistAction
62
+ };
63
+ }),
64
+ children: (0, jsx_runtime_1.jsx)(button_1.ButtonFunction, {
65
+ size: size,
66
+ icon: icon,
67
+ "data-test-id": constants_1.TEST_IDS.actions.droplistTrigger
68
+ })
69
+ })
70
+ })
71
+ );
72
+ }
@@ -0,0 +1 @@
1
+ export * from './ActionsButton';
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = {
8
+ enumerable: true,
9
+ get: function () {
10
+ return m[k];
11
+ }
12
+ };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ } : function (o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ });
19
+ var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
20
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
+ };
22
+ Object.defineProperty(exports, "__esModule", {
23
+ value: true
24
+ });
25
+ __exportStar(require("./ActionsButton"), exports);
@@ -0,0 +1,3 @@
1
+ .container{
2
+ display:flex;
3
+ }
@@ -1,13 +1,9 @@
1
- import { ElementType, MouseEventHandler, ReactElement, ReactNode } from 'react';
1
+ import { ElementType, MouseEventHandler, ReactNode } from 'react';
2
2
  import { ButtonSimpleProps, ButtonTonalProps } from '@snack-uikit/button';
3
3
  import { PickLinkProps } from '@snack-uikit/link';
4
- import { BaseItemProps } from '@snack-uikit/list';
5
4
  import { WithSupportProps } from '@snack-uikit/utils';
5
+ import { type Action } from '../../helperComponents/ActionsButton';
6
6
  import { Appearance } from './types';
7
- type Action = {
8
- icon?: ReactElement;
9
- tagLabel?: string;
10
- } & Pick<BaseItemProps, 'content' | 'onClick' | 'disabled'>;
11
7
  export type NotificationCardProps<LinkElement extends ElementType = 'a'> = WithSupportProps<{
12
8
  /** Идентификатор уведомления */
13
9
  id: string;
@@ -40,4 +36,3 @@ export type NotificationCardProps<LinkElement extends ElementType = 'a'> = WithS
40
36
  }>;
41
37
  /** Компонент карточки уведомления */
42
38
  export declare function NotificationCard<LinkElement extends ElementType = 'a'>({ id, appearance, label, unread, title, content, link, date, onClick, primaryButton, secondaryButton, actions, onVisible, className, ...rest }: NotificationCardProps<LinkElement>): import("react/jsx-runtime").JSX.Element;
43
- export {};
@@ -13,13 +13,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import cn from 'classnames';
14
14
  import { useEffect, useMemo, useRef, useState } from 'react';
15
15
  import { ButtonSimple, ButtonTonal } from '@snack-uikit/button';
16
+ import { KebabSVG } from '@snack-uikit/icons';
16
17
  import { Link } from '@snack-uikit/link';
17
18
  import { TruncateString } from '@snack-uikit/truncate-string';
18
19
  import { Typography } from '@snack-uikit/typography';
19
20
  import { extractSupportProps } from '@snack-uikit/utils';
20
- import { NotificationCardFunction } from './components';
21
+ import { ActionsButton } from '../../helperComponents/ActionsButton';
21
22
  import { APPEARANCE, TEST_IDS } from './constants';
22
- import { getIcon } from './helpers';
23
+ import { getIcon, stopPropagationClick } from './helpers';
23
24
  import styles from './styles.module.css';
24
25
  /** Компонент карточки уведомления */
25
26
  export function NotificationCard(_a) {
@@ -53,5 +54,7 @@ export function NotificationCard(_a) {
53
54
  e.stopPropagation();
54
55
  (_a = link === null || link === void 0 ? void 0 : link.onClick) === null || _a === void 0 ? void 0 : _a.call(link, e);
55
56
  };
56
- 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(NotificationCardFunction, { actions: actions, open: isDroplistOpen, setDroplistOpen: setDroplistOpen })), 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) && (_jsxs("div", { className: styles.notificationCardButtons, 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 }))] }))] })));
57
+ 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
+ // 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 }))] }))] })));
57
60
  }
@@ -1,2 +1 @@
1
- export * from './NotificationCardFunction';
2
1
  export * from './NotificationCardSkeleton';
@@ -1,2 +1 @@
1
- export * from './NotificationCardFunction';
2
1
  export * from './NotificationCardSkeleton';
@@ -1,2 +1,4 @@
1
+ import { MouseEvent } from 'react';
1
2
  import { Appearance } from './types';
2
3
  export declare function getIcon(appearance: Appearance): import("react/jsx-runtime").JSX.Element | null;
4
+ export declare function stopPropagationClick(e: MouseEvent<HTMLElement>): void;
@@ -16,3 +16,6 @@ export function getIcon(appearance) {
16
16
  return null;
17
17
  }
18
18
  }
19
+ export function stopPropagationClick(e) {
20
+ e.stopPropagation();
21
+ }
@@ -1,6 +1,6 @@
1
1
  .notificationCardFunction{
2
2
  padding-top:var(--space-notification-panel-card-function-badge-padding-top, 12px);
3
- padding-right:var(--space-notification-panel-card-function-badge-padding-right, 16px);
3
+ padding-right:var(--space-notification-panel-card-function-badge-padding-right, 12px);
4
4
  pointer-events:none;
5
5
  position:absolute;
6
6
  top:0;
@@ -24,19 +24,20 @@
24
24
  }
25
25
 
26
26
  .notificationCard{
27
- padding-left:var(--space-notification-panel-card-padding-horizontal, 16px);
28
- padding-right:var(--space-notification-panel-card-padding-horizontal, 16px);
29
- padding-top:var(--space-notification-panel-card-padding-vertical, 16px);
30
- padding-bottom:var(--space-notification-panel-card-padding-vertical, 16px);
27
+ padding-left:var(--space-notification-panel-card-padding-horizontal, 12px);
28
+ padding-right:var(--space-notification-panel-card-padding-horizontal, 12px);
29
+ padding-top:var(--space-notification-panel-card-padding-vertical, 12px);
30
+ padding-bottom:var(--space-notification-panel-card-padding-vertical, 12px);
31
31
  gap:var(--space-notification-panel-card-gap, 8px);
32
- border-bottom-width:var(--border-width-notification-panel-card, 1px);
32
+ border-width:var(--border-width-notification-panel-card, 1px);
33
+ border-radius:var(--radius-notification-panel-card, 4px);
33
34
  position:relative;
34
35
  display:flex;
35
36
  flex-direction:column;
36
37
  box-sizing:border-box;
37
38
  max-width:100%;
38
- border-bottom-color:var(--sys-neutral-decor-default, #dde0ea);
39
- border-bottom-style:solid;
39
+ border-color:var(--sys-neutral-decor-default, #dde0ea);
40
+ border-style:solid;
40
41
  }
41
42
  .notificationCard::before{
42
43
  pointer-events:none;
@@ -54,7 +55,7 @@
54
55
  outline-width:var(--border-state-focus-s-border-width, 2px);
55
56
  outline-style:var(--border-state-focus-s-border-style, solid);
56
57
  outline-color:var(--border-state-focus-s-border-color, );
57
- border-bottom-color:transparent;
58
+ border-color:transparent;
58
59
  outline-color:var(--sys-available-complementary, #1c1c24);
59
60
  }
60
61
  .notificationCard[data-droplist-open]::before, .notificationCard:hover::before, .notificationCard:focus-visible::before, .notificationCard:focus-within:not(:focus)::before{
@@ -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 { NotificationPanelBlank, NotificationPanelBlankProps, NotificationPanelSettingsProps } from './components';
6
+ import { NotificationCardStack, NotificationCardStackProps, NotificationPanelBlank, NotificationPanelBlankProps, NotificationPanelSettingsProps } from './components';
7
7
  import { NotificationPanelDivider, NotificationPanelDividerProps } from './components/NotificationPanelDivider';
8
8
  export type { NotificationPanelBlankProps };
9
9
  export type NotificationPanelProps = WithSupportProps<{
@@ -41,4 +41,6 @@ export declare namespace NotificationPanel {
41
41
  type BlankProps = NotificationPanelBlankProps;
42
42
  const Divider: typeof NotificationPanelDivider;
43
43
  type DividerProps = NotificationPanelDividerProps;
44
+ const Stack: typeof NotificationCardStack;
45
+ type StackProps = NotificationCardStackProps;
44
46
  }
@@ -20,7 +20,7 @@ import { TruncateString } from '@snack-uikit/truncate-string';
20
20
  import { Typography } from '@snack-uikit/typography';
21
21
  import { extractSupportProps } from '@snack-uikit/utils';
22
22
  import { NotificationCardSkeleton } from '../NotificationCard/components';
23
- import { NotificationPanelBlank, NotificationPanelSettings, } from './components';
23
+ import { NotificationCardStack, NotificationPanelBlank, NotificationPanelSettings, } from './components';
24
24
  import { NotificationPanelDivider } from './components/NotificationPanelDivider';
25
25
  import { TEST_IDS } from './constants';
26
26
  import { WithTooltip } from './helperComponents';
@@ -29,9 +29,10 @@ import styles from './styles.module.css';
29
29
  export function NotificationPanel(_a) {
30
30
  var { title, settings, segments, readAllButton, footerButton, content, loading, skeletonsAmount = 2, scrollEndRef, scrollContainerRef, className } = _a, rest = __rest(_a, ["title", "settings", "segments", "readAllButton", "footerButton", "content", "loading", "skeletonsAmount", "scrollEndRef", "scrollContainerRef", "className"]);
31
31
  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))] })] }), _jsx("div", { children: segments && (_jsx(SegmentedControl, Object.assign({}, segments, { size: 's', items: segments.items.map(item => (Object.assign(Object.assign({}, item), { disabled: item.disabled || loading }))), "data-test-id": TEST_IDS.segments }))) })] }), _jsxs(Scroll, { size: 'm', className: styles.notificationPanelBody, ref: scrollContainerRef, 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 }) }))] })));
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))] })] }), _jsx("div", { children: segments && (_jsx(SegmentedControl, Object.assign({}, segments, { size: 's', items: segments.items.map(item => (Object.assign(Object.assign({}, item), { disabled: item.disabled || loading }))), "data-test-id": TEST_IDS.segments }))) })] }), _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
33
  }
34
34
  (function (NotificationPanel) {
35
35
  NotificationPanel.Blank = NotificationPanelBlank;
36
36
  NotificationPanel.Divider = NotificationPanelDivider;
37
+ NotificationPanel.Stack = NotificationCardStack;
37
38
  })(NotificationPanel || (NotificationPanel = {}));
@@ -0,0 +1,27 @@
1
+ import { ReactNode } from 'react';
2
+ import { Action } from '../../../../helperComponents/ActionsButton';
3
+ export type NotificationCardStackProps = {
4
+ /**
5
+ * Заголовок стопки карточек
6
+ */
7
+ title: string;
8
+ /**
9
+ * Состояние открыт/закрыт по умолчанию
10
+ * @default false
11
+ */
12
+ defaultOpen?: boolean;
13
+ /**
14
+ * Колбек смены состояния открыт/закрыт
15
+ * @type (open: boolean) => void
16
+ */
17
+ onOpenChanged?: (open: boolean) => void;
18
+ /**
19
+ * Карточки в стопке, видна первая карточка, остальные схлопываются под нее.
20
+ */
21
+ children: Iterable<ReactNode>;
22
+ /**
23
+ * Список действий в выпадающем меню
24
+ */
25
+ actions?: Action[];
26
+ };
27
+ export declare function NotificationCardStack({ children, defaultOpen, onOpenChanged, title, actions, }: NotificationCardStackProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,28 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Children, useMemo, useState } from 'react';
3
+ import { ButtonFunction } from '@snack-uikit/button';
4
+ import { ChevronDownSVG, ChevronUpSVG, KebabSVG } from '@snack-uikit/icons';
5
+ import { ActionsButton } from '../../../../helperComponents/ActionsButton';
6
+ import { TEST_IDS } from '../../constants';
7
+ import { StackTail } from '../../helperComponents/StackTail';
8
+ import { useAnimatedOpening } from './hooks';
9
+ import styles from './styles.module.css';
10
+ import { cloneCard } from './utils';
11
+ const ANIMATION_DURATION = 0.3;
12
+ export function NotificationCardStack({ children, defaultOpen, onOpenChanged, title, actions, }) {
13
+ const [actionsOpen, setActionsOpen] = useState(false);
14
+ const { open, toggleOpen, isVisible } = useAnimatedOpening({
15
+ defaultOpen,
16
+ onOpenChanged,
17
+ duration: ANIMATION_DURATION * 1000,
18
+ });
19
+ const [first, ...stack] = useMemo(() => Children.toArray(children), [children]);
20
+ if (!first) {
21
+ return null;
22
+ }
23
+ if (!stack.length) {
24
+ return _jsx(_Fragment, { children: first });
25
+ }
26
+ const firstCardElement = open ? first : cloneCard(first, { onClick: toggleOpen });
27
+ 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
+ }
@@ -0,0 +1,12 @@
1
+ type UseAnimatedOpeningProps = {
2
+ defaultOpen?: boolean;
3
+ onOpenChanged?: (open: boolean) => void;
4
+ duration: number;
5
+ };
6
+ type UseAnimatedOpeningResult = {
7
+ open: boolean;
8
+ isVisible: boolean;
9
+ toggleOpen(): void;
10
+ };
11
+ export declare function useAnimatedOpening({ defaultOpen, onOpenChanged, duration, }: UseAnimatedOpeningProps): UseAnimatedOpeningResult;
12
+ export {};
@@ -0,0 +1,26 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { useUncontrolledProp } from 'uncontrollable';
3
+ export function useAnimatedOpening({ defaultOpen = false, onOpenChanged, duration, }) {
4
+ const [open, setOpen] = useUncontrolledProp(undefined, defaultOpen, onOpenChanged);
5
+ const [isVisible, setIsVisible] = useState(open);
6
+ const timeout = useRef();
7
+ const toggleOpen = useCallback(() => {
8
+ setOpen(!open);
9
+ }, [open, setOpen]);
10
+ useEffect(() => {
11
+ clearTimeout(timeout.current);
12
+ if (open) {
13
+ setIsVisible(true);
14
+ }
15
+ else {
16
+ timeout.current = setTimeout(() => {
17
+ setIsVisible(false);
18
+ }, duration);
19
+ }
20
+ }, [open, duration]);
21
+ return {
22
+ toggleOpen,
23
+ open,
24
+ isVisible,
25
+ };
26
+ }
@@ -0,0 +1 @@
1
+ export * from './NotificationCardStack';
@@ -0,0 +1 @@
1
+ export * from './NotificationCardStack';