omninotice-notification-feed 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +266 -2
  2. package/dist/NotificationFeedPage-B7jnF1LL.js +971 -0
  3. package/dist/NotificationFeedPage-B7jnF1LL.js.map +1 -0
  4. package/dist/NotificationFeedPage-F2ht69hw.cjs +2 -0
  5. package/dist/NotificationFeedPage-F2ht69hw.cjs.map +1 -0
  6. package/dist/NotificationsFeedProvider-BApcYuJs.cjs +2 -0
  7. package/dist/NotificationsFeedProvider-BApcYuJs.cjs.map +1 -0
  8. package/dist/NotificationsFeedProvider-DTr1ulMN.js +35 -0
  9. package/dist/NotificationsFeedProvider-DTr1ulMN.js.map +1 -0
  10. package/dist/api/actions.d.ts +5 -0
  11. package/dist/api/apiFetch.d.ts +28 -0
  12. package/dist/api/envelope.d.ts +24 -0
  13. package/dist/api/notificationCounts.d.ts +24 -0
  14. package/dist/api/notificationDetails.d.ts +74 -0
  15. package/dist/api/notificationMapper.d.ts +11 -0
  16. package/dist/api/notifications.d.ts +102 -0
  17. package/dist/api/requests.d.ts +5 -0
  18. package/dist/api/schema.d.ts +17 -0
  19. package/dist/app/contexts/NotificationsContext.d.ts +10 -0
  20. package/dist/app/contexts/TabContext.d.ts +9 -0
  21. package/dist/app/providers/NotificationsFeedDataProvider.d.ts +19 -0
  22. package/dist/app/providers/NotificationsFeedProvider.d.ts +10 -0
  23. package/dist/app/providers/TabProvider.d.ts +11 -0
  24. package/dist/components/atoms/Button/Button.d.ts +3 -0
  25. package/dist/components/atoms/Container/Container.d.ts +4 -0
  26. package/dist/components/atoms/Loaders/SpinnerLoader/SpinnerLoader.d.ts +4 -0
  27. package/dist/components/atoms/NotificationIcon/NotificationIcon.d.ts +5 -0
  28. package/dist/components/atoms/Text/Text.d.ts +2 -0
  29. package/dist/components/atoms/icons/ArrowIcon.d.ts +2 -0
  30. package/dist/components/atoms/icons/BellRingIcon.d.ts +1 -0
  31. package/dist/components/atoms/icons/CheckIcon.d.ts +2 -0
  32. package/dist/components/atoms/icons/ChevronIcon.d.ts +2 -0
  33. package/dist/components/atoms/icons/CloseIcon.d.ts +2 -0
  34. package/dist/components/atoms/index.d.ts +8 -0
  35. package/dist/components/atoms/types.d.ts +33 -0
  36. package/dist/components/molecules/NotificationCard/NotificationCard.d.ts +2 -0
  37. package/dist/components/molecules/NotificationList/NotificationList.d.ts +6 -0
  38. package/dist/components/molecules/NotificationsState/NotificationsState.d.ts +2 -0
  39. package/dist/components/molecules/PageTitle/PageTitle.d.ts +1 -0
  40. package/dist/components/molecules/Tab/Tab.d.ts +1 -0
  41. package/dist/components/molecules/index.d.ts +3 -0
  42. package/dist/components/molecules/types.d.ts +60 -0
  43. package/dist/components/organisms/NotificationDetailsSidebar/NotificationDetailsSidebar.d.ts +8 -0
  44. package/dist/components/organisms/NotificationsRoot/NotificationsRoot.d.ts +4 -0
  45. package/dist/components/organisms/NotificationsSection/NotificationsSection.d.ts +1 -0
  46. package/dist/components/organisms/index.d.ts +1 -0
  47. package/dist/components/pages/NotificationFeedPage.d.ts +8 -0
  48. package/dist/config/SettingsContext.d.ts +3 -0
  49. package/dist/config/settings.config.d.ts +61 -0
  50. package/dist/helpers/classNames.d.ts +3 -0
  51. package/dist/helpers/decoder.d.ts +2 -0
  52. package/dist/helpers/isEmoji.d.ts +1 -0
  53. package/dist/helpers/renderButtonContent.d.ts +2 -0
  54. package/dist/helpers/renderIcon.d.ts +2 -0
  55. package/dist/helpers/resolvePicture.d.ts +18 -0
  56. package/dist/hooks/useNotificationDetails.d.ts +7 -0
  57. package/dist/hooks/useNotificationsFeed.d.ts +33 -0
  58. package/dist/hooks/useTab.d.ts +1 -0
  59. package/dist/index.d.ts +0 -0
  60. package/dist/notificationDetails-BEOAyDdp.cjs +2 -0
  61. package/dist/notificationDetails-BEOAyDdp.cjs.map +1 -0
  62. package/dist/notificationDetails-CqA8ONhr.js +102 -0
  63. package/dist/notificationDetails-CqA8ONhr.js.map +1 -0
  64. package/dist/public.cjs +1 -0
  65. package/dist/public.d.ts +8 -0
  66. package/dist/public.js +4 -0
  67. package/dist/register-all.cjs +2 -0
  68. package/dist/register-all.cjs.map +1 -0
  69. package/dist/register-all.d.ts +1 -0
  70. package/dist/register-all.js +24 -0
  71. package/dist/register-all.js.map +1 -0
  72. package/dist/standalone.cjs +1 -0
  73. package/dist/standalone.d.ts +8 -0
  74. package/dist/standalone.js +3 -0
  75. package/dist/style.css +2 -0
  76. package/package.json +67 -4
package/README.md CHANGED
@@ -1,3 +1,267 @@
1
- # Temporary Holding Version
1
+ # omninotice-notification-feed
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Совместимость с Apiary: `^1.3.0`. Требуется React `>=18.2`.
4
+
5
+ **Карта:** [Подключение](#быстрое-подключение) · [Apiary-слот](#apiary-слот) ·
6
+ [Запросы](#запросы) · [Настройки](#настройки) · [API](#api-пакета) ·
7
+ [CSS-токены](#css-токены) · [Локальный просмотр](#локальный-просмотр)
8
+
9
+ ## Быстрое подключение
10
+
11
+ ```tsx
12
+ import {
13
+ NotificationFeedPage,
14
+ NotificationsFeedProvider,
15
+ } from "omninotice-notification-feed";
16
+ import "omninotice-notification-feed/style.css";
17
+
18
+ export function Notifications() {
19
+ return (
20
+ <NotificationsFeedProvider>
21
+ <NotificationFeedPage />
22
+ </NotificationsFeedProvider>
23
+ );
24
+ }
25
+ ```
26
+
27
+ Этот способ использует провайдеры `@core/data` и действие `@core/actions`.
28
+ Для обычного React-приложения без Apiary используйте точку входа
29
+ `omninotice-notification-feed/standalone` и передайте API-функции:
30
+
31
+ ```tsx
32
+ import {
33
+ NotificationFeedPage,
34
+ NotificationsFeedProvider,
35
+ } from "omninotice-notification-feed/standalone";
36
+ import "omninotice-notification-feed/style.css";
37
+
38
+ const api = {
39
+ fetchList: (page: number) => myApi.getNotifications({ page }),
40
+ fetchCounts: () => myApi.getNotificationCounts(),
41
+ fetchDetails: (messageId: string, signal?: AbortSignal) =>
42
+ myApi.getNotificationDetails(messageId, { signal }),
43
+ markRead: (messageId: string) => myApi.markNotificationRead(messageId),
44
+ };
45
+
46
+ export function Notifications() {
47
+ return (
48
+ <NotificationsFeedProvider api={api}>
49
+ <NotificationFeedPage />
50
+ </NotificationsFeedProvider>
51
+ );
52
+ }
53
+ ```
54
+
55
+ Функции API должны возвращать ответы в формате, описанном в разделе
56
+ [Запросы](#запросы). Передавайте `signal` в запрос деталей, чтобы он
57
+ отменялся при закрытии панели. `markRead` вызывается после успешной загрузки
58
+ деталей непрочитанного уведомления и при нажатии на действие карточки;
59
+ локальное состояние меняется только после успешного выполнения функции.
60
+ Существующий корневой импорт и Apiary-слот сохраняют прежний контракт.
61
+
62
+ ### Apiary-слот
63
+
64
+ В точке входа приложения импортируйте регистрацию и стили:
65
+
66
+ ```ts
67
+ import "omninotice-notification-feed/register-all";
68
+ import "omninotice-notification-feed/style.css";
69
+ ```
70
+
71
+ Добавьте компонент в конфигурацию слота:
72
+
73
+ ```ts
74
+ { name: "sidebar", components: [{ id: "notifications", order: 2 }] }
75
+ ```
76
+
77
+ Обёртка `NotificationsFeedProvider` и регистрация компонента выполняются пакетом.
78
+ Хост должен предоставлять `@core/hive`, `@core/data` и `@core/actions`.
79
+
80
+ ## Запросы
81
+
82
+ Пакет вызывает провайдеры через `callProvider`. Зарегистрируйте обработчики в
83
+ `@core/data` под этими именами:
84
+
85
+ | Провайдер | Параметры | Результат |
86
+ | --- | --- | --- |
87
+ | `notifications.doocot.list` | `{ page: number }` | Ответ списка |
88
+ | `notifications.doocot.counts` | нет | Ответ счётчиков |
89
+ | `notifications.doocot.details` | `{ messageId: string, signal?: AbortSignal }` | Ответ деталей |
90
+
91
+ Пример обработчиков для хоста (замените URL на адреса своего API), которые
92
+ затем нужно зарегистрировать в `@core/data`:
93
+
94
+ ```ts
95
+ import { NOTIFICATION_PROVIDERS } from "omninotice-notification-feed";
96
+
97
+ async function getJson(url: string, signal?: AbortSignal) {
98
+ const response = await fetch(url, { signal });
99
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
100
+ return response.json();
101
+ }
102
+
103
+ export const notificationProviders = {
104
+ [NOTIFICATION_PROVIDERS.list]: ({ page }: { page: number }) =>
105
+ getJson(`/my/chits?page=${page}`),
106
+ [NOTIFICATION_PROVIDERS.counts]: () =>
107
+ getJson("/my/chits/status"),
108
+ [NOTIFICATION_PROVIDERS.details]: ({
109
+ messageId,
110
+ signal,
111
+ }: {
112
+ messageId: string;
113
+ signal?: AbortSignal;
114
+ }) =>
115
+ getJson(
116
+ `/my/chit/${encodeURIComponent(messageId)}`,
117
+ signal,
118
+ ),
119
+ };
120
+ ```
121
+
122
+ Каждый обработчик должен вернуть JSON-ответ в формате ниже. Если в приложении
123
+ уже есть API-клиент, используйте его вместо `fetch`.
124
+
125
+ Провайдер деталей должен передавать `signal` в сетевой запрос, например
126
+ `fetch(url, { signal })`: при закрытии панели запрос отменяется.
127
+
128
+ Все ответы имеют вид `{ detail, data, info }`. `data` — массив:
129
+
130
+ - список: элементы с `status`, `created_date`, `modified_date`, `is_read` и
131
+ `chit` (`message_id`, `message_type`, `title`, `description`, `picture`,
132
+ `action`);
133
+ - счётчики: первый элемент — `{ total_count, unread_count }`;
134
+ - детали: элемент списка с дополнительными `chit.text`, `chit.action` и
135
+ `chit.extra`.
136
+
137
+ `info` содержит `api_version`, `count`, `total`, `page`, `page_size`.
138
+ Пустая страница завершает загрузку. Если стандартная пагинация по
139
+ `total_count` не подходит, передайте `getHasMore(info, loadedCount)` в
140
+ `NotificationsFeedProvider`.
141
+
142
+ После успешной загрузки деталей непрочитанного уведомления и при нажатии на
143
+ действие карточки пакет вызывает `runAction({ type: "mark-read", id })`, где
144
+ `id` — `messageId`. Зарегистрируйте обработчик этого действия в `@core/actions`:
145
+
146
+ ```ts
147
+ async function markRead({ id }: { id: string }) {
148
+ const response = await fetch(
149
+ `/my/${encodeURIComponent(id)}/read`,
150
+ {
151
+ method: "PATCH",
152
+ headers: { "Content-Type": "application/json" },
153
+ body: JSON.stringify({ chit_id: id }),
154
+ },
155
+ );
156
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
157
+ }
158
+ ```
159
+
160
+ `id` передаётся как `chit_id` в URL и JSON-теле запроса. Подключите функцию к
161
+ действию `mark-read` в конфигурации `@core/actions`. При ошибке пакет показывает
162
+ сообщение, а локально отмечает уведомление прочитанным только после успеха.
163
+
164
+ ## Настройки
165
+
166
+ Передайте настройки в `NotificationsFeedProvider`:
167
+
168
+ ```tsx
169
+ <NotificationsFeedProvider
170
+ settings={{
171
+ pageTitle: "Уведомления",
172
+ pageSubtitle: "Новости и задачи",
173
+ autoLoadUnread: true,
174
+ sidebarBackdrop: true,
175
+ }}
176
+ >
177
+ <NotificationFeedPage header={<MyHeader />} />
178
+ </NotificationsFeedProvider>
179
+ ```
180
+
181
+ | Настройка | По умолчанию | Назначение |
182
+ | --- | --- | --- |
183
+ | `pageTitle` | `Уведомления` | Заголовок |
184
+ | `pageSubtitle` | описание ленты | Подзаголовок |
185
+ | `autoLoadUnread` | `true` | Загружать страницы, пока не найдутся непрочитанные |
186
+ | `sidebarBackdrop` | `true` | Затемнение за панелью деталей |
187
+ | `defaultIcon` | иконка уведомления | Иконка без изображения |
188
+ | `notificationState` | тексты пакета | Содержимое состояний `empty`, `error`, `allRead`, `noUnreadLoaded` |
189
+
190
+ Для `notificationState` можно переопределить `title`, `description`, `btn`
191
+ (`title`, `onClick`), `className` и `icon`. Настройки объединяются с
192
+ значениями по умолчанию. `defaultIcon` и `notificationState` доступны при
193
+ прямом использовании `NotificationsFeedProvider`; в `SlotComponentProps.settings`
194
+ поддерживаются только первые четыре настройки таблицы.
195
+
196
+ `NotificationFeedPage` принимает необязательный `header` — React-узел перед
197
+ заголовком страницы.
198
+
199
+ ## API пакета
200
+
201
+ Из корневого импорта экспортируются `NotificationsFeedProvider`,
202
+ `NotificationFeedPage`, `SettingsOverrides`, `GetHasMore`, `NOTIFICATION_PROVIDERS`,
203
+ типы ответов и уведомлений (`NotificationsResponse`, `Notification`,
204
+ `NotificationCountsResponse`, `NotificationDetailsResponse`) и соответствующие
205
+ схемы (`NotificationsResponseSchema`, `NotificationCountsResponseSchema`,
206
+ `NotificationDetailsResponseSchema` и схемы элементов). Детали показывают
207
+ `chit.text`, а при его отсутствии — `chit.description`; `chit.action`
208
+ отображается как ссылка.
209
+
210
+ ## CSS-токены
211
+
212
+ Токены пакета из `NotificationFeedPage.module.css`:
213
+
214
+ ```css
215
+ --omni-main-bg: var(--color-surface, #f5f6f9); /* фон страницы */
216
+ --omni-primary: var(--color-primary, #487bfe); /* основной цвет */
217
+ --omni-primary-hover: var(
218
+ --color-primary-hover,
219
+ hsl(from var(--omni-primary) h s calc(l - 10))
220
+ ); /* цвет при наведении */
221
+ --omni-primary-text: var(--color-text-primary, #0c151d); /* основной текст */
222
+ --omni-secondary-text: var(--color-text-secondary, #767a7f); /* вторичный текст */
223
+ --omni-breadcumbs-icon-color: var(--color-icon, #4a5665); /* цвет иконки */
224
+ --omni-sidebar-box-shadow: var(
225
+ --color-shadow,
226
+ 0px 0px 1px 0px #00000066,
227
+ -8px 8px 24px -8px #00000029
228
+ ); /* тень панели */
229
+ --omni-state-box-shadow: var(--color-shadow, 0px 0px 1px #0000004D); /* тень состояния */
230
+ --omni-nf-bg: var(--color-surface, #ffffff); /* фон карточки */
231
+ --omni-nf-bg-hover: var(
232
+ --color-bg-hover,
233
+ color-mix(in srgb, var(--omni-primary) 12%, white)
234
+ ); /* фон при наведении */
235
+ --omni-nf-icon: var(--omni-primary); /* цвет иконки уведомления */
236
+ --omni-nf-icon-error: var(--color-danger, #e65443); /* цвет иконки ошибки */
237
+ --omni-nf-icon-bg: var(
238
+ --color-primary-soft,
239
+ color-mix(in srgb, var(--omni-nf-icon) 25%, white)
240
+ ); /* фон иконки уведомления */
241
+ --omni-nf-icon-bg-error: var(
242
+ --color-danger-soft,
243
+ color-mix(in srgb, var(--omni-nf-icon-error) 25%, white)
244
+ ); /* фон иконки ошибки */
245
+ --omni-border-color: var(--color-border, #eceef4); /* цвет границы */
246
+ --omni-border-hover: var(--color-text-primary, #0c151d); /* граница при наведении */
247
+ --omni-radius: var(--radius-md, 8px); /* радиус скругления */
248
+ --omni-container-padding-inline: 24px 20px; /* отступы контейнера */
249
+ --omni-nf-icon-container-size: 56px; /* размер контейнера иконки */
250
+ --omni-nf-icon-chevron-size: 24px; /* размер шеврона */
251
+ --omni-tabs-margin-block: 32px; /* отступ вкладок */
252
+ --omni-transition: 0.15s ease-in; /* скорость перехода */
253
+ ```
254
+
255
+ В состоянии ошибки `NotificationsState.module.css` переопределяет:
256
+
257
+ ```css
258
+ --omni-nf-icon: var(--omni-nf-icon-error); /* цвет иконки ошибки */
259
+ --omni-nf-icon-bg: var(--omni-nf-icon-bg-error); /* фон иконки ошибки */
260
+ ```
261
+
262
+ Стили компонентов изолированы CSS Modules.
263
+
264
+ ## Локальный просмотр
265
+
266
+ `npm run dev` запускает превью с моками из `public/mock`. Создайте их командой
267
+ `npm run generate:mock`; после клонирования её нужно выполнить один раз.