@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.
@@ -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, NotificationBellIcon, NotificationBellBadge, NotificationBellBadgeDot } from './styles';
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(NotificationBellIcon, null, React.createElement(NotificationIcon, {
34
- size: "small",
35
- view: getIconView(),
26
+ }, React.createElement(NotificationIcon, {
27
+ size: "medium",
36
28
  type: "enabled",
37
- color: getIconColor()
38
- })), showBadge && React.createElement(NotificationBellBadge, null, React.createElement(NotificationBellBadgeDot, {
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, { useEffect, useRef, useCallback } from '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
- useEffect(() => {
47
- if (!hasMore || !onLoadMore || isLoading) {
48
- return;
49
- }
50
- const loadMoreElement = loadMoreRef.current;
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
- ref: listRef
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;--icon-color:", ";&:hover:not(:disabled){background-color:", ";--icon-color:", ";}"], ({
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-19"
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-20"
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushwoosh/dumb-components",
3
- "version": "1.1.88",
3
+ "version": "1.1.89",
4
4
  "description": "React components to build Pushwoosh products",
5
5
  "main": "index.js",
6
6
  "module": "index.js",