@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
package/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## <small>0.13.26 (2026-01-29)</small>
7
+
8
+ * feat(PDS-3356): add notification card stack ([06a2d74](https://github.com/cloud-ru-tech/snack-uikit/commit/06a2d74))
9
+
10
+
11
+
12
+
13
+
6
14
  ## <small>0.13.25 (2026-01-19)</small>
7
15
 
8
16
  * chore(FF-6693): migrate tests from TestCafe to Playwright ([f32aff8](https://github.com/cloud-ru-tech/snack-uikit/commit/f32aff8))
package/README.md CHANGED
@@ -170,6 +170,67 @@ function NotificationPanelExample() {
170
170
  }
171
171
  ```
172
172
 
173
+ ## NotificationPanel.Stack
174
+
175
+ ### Description
176
+
177
+ - `NotificationPanel.Stack` — вспомогательный компонент для отображения группы уведомлений в виде **стека карточек** внутри `NotificationPanel`.
178
+ - Используется для **компактного отображения набора уведомлений**, которые можно свернуть/развернуть по заголовку.
179
+ - Принимает **заголовок стека** (`title`), **состояние открытия по умолчанию** (`defaultOpen`) и колбэк изменения состояния (`onOpenChanged`).
180
+ - Поддерживает **дополнительные действия** (`actions`) в виде выпадающего списка, аналогично действиям настроек панели.
181
+ - Внутри стека отрисовываются карточки `NotificationCard`.
182
+
183
+ ### Example
184
+
185
+ ```tsx
186
+ import { NotificationCard, NotificationPanel } from '@snack-uikit/notification';
187
+
188
+ function NotificationPanelStackExample() {
189
+ const cards = [
190
+ {
191
+ id: 'card-1',
192
+ label: 'Category・Subcategory',
193
+ appearance: 'neutral' as const,
194
+ title: 'First notification in stack',
195
+ content: 'Demo content.',
196
+ date: 'DD.MM.YYYY HH:MM',
197
+ },
198
+ {
199
+ id: 'card-2',
200
+ label: 'Category・Subcategory',
201
+ appearance: 'neutral' as const,
202
+ title: 'Second notification in stack',
203
+ content: 'Another demo content.',
204
+ date: 'DD.MM.YYYY HH:MM',
205
+ },
206
+ ];
207
+
208
+ return (
209
+ <NotificationPanel
210
+ title="Notifications"
211
+ content={
212
+ <NotificationPanel.Stack
213
+ title="Previous notifications"
214
+ actions={[
215
+ {
216
+ content: { option: 'Move to archive' },
217
+ onClick: () => console.log('Move to archive'),
218
+ },
219
+ {
220
+ content: { option: 'Delete all' },
221
+ onClick: () => console.log('Delete all'),
222
+ },
223
+ ]}
224
+ >
225
+ {cards.map(card => (
226
+ <NotificationCard {...card} key={card.id} />
227
+ ))}
228
+ </NotificationPanel.Stack>
229
+ }
230
+ />
231
+ );
232
+ }
233
+ ```
173
234
 
174
235
  [//]: DOCUMENTATION_SECTION_START
175
236
  [//]: THIS_SECTION_IS_AUTOGENERATED_PLEASE_DONT_EDIT_IT
@@ -222,6 +283,15 @@ function NotificationPanelExample() {
222
283
  |------|------|---------------|-------------|
223
284
  | text* | `string` | - | Текст разделителя |
224
285
  | className | `string` | - | CSS-класс |
286
+ ## NotificationPanel.Stack
287
+ ### Props
288
+ | name | type | default value | description |
289
+ |------|------|---------------|-------------|
290
+ | children* | `Iterable<ReactNode>` | - | Карточки в стопке, видна первая карточка, остальные схлопываются под нее. |
291
+ | title* | `string` | - | Заголовок стопки карточек |
292
+ | defaultOpen | `boolean` | false | Состояние открыт/закрыт по умолчанию |
293
+ | onOpenChanged | `(open: boolean) => void` | - | Колбек смены состояния открыт/закрыт |
294
+ | actions | `Action[]` | - | Список действий в выпадающем меню |
225
295
  ## NotificationPanelPopover
226
296
  Компонент-обёртка для NotificationPanel для использования как выпадающий элемент
227
297
  ### Props
@@ -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 {};
@@ -21,11 +21,12 @@ 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 icons_1 = require("@snack-uikit/icons");
24
25
  const link_1 = require("@snack-uikit/link");
25
26
  const truncate_string_1 = require("@snack-uikit/truncate-string");
26
27
  const typography_1 = require("@snack-uikit/typography");
27
28
  const utils_1 = require("@snack-uikit/utils");
28
- const components_1 = require("./components");
29
+ const ActionsButton_1 = require("../../helperComponents/ActionsButton");
29
30
  const constants_1 = require("./constants");
30
31
  const helpers_1 = require("./helpers");
31
32
  const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
@@ -88,10 +89,13 @@ function NotificationCard(_a) {
88
89
  "data-clickable": Boolean(onClick) || undefined,
89
90
  "data-droplist-open": isDroplistOpen || undefined,
90
91
  className: (0, classnames_1.default)(styles_module_scss_1.default.notificationCard, className),
91
- children: [(actions === null || actions === void 0 ? void 0 : actions.length) && (0, jsx_runtime_1.jsx)(components_1.NotificationCardFunction, {
92
+ children: [(actions === null || actions === void 0 ? void 0 : actions.length) && (0, jsx_runtime_1.jsx)(ActionsButton_1.ActionsButton, {
93
+ className: styles_module_scss_1.default.notificationCardFunction,
92
94
  actions: actions,
93
95
  open: isDroplistOpen,
94
- setDroplistOpen: setDroplistOpen
96
+ setDroplistOpen: setDroplistOpen,
97
+ size: 's',
98
+ icon: (0, jsx_runtime_1.jsx)(icons_1.KebabSVG, {})
95
99
  }), label && (0, jsx_runtime_1.jsx)(typography_1.Typography.LightLabelS, {
96
100
  tag: 'div',
97
101
  className: styles_module_scss_1.default.notificationCardLabel,
@@ -119,8 +123,11 @@ function NotificationCard(_a) {
119
123
  className: styles_module_scss_1.default.notificationCardContent,
120
124
  "data-test-id": constants_1.TEST_IDS.content,
121
125
  children: content
122
- }), (primaryButton || secondaryButton) && (0, jsx_runtime_1.jsxs)("div", {
126
+ }), (primaryButton || secondaryButton) &&
127
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions
128
+ (0, jsx_runtime_1.jsxs)("div", {
123
129
  className: styles_module_scss_1.default.notificationCardButtons,
130
+ onClick: helpers_1.stopPropagationClick,
124
131
  children: [secondaryButton && (0, jsx_runtime_1.jsx)(button_1.ButtonSimple, Object.assign({}, secondaryButton, {
125
132
  appearance: 'neutral',
126
133
  size: 's',
@@ -1,2 +1 @@
1
- export * from './NotificationCardFunction';
2
1
  export * from './NotificationCardSkeleton';
@@ -22,5 +22,4 @@ var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
22
22
  Object.defineProperty(exports, "__esModule", {
23
23
  value: true
24
24
  });
25
- __exportStar(require("./NotificationCardFunction"), exports);
26
25
  __exportStar(require("./NotificationCardSkeleton"), exports);
@@ -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;
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getIcon = getIcon;
7
+ exports.stopPropagationClick = stopPropagationClick;
7
8
  const jsx_runtime_1 = require("react/jsx-runtime");
8
9
  const icons_1 = require("@snack-uikit/icons");
9
10
  const constants_1 = require("./constants");
@@ -29,4 +30,7 @@ function getIcon(appearance) {
29
30
  default:
30
31
  return null;
31
32
  }
33
+ }
34
+ function stopPropagationClick(e) {
35
+ e.stopPropagation();
32
36
  }
@@ -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
  }
@@ -86,19 +86,21 @@ function NotificationPanel(_a) {
86
86
  "data-test-id": constants_1.TEST_IDS.segments
87
87
  }))
88
88
  })]
89
- }), (0, jsx_runtime_1.jsxs)(scroll_1.Scroll, {
89
+ }), (0, jsx_runtime_1.jsx)(scroll_1.Scroll, {
90
90
  size: 'm',
91
- className: styles_module_scss_1.default.notificationPanelBody,
92
91
  ref: scrollContainerRef,
93
- children: [content, loading && (0, jsx_runtime_1.jsx)(skeleton_1.SkeletonContextProvider, {
94
- loading: loading || false,
95
- children: skeletons.map(skeleton => (0, jsx_runtime_1.jsx)(skeleton_1.WithSkeleton, {
96
- skeleton: (0, jsx_runtime_1.jsx)(components_1.NotificationCardSkeleton, {})
97
- }, skeleton))
98
- }), (0, jsx_runtime_1.jsx)("div", {
99
- className: styles_module_scss_1.default.scrollStub,
100
- ref: scrollEndRef
101
- })]
92
+ children: (0, jsx_runtime_1.jsxs)("div", {
93
+ className: styles_module_scss_1.default.notificationPanelBody,
94
+ children: [content, loading && (0, jsx_runtime_1.jsx)(skeleton_1.SkeletonContextProvider, {
95
+ loading: loading || false,
96
+ children: skeletons.map(skeleton => (0, jsx_runtime_1.jsx)(skeleton_1.WithSkeleton, {
97
+ skeleton: (0, jsx_runtime_1.jsx)(components_1.NotificationCardSkeleton, {})
98
+ }, skeleton))
99
+ }), (0, jsx_runtime_1.jsx)("div", {
100
+ className: styles_module_scss_1.default.scrollStub,
101
+ ref: scrollEndRef
102
+ })]
103
+ })
102
104
  }), footerButton && (0, jsx_runtime_1.jsx)("button", {
103
105
  type: 'button',
104
106
  onClick: footerButton.onClick,
@@ -113,4 +115,5 @@ function NotificationPanel(_a) {
113
115
  (function (NotificationPanel) {
114
116
  NotificationPanel.Blank = components_2.NotificationPanelBlank;
115
117
  NotificationPanel.Divider = NotificationPanelDivider_1.NotificationPanelDivider;
118
+ NotificationPanel.Stack = components_2.NotificationCardStack;
116
119
  })(NotificationPanel || (exports.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,101 @@
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.NotificationCardStack = NotificationCardStack;
12
+ const jsx_runtime_1 = require("react/jsx-runtime");
13
+ const react_1 = require("react");
14
+ const button_1 = require("@snack-uikit/button");
15
+ const icons_1 = require("@snack-uikit/icons");
16
+ const ActionsButton_1 = require("../../../../helperComponents/ActionsButton");
17
+ const constants_1 = require("../../constants");
18
+ const StackTail_1 = require("../../helperComponents/StackTail");
19
+ const hooks_1 = require("./hooks");
20
+ const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
21
+ const utils_1 = require("./utils");
22
+ const ANIMATION_DURATION = 0.3;
23
+ function NotificationCardStack(_ref) {
24
+ let {
25
+ children,
26
+ defaultOpen,
27
+ onOpenChanged,
28
+ title,
29
+ actions
30
+ } = _ref;
31
+ const [actionsOpen, setActionsOpen] = (0, react_1.useState)(false);
32
+ const {
33
+ open,
34
+ toggleOpen,
35
+ isVisible
36
+ } = (0, hooks_1.useAnimatedOpening)({
37
+ defaultOpen,
38
+ onOpenChanged,
39
+ duration: ANIMATION_DURATION * 1000
40
+ });
41
+ const [first, ...stack] = (0, react_1.useMemo)(() => react_1.Children.toArray(children), [children]);
42
+ if (!first) {
43
+ return null;
44
+ }
45
+ if (!stack.length) {
46
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {
47
+ children: first
48
+ });
49
+ }
50
+ const firstCardElement = open ? first : (0, utils_1.cloneCard)(first, {
51
+ onClick: toggleOpen
52
+ });
53
+ return (0, jsx_runtime_1.jsxs)("div", {
54
+ className: styles_module_scss_1.default.container,
55
+ style: {
56
+ '--snack-notification-stack-animation-duration': `${ANIMATION_DURATION}s`
57
+ },
58
+ "data-test-id": constants_1.TEST_IDS.cardStack.wrapper,
59
+ children: [(0, jsx_runtime_1.jsxs)("div", {
60
+ className: styles_module_scss_1.default.header,
61
+ "data-test-id": constants_1.TEST_IDS.cardStack.headline,
62
+ children: [(0, jsx_runtime_1.jsx)("label", {
63
+ className: styles_module_scss_1.default.title,
64
+ onClick: toggleOpen,
65
+ "data-test-id": constants_1.TEST_IDS.cardStack.title,
66
+ children: title
67
+ }), (0, jsx_runtime_1.jsxs)("div", {
68
+ className: styles_module_scss_1.default.right,
69
+ children: [actions && actions.length > 0 && (0, jsx_runtime_1.jsx)(ActionsButton_1.ActionsButton, {
70
+ actions: actions,
71
+ open: actionsOpen,
72
+ setDroplistOpen: setActionsOpen,
73
+ size: 'xs',
74
+ icon: (0, jsx_runtime_1.jsx)(icons_1.KebabSVG, {})
75
+ }), (0, jsx_runtime_1.jsx)(button_1.ButtonFunction, {
76
+ size: 'xs',
77
+ onClick: toggleOpen,
78
+ "data-test-id": constants_1.TEST_IDS.cardStack.openButton,
79
+ icon: open ? (0, jsx_runtime_1.jsx)(icons_1.ChevronUpSVG, {}) : (0, jsx_runtime_1.jsx)(icons_1.ChevronDownSVG, {})
80
+ })]
81
+ })]
82
+ }), (0, jsx_runtime_1.jsxs)("div", {
83
+ className: styles_module_scss_1.default.cards,
84
+ children: [(0, jsx_runtime_1.jsxs)("div", {
85
+ className: styles_module_scss_1.default.first,
86
+ children: [(0, jsx_runtime_1.jsx)(StackTail_1.StackTail, {
87
+ open: open,
88
+ count: stack.length
89
+ }), firstCardElement]
90
+ }), (0, jsx_runtime_1.jsx)("div", {
91
+ className: styles_module_scss_1.default.stack,
92
+ "data-open": open || undefined,
93
+ "data-tail-size": stack.length,
94
+ children: (0, jsx_runtime_1.jsx)("div", {
95
+ className: styles_module_scss_1.default.animationContainer,
96
+ children: isVisible ? stack : []
97
+ })
98
+ })]
99
+ })]
100
+ });
101
+ }
@@ -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,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useAnimatedOpening = useAnimatedOpening;
7
+ const react_1 = require("react");
8
+ const uncontrollable_1 = require("uncontrollable");
9
+ function useAnimatedOpening(_ref) {
10
+ let {
11
+ defaultOpen = false,
12
+ onOpenChanged,
13
+ duration
14
+ } = _ref;
15
+ const [open, setOpen] = (0, uncontrollable_1.useUncontrolledProp)(undefined, defaultOpen, onOpenChanged);
16
+ const [isVisible, setIsVisible] = (0, react_1.useState)(open);
17
+ const timeout = (0, react_1.useRef)();
18
+ const toggleOpen = (0, react_1.useCallback)(() => {
19
+ setOpen(!open);
20
+ }, [open, setOpen]);
21
+ (0, react_1.useEffect)(() => {
22
+ clearTimeout(timeout.current);
23
+ if (open) {
24
+ setIsVisible(true);
25
+ } else {
26
+ timeout.current = setTimeout(() => {
27
+ setIsVisible(false);
28
+ }, duration);
29
+ }
30
+ }, [open, duration]);
31
+ return {
32
+ toggleOpen,
33
+ open,
34
+ isVisible
35
+ };
36
+ }
@@ -0,0 +1 @@
1
+ export * from './NotificationCardStack';
@@ -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("./NotificationCardStack"), exports);
@@ -0,0 +1,74 @@
1
+ .container{
2
+ gap:var(--space-notification-panel-card-stack-container, 4px);
3
+ display:flex;
4
+ flex-direction:column;
5
+ }
6
+
7
+ .header{
8
+ gap:var(--space-notification-panel-card-stack-header-gap, 4px);
9
+ padding-bottom:var(--space-notification-panel-card-stack-header-padding-bottom, 4px);
10
+ display:flex;
11
+ flex-direction:row;
12
+ align-items:center;
13
+ color:var(var(--sys-neutral-text-main, #41424e));
14
+ }
15
+
16
+ .title{
17
+ font-family:var(--sans-title-s-font-family, SB Sans Interface);
18
+ font-weight:var(--sans-title-s-font-weight, Semibold);
19
+ line-height:var(--sans-title-s-line-height, 20px);
20
+ font-size:var(--sans-title-s-font-size, 14px);
21
+ letter-spacing:var(--sans-title-s-letter-spacing, 0.15px);
22
+ paragraph-spacing:var(--sans-title-s-paragraph-spacing, 7.7px);
23
+ overflow:hidden;
24
+ flex-grow:1;
25
+ flex-shrink:1;
26
+ text-overflow:ellipsis;
27
+ white-space:nowrap;
28
+ }
29
+
30
+ .right{
31
+ gap:var(--space-notification-panel-card-stack-header-gap, 4px);
32
+ display:flex;
33
+ flex-direction:row;
34
+ flex-grow:0;
35
+ flex-shrink:0;
36
+ }
37
+
38
+ .first{
39
+ display:flex;
40
+ flex-direction:column-reverse;
41
+ }
42
+
43
+ .stack{
44
+ position:relative;
45
+ overflow:visible;
46
+ height:auto;
47
+ transition:overflow var(--snack-notification-stack-animation-duration) allow-discrete step-end;
48
+ }
49
+ .stack:not([data-open]){
50
+ overflow:hidden;
51
+ transition:height var(--snack-notification-stack-animation-duration) allow-discrete step-end;
52
+ }
53
+ .stack:not([data-open])[data-tail-size]{
54
+ height:8px;
55
+ }
56
+ .stack:not([data-open])[data-tail-size="1"]{
57
+ height:4px;
58
+ }
59
+
60
+ .animationContainer{
61
+ translate:0 -100%;
62
+ scale:0.98;
63
+ display:flex;
64
+ flex-direction:column;
65
+ gap:var(--space-notification-panel-container-body-stack-cards, 4px);
66
+ margin-top:var(--space-notification-panel-container-body-stack-cards, 4px);
67
+ opacity:0;
68
+ transition:scale var(--snack-notification-stack-animation-duration), translate var(--snack-notification-stack-animation-duration), opacity var(--snack-notification-stack-animation-duration);
69
+ }
70
+ [data-open] .animationContainer{
71
+ translate:0 0;
72
+ scale:1;
73
+ opacity:1;
74
+ }
@@ -0,0 +1,2 @@
1
+ import { ReactNode } from 'react';
2
+ export declare const cloneCard: (element: ReactNode, props: Record<string, unknown>) => string | number | boolean | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.cloneCard = void 0;
7
+ const react_1 = require("react");
8
+ const cloneCard = (element, props) => {
9
+ if (!(0, react_1.isValidElement)(element)) {
10
+ return element;
11
+ }
12
+ return (0, react_1.cloneElement)(element, Object.assign(Object.assign({}, element.props), props));
13
+ };
14
+ exports.cloneCard = cloneCard;
@@ -29,9 +29,16 @@ function NotificationPanelDivider(_a) {
29
29
  className
30
30
  } = _a,
31
31
  rest = __rest(_a, ["text", "className"]);
32
- return (0, jsx_runtime_1.jsx)(typography_1.Typography.LightLabelS, Object.assign({
33
- className: (0, classnames_1.default)(styles_module_scss_1.default.notificationPanelDivider, className)
32
+ return (0, jsx_runtime_1.jsxs)("div", Object.assign({
33
+ className: (0, classnames_1.default)(styles_module_scss_1.default.container, className)
34
34
  }, (0, utils_1.extractSupportProps)(rest), {
35
- children: text
35
+ children: [(0, jsx_runtime_1.jsx)("div", {
36
+ className: styles_module_scss_1.default.line
37
+ }), (0, jsx_runtime_1.jsx)(typography_1.Typography.LightLabelS, {
38
+ className: styles_module_scss_1.default.text,
39
+ children: text
40
+ }), (0, jsx_runtime_1.jsx)("div", {
41
+ className: styles_module_scss_1.default.line
42
+ })]
36
43
  }));
37
44
  }
@@ -1,10 +1,19 @@
1
- .notificationPanelDivider{
2
- height:var(--size-notification-panel-readed-divider, 32px);
3
- border-bottom-width:var(--border-width-notification-panel-container, 1px);
1
+ .container{
4
2
  display:flex;
3
+ gap:var(--space-notification-panel-divider-gap, 8px);
5
4
  align-items:center;
6
5
  justify-content:center;
6
+ }
7
+
8
+ .text{
9
+ flex-grow:0;
10
+ flex-shrink:0;
7
11
  color:var(--sys-neutral-text-light, #8b8e9b);
12
+ }
13
+
14
+ .line{
15
+ flex-grow:1;
16
+ flex-shrink:1;
8
17
  background-color:var(--sys-neutral-background2-level, #ffffff);
9
18
  border-bottom-color:var(--sys-neutral-decor-default, #dde0ea);
10
19
  border-bottom-style:solid;
@@ -1,2 +1,3 @@
1
1
  export * from './NotificationPanelSettings';
2
2
  export * from './NotificationPanelBlank';
3
+ export * from './NotificationCardStack';
@@ -23,4 +23,5 @@ Object.defineProperty(exports, "__esModule", {
23
23
  value: true
24
24
  });
25
25
  __exportStar(require("./NotificationPanelSettings"), exports);
26
- __exportStar(require("./NotificationPanelBlank"), exports);
26
+ __exportStar(require("./NotificationPanelBlank"), exports);
27
+ __exportStar(require("./NotificationCardStack"), exports);