@pushwoosh/dumb-components 1.1.88 → 1.1.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NotificationInbox/NotificationBell.js +6 -13
- package/NotificationInbox/NotificationInbox.js +10 -31
- package/NotificationInbox/styles.d.ts +0 -1
- package/NotificationInbox/styles.js +5 -9
- package/NotificationInbox/useInfiniteScroll.d.ts +11 -0
- package/NotificationInbox/useInfiniteScroll.js +39 -0
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Color } from '@pushwoosh/kit-constants';
|
|
3
3
|
import { NotificationIcon } from '@pushwoosh/kit-icons';
|
|
4
|
-
import { NotificationBellButton,
|
|
4
|
+
import { NotificationBellButton, NotificationBellBadge, NotificationBellBadgeDot } from './styles';
|
|
5
5
|
export function NotificationBell({
|
|
6
6
|
count = 0,
|
|
7
7
|
severity,
|
|
@@ -17,25 +17,18 @@ export function NotificationBell({
|
|
|
17
17
|
if (severity === 'warning') return Color.WARNING;
|
|
18
18
|
return Color.PRIMARY;
|
|
19
19
|
};
|
|
20
|
-
const getIconColor = () => {
|
|
21
|
-
if (isOpened) return Color.CLEAR;
|
|
22
|
-
return Color.MAIN;
|
|
23
|
-
};
|
|
24
|
-
const getIconView = () => {
|
|
25
|
-
return isOpened ? 'filled' : 'lined';
|
|
26
|
-
};
|
|
27
20
|
return React.createElement(NotificationBellButton, {
|
|
28
21
|
className: className,
|
|
29
22
|
"$isOpened": isOpened,
|
|
30
23
|
onClick: onClick,
|
|
31
24
|
type: "button",
|
|
32
25
|
"aria-label": hasNotifications ? 'You have unread notifications' : 'Notifications'
|
|
33
|
-
}, React.createElement(
|
|
34
|
-
size: "
|
|
35
|
-
view: getIconView(),
|
|
26
|
+
}, React.createElement(NotificationIcon, {
|
|
27
|
+
size: "medium",
|
|
36
28
|
type: "enabled",
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
view: isOpened ? 'filled' : 'lined',
|
|
30
|
+
color: "currentColor"
|
|
31
|
+
}), showBadge && React.createElement(NotificationBellBadge, null, React.createElement(NotificationBellBadgeDot, {
|
|
39
32
|
"$color": getBadgeColor(),
|
|
40
33
|
"$isDot": true
|
|
41
34
|
})));
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
2
|
import { Color } from '@pushwoosh/kit-constants';
|
|
3
3
|
import { Horizontal, Vertical } from '@pushwoosh/kit-helpers';
|
|
4
4
|
import { Text } from '@pushwoosh/kit-typography';
|
|
5
|
+
import { useInfiniteScroll } from './useInfiniteScroll';
|
|
5
6
|
import { Badge } from '../Badge';
|
|
6
7
|
import { Spinner } from '../Spinner';
|
|
7
8
|
import emptyNotificationsIcon from './assets/EmptyNotifications.svg?url';
|
|
@@ -33,9 +34,6 @@ export function NotificationInbox({
|
|
|
33
34
|
emptyStateIcon,
|
|
34
35
|
className
|
|
35
36
|
}) {
|
|
36
|
-
const listRef = useRef(null);
|
|
37
|
-
const observerRef = useRef(null);
|
|
38
|
-
const loadMoreRef = useRef(null);
|
|
39
37
|
const unreadCount = notifications.filter(n => !n.isRead).length;
|
|
40
38
|
const handleNotificationClick = useCallback(notification => {
|
|
41
39
|
if (!notification.isRead && onMarkAsRead) {
|
|
@@ -43,31 +41,11 @@ export function NotificationInbox({
|
|
|
43
41
|
}
|
|
44
42
|
onNotificationClick === null || onNotificationClick === void 0 || onNotificationClick(notification);
|
|
45
43
|
}, [onMarkAsRead, onNotificationClick]);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (!loadMoreElement) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
observerRef.current = new IntersectionObserver(entries => {
|
|
55
|
-
const [entry] = entries;
|
|
56
|
-
if (entry !== null && entry !== void 0 && entry.isIntersecting && hasMore && !isLoading) {
|
|
57
|
-
onLoadMore();
|
|
58
|
-
}
|
|
59
|
-
}, {
|
|
60
|
-
root: listRef.current,
|
|
61
|
-
rootMargin: '100px',
|
|
62
|
-
threshold: 0.1
|
|
63
|
-
});
|
|
64
|
-
observerRef.current.observe(loadMoreElement);
|
|
65
|
-
return () => {
|
|
66
|
-
if (observerRef.current) {
|
|
67
|
-
observerRef.current.disconnect();
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
}, [hasMore, onLoadMore, isLoading]);
|
|
44
|
+
const loadMoreRef = useInfiniteScroll({
|
|
45
|
+
hasMore,
|
|
46
|
+
isLoading,
|
|
47
|
+
onLoadMore
|
|
48
|
+
});
|
|
71
49
|
if (notifications.length === 0 && !isLoading) {
|
|
72
50
|
return React.createElement(NotificationInboxContainer, {
|
|
73
51
|
className: className
|
|
@@ -109,7 +87,7 @@ export function NotificationInbox({
|
|
|
109
87
|
"$variant": "h4",
|
|
110
88
|
"$color": Color.LOCKED
|
|
111
89
|
}, unreadCount, ' ', "unread")))), React.createElement(NotificationInboxList, {
|
|
112
|
-
|
|
90
|
+
"data-notification-list": true
|
|
113
91
|
}, notifications.map(notification => {
|
|
114
92
|
const isRead = notification.isRead ?? false;
|
|
115
93
|
const badgeColor = severityToBadgeColorMap[notification.severity] || 'gray';
|
|
@@ -156,11 +134,12 @@ export function NotificationInbox({
|
|
|
156
134
|
}
|
|
157
135
|
}, notification.expandButton.label))));
|
|
158
136
|
}), hasMore && React.createElement(NotificationInboxLoadMore, {
|
|
137
|
+
ref: loadMoreRef,
|
|
159
138
|
"$variant": "footnote",
|
|
160
139
|
"$color": Color.PHANTOM
|
|
161
140
|
}, isLoading ? React.createElement(Spinner, {
|
|
162
141
|
size: "small"
|
|
163
|
-
}) : 'Loading more...'), isLoading && notifications.length === 0 && React.createElement(Horizontal, {
|
|
142
|
+
}) : 'Loading more...'), isLoading && notifications.length === 0 && !hasMore && React.createElement(Horizontal, {
|
|
164
143
|
"$justifyContent": "center",
|
|
165
144
|
"$alignItems": "center",
|
|
166
145
|
"$padding": "16px 0"
|
|
@@ -431,7 +431,6 @@ export declare const NotificationBarBadgeText: import("styled-components").Style
|
|
|
431
431
|
export declare const NotificationBellButton: import("styled-components").StyledComponent<"button", any, {
|
|
432
432
|
$isOpened: boolean;
|
|
433
433
|
}, never>;
|
|
434
|
-
export declare const NotificationBellIcon: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
435
434
|
export declare const NotificationBellBadge: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
436
435
|
export declare const NotificationBellBadgeDot: import("styled-components").StyledComponent<"div", any, {
|
|
437
436
|
$color: string;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import styled from 'styled-components';
|
|
2
|
-
import { Color, FontSize, FontWeight, FontFamily, ShapeRadius } from '@pushwoosh/kit-constants';
|
|
2
|
+
import { Color, FontSize, FontWeight, FontFamily, ShapeRadius, Shadow } from '@pushwoosh/kit-constants';
|
|
3
3
|
import { Horizontal, Vertical } from '@pushwoosh/kit-helpers';
|
|
4
4
|
import { Text } from '@pushwoosh/kit-typography';
|
|
5
5
|
export const NotificationInboxContainer = styled(Vertical).withConfig({
|
|
6
6
|
displayName: "NotificationInboxContainer",
|
|
7
7
|
componentId: "sc-1nrene1-0"
|
|
8
|
-
})(["width:100%;min-width:360px;max-width:360px;max-height:600px;background:", ";border:1px solid ", ";border-radius:", ";overflow:hidden;display:flex;flex-direction:column;"], Color.CLEAR, Color.FORM, ShapeRadius.DIALOG);
|
|
8
|
+
})(["width:100%;min-width:360px;max-width:360px;max-height:600px;background:", ";border:1px solid ", ";border-radius:", ";box-shadow:", ";overflow:hidden;display:flex;flex-direction:column;"], Color.CLEAR, Color.FORM, ShapeRadius.DIALOG, Shadow.REGULAR);
|
|
9
9
|
export const NotificationInboxHeader = styled(Horizontal).withConfig({
|
|
10
10
|
displayName: "NotificationInboxHeader",
|
|
11
11
|
componentId: "sc-1nrene1-1"
|
|
@@ -237,7 +237,7 @@ export const NotificationBarBadgeText = styled(Text).withConfig({
|
|
|
237
237
|
export const NotificationBellButton = styled.button.withConfig({
|
|
238
238
|
displayName: "NotificationBellButton",
|
|
239
239
|
componentId: "sc-1nrene1-17"
|
|
240
|
-
})(["position:relative;width:36px;height:36px;padding:6px;border:none;background:", ";border-radius:", ";cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background-color 0.2s
|
|
240
|
+
})(["position:relative;width:36px;height:36px;padding:6px;border:none;background:", ";border-radius:", ";cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background-color 0.2s;color:", ";transition:background-color 0.2s,color 0.2s;&:hover:not(:disabled){background-color:", ";color:", ";}"], ({
|
|
241
241
|
$isOpened
|
|
242
242
|
}) => $isOpened ? Color.MAIN : 'transparent', ShapeRadius.CONTROL, ({
|
|
243
243
|
$isOpened
|
|
@@ -246,17 +246,13 @@ export const NotificationBellButton = styled.button.withConfig({
|
|
|
246
246
|
}) => $isOpened ? Color.MAIN : Color.BRIGHT_LIGHT, ({
|
|
247
247
|
$isOpened
|
|
248
248
|
}) => $isOpened ? Color.CLEAR : Color.PRIMARY_HOVER);
|
|
249
|
-
export const NotificationBellIcon = styled.div.withConfig({
|
|
250
|
-
displayName: "NotificationBellIcon",
|
|
251
|
-
componentId: "sc-1nrene1-18"
|
|
252
|
-
})(["width:24px;height:24px;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:color 0.2s;color:var(--icon-color);"]);
|
|
253
249
|
export const NotificationBellBadge = styled.div.withConfig({
|
|
254
250
|
displayName: "NotificationBellBadge",
|
|
255
|
-
componentId: "sc-1nrene1-
|
|
251
|
+
componentId: "sc-1nrene1-18"
|
|
256
252
|
})(["position:absolute;right:4px;top:4px;z-index:1;"]);
|
|
257
253
|
export const NotificationBellBadgeDot = styled.div.withConfig({
|
|
258
254
|
displayName: "NotificationBellBadgeDot",
|
|
259
|
-
componentId: "sc-1nrene1-
|
|
255
|
+
componentId: "sc-1nrene1-19"
|
|
260
256
|
})(["background-color:", ";border-radius:100px;", " display:flex;align-items:center;justify-content:center;font-size:10px;font-family:", ";font-weight:", ";line-height:1;color:", ";white-space:nowrap;"], ({
|
|
261
257
|
$color
|
|
262
258
|
}) => $color, ({
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type UseInfiniteScrollOptions = {
|
|
2
|
+
hasMore: boolean;
|
|
3
|
+
isLoading: boolean;
|
|
4
|
+
onLoadMore?: () => void;
|
|
5
|
+
root?: Element | null;
|
|
6
|
+
rootMargin?: string;
|
|
7
|
+
threshold?: number | number[];
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare function useInfiniteScroll({ hasMore, isLoading, onLoadMore, root, rootMargin, threshold, enabled, }: UseInfiniteScrollOptions): (node: HTMLDivElement | null) => void;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
export function useInfiniteScroll({
|
|
3
|
+
hasMore,
|
|
4
|
+
isLoading,
|
|
5
|
+
onLoadMore,
|
|
6
|
+
root,
|
|
7
|
+
rootMargin = '100px',
|
|
8
|
+
threshold = 0.1,
|
|
9
|
+
enabled = true
|
|
10
|
+
}) {
|
|
11
|
+
const elementRef = useRef(null);
|
|
12
|
+
const observerRef = useRef(null);
|
|
13
|
+
const setRef = useCallback(node => {
|
|
14
|
+
elementRef.current = node;
|
|
15
|
+
}, []);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
var _observerRef$current;
|
|
18
|
+
const el = elementRef.current;
|
|
19
|
+
if (!enabled || !el || !hasMore || !onLoadMore) return;
|
|
20
|
+
const resolvedRoot = root ?? el.closest('[data-notification-list]');
|
|
21
|
+
(_observerRef$current = observerRef.current) === null || _observerRef$current === void 0 || _observerRef$current.disconnect();
|
|
22
|
+
observerRef.current = new IntersectionObserver(([entry]) => {
|
|
23
|
+
if (entry !== null && entry !== void 0 && entry.isIntersecting && !isLoading && hasMore) {
|
|
24
|
+
onLoadMore();
|
|
25
|
+
}
|
|
26
|
+
}, {
|
|
27
|
+
root: resolvedRoot,
|
|
28
|
+
rootMargin,
|
|
29
|
+
threshold
|
|
30
|
+
});
|
|
31
|
+
observerRef.current.observe(el);
|
|
32
|
+
return () => {
|
|
33
|
+
var _observerRef$current2;
|
|
34
|
+
(_observerRef$current2 = observerRef.current) === null || _observerRef$current2 === void 0 || _observerRef$current2.disconnect();
|
|
35
|
+
observerRef.current = null;
|
|
36
|
+
};
|
|
37
|
+
}, [enabled, hasMore, isLoading, onLoadMore, root, rootMargin, threshold]);
|
|
38
|
+
return setRef;
|
|
39
|
+
}
|