@stack-spot/portal-components 2.6.1 → 2.8.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.
- package/CHANGELOG.md +14 -0
- package/dist/components/notification/NotificationItem.d.ts.map +1 -1
- package/dist/components/notification/NotificationItem.js +5 -2
- package/dist/components/notification/NotificationItem.js.map +1 -1
- package/dist/components/notification/types.d.ts +7 -2
- package/dist/components/notification/types.d.ts.map +1 -1
- package/dist/components/notification/types.js.map +1 -1
- package/dist/context/notification/hooks.d.ts +6 -1
- package/dist/context/notification/hooks.d.ts.map +1 -1
- package/dist/context/notification/hooks.js +9 -0
- package/dist/context/notification/hooks.js.map +1 -1
- package/dist/hooks/keyboard.d.ts +35 -3
- package/dist/hooks/keyboard.d.ts.map +1 -1
- package/dist/hooks/keyboard.js +33 -8
- package/dist/hooks/keyboard.js.map +1 -1
- package/package.json +1 -1
- package/src/components/notification/NotificationItem.tsx +6 -4
- package/src/components/notification/types.ts +10 -3
- package/src/context/notification/hooks.ts +12 -0
- package/src/hooks/keyboard.tsx +57 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.8.0](https://github.com/stack-spot/portal-commons/compare/portal-components@v2.7.0...portal-components@v2.8.0) (2024-10-25)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* adds new features to the keyboard hook ([#459](https://github.com/stack-spot/portal-commons/issues/459)) ([39b669c](https://github.com/stack-spot/portal-commons/commit/39b669c4ea4b551b399be50678399e14607ce167))
|
|
9
|
+
|
|
10
|
+
## [2.7.0](https://github.com/stack-spot/portal-commons/compare/portal-components@v2.6.1...portal-components@v2.7.0) (2024-10-18)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* Handle i18n in notification ([#445](https://github.com/stack-spot/portal-commons/issues/445)) ([1803cea](https://github.com/stack-spot/portal-commons/commit/1803cea1f5ef3b257debb6383dd0c0bc81c9597a))
|
|
16
|
+
|
|
3
17
|
## [2.6.1](https://github.com/stack-spot/portal-commons/compare/portal-components@v2.6.0...portal-components@v2.6.1) (2024-09-26)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotificationItem.d.ts","sourceRoot":"","sources":["../../../src/components/notification/NotificationItem.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NotificationItem.d.ts","sourceRoot":"","sources":["../../../src/components/notification/NotificationItem.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,8BAA8B,EAAE,MAAM,SAAS,CAAA;AAexD,UAAU,KAAK;IACb,YAAY,EAAE,8BAA8B,CAAC;IAC7C,SAAS,EAAE,OAAO,CAAC;IAEnB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAyHD,UAAU,+BAAgC,SAAQ,KAAK;IACrD;;;;;;;;;;OAUG;IACH,qBAAqB,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,GAAG,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/F;AAED,UAAU,wBAAyB,SAAQ,KAAK;IAC9C;;OAEG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,KAAK,qBAAqB,GAAG,+BAA+B,GAAG,wBAAwB,CAAA;AAEvF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,0CAA2C,qBAAqB,4CA2C5F,CAAA"}
|
|
@@ -6,6 +6,7 @@ import { useTranslate } from '@stack-spot/portal-translate';
|
|
|
6
6
|
import { differenceInDays, parseISO } from 'date-fns';
|
|
7
7
|
import { useAnchorTag } from '../../context/anchor.js';
|
|
8
8
|
import { useDateFormatter } from '../../hooks/date.js';
|
|
9
|
+
import { useGetNotificationTitleAndDescription } from '../../context/notification/hooks.js';
|
|
9
10
|
import { LazyMarkdown } from '../LazyMarkdown/index.js';
|
|
10
11
|
const styles = {
|
|
11
12
|
item: (color, isRead) => ({
|
|
@@ -50,8 +51,9 @@ const getDaysAgo = (dateString) => {
|
|
|
50
51
|
const NotificationContent = ({ notification, isSummary }) => {
|
|
51
52
|
const { formatDate } = useDateFormatter();
|
|
52
53
|
const t = useTranslate(dictionary);
|
|
54
|
+
const { description } = useGetNotificationTitleAndDescription(notification);
|
|
53
55
|
const daysAgo = getDaysAgo(notification.trigger_at);
|
|
54
|
-
return (_jsxs(_Fragment, { children: [!isSummary && _jsx(Flex, { mt: 4, mb: 3, children: _jsx(LazyMarkdown, { children:
|
|
56
|
+
return (_jsxs(_Fragment, { children: [!isSummary && _jsx(Flex, { mt: 4, mb: 3, children: _jsx(LazyMarkdown, { children: description }) }), _jsxs(Flex, { children: [_jsx(Text, { appearance: "microtext1", colorScheme: "light.700", children: t[notification.context] }), _jsx(Text, { appearance: "microtext1", colorScheme: "light.700", mx: "2", children: "\u2022" }), !isSummary && _jsxs(_Fragment, { children: [_jsx(Text, { appearance: "microtext1", colorScheme: "light.700", children: formatDate(notification.trigger_at) }), _jsx(Text, { appearance: "microtext1", colorScheme: "light.700", mx: "2", children: "\u2022" })] }), _jsx(Text, { appearance: "microtext1", colorScheme: "light.700", children: daysAgo > 0 ? daysAgo + ' ' + t.daysAgo : t.today })] })] }));
|
|
55
57
|
};
|
|
56
58
|
/**
|
|
57
59
|
* NotificationFooter component that renders the footer of a notification.
|
|
@@ -70,6 +72,7 @@ const NotificationFooter = ({ actionURL, onClickAction, title }) => {
|
|
|
70
72
|
*/
|
|
71
73
|
export const NotificationItem = ({ notification, isSummary, ...props }) => {
|
|
72
74
|
const t = useTranslate(dictionary);
|
|
75
|
+
const { title } = useGetNotificationTitleAndDescription(notification);
|
|
73
76
|
function commit() {
|
|
74
77
|
if ('onCommit' in props)
|
|
75
78
|
props.onCommit();
|
|
@@ -85,7 +88,7 @@ export const NotificationItem = ({ notification, isSummary, ...props }) => {
|
|
|
85
88
|
else
|
|
86
89
|
props.onClickMarkReadUnread(true, 'callToAction');
|
|
87
90
|
}
|
|
88
|
-
return (_jsxs(Box, { sx: { position: 'relative' }, children: [_jsxs(Flex, { bg: "light.400", p: "3 3 3 5", r: "xs", flexDirection: "column", w: "100%", sx: styles.item(statusToColor[notification.criticality], notification.committed), children: [_jsx(NotificationHeader, { title:
|
|
91
|
+
return (_jsxs(Box, { sx: { position: 'relative' }, children: [_jsxs(Flex, { bg: "light.400", p: "3 3 3 5", r: "xs", flexDirection: "column", w: "100%", sx: styles.item(statusToColor[notification.criticality], notification.committed), children: [_jsx(NotificationHeader, { title: title, isSummary: isSummary }), _jsx(NotificationContent, { notification: notification, isSummary: isSummary }), notification.call_to_action && _jsx(NotificationFooter, { actionURL: notification.call_to_action, onClickAction: clickAction, title: title })] }), _jsx(Box, { sx: { position: 'absolute', top: '8px', right: '8px' }, children: _jsx(Tooltip, { text: notification.committed ? t.committed : t.uncommitted, position: "left", sx: style.tooltip, children: notification.committed
|
|
89
92
|
? _jsx(IconBox, { role: "img", "aria-label": t.committed, size: "xs", style: { margin: '4px', opacity: 0.5 }, children: _jsx(EnvelopeOpen, {}) })
|
|
90
93
|
: (_jsx(IconButton, { "aria-label": t.uncommitted, onClick: commit, children: _jsx(IconBox, { size: "xs", children: _jsx(Envelope, {}) }) })) }) })] }));
|
|
91
94
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotificationItem.js","sourceRoot":"","sources":["../../../src/components/notification/NotificationItem.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAiD,IAAI,EAAE,MAAM,cAAc,CAAA;AAC9G,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAc,YAAY,EAAE,MAAM,8BAA8B,CAAA;AACvE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAGpD,MAAM,MAAM,GAAG;IACb,IAAI,EAAE,CAAC,KAAa,EAAE,MAAe,EAAE,EAAE,CAAC,CAAC;QACzC,UAAU,EAAE,aAAa,KAAK,EAAE;QAChC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAC1B,CAAC;CACgD,CAAA;AAEpD,MAAM,aAAa,GAAkD;IACnE,GAAG,EAAE,aAAa;IAClB,MAAM,EAAE,aAAa;IACrB,IAAI,EAAE,YAAY;CACnB,CAAA;AASD,MAAM,KAAK,GAAW;IACpB,OAAO,EAAE;QACP,UAAU,EAAE;YACV,GAAG,EAAE,KAAK;SACX;KACF;CACF,CAAA;AAED;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,CAAC,EAAE,KAAK,EAAE,SAAS,EAAyC,EAAE,EAAE,CAAC,CAC1F,KAAC,IAAI,IAAC,cAAc,EAAC,eAAe,EAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAC,QAAQ,YAC3G,KAAC,IAAI,IAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,cAAc,kBAC5D,KAAK,GACD,GACF,CACR,CAAA;AAED;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,UAAkB,EAAU,EAAE;IAChD,MAAM,SAAS,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAA;IACtC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAA;IACxB,OAAO,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;AAC3C,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,CAAC,EAAE,YAAY,EAAE,SAAS,EAAS,EAAE,EAAE;IACjE,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,EAAE,CAAA;IACzC,MAAM,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"NotificationItem.js","sourceRoot":"","sources":["../../../src/components/notification/NotificationItem.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
export type NotificationType = 'LOW' | 'MEDIUM' | 'HIGH';
|
|
2
2
|
export type NotificationContext = 'ACCOUNT' | 'STUDIO' | 'WORKSPACE' | 'AI';
|
|
3
|
-
export type
|
|
4
|
-
id: string;
|
|
3
|
+
export type NotificationContentResponse = {
|
|
5
4
|
title: string;
|
|
6
5
|
description: string;
|
|
6
|
+
};
|
|
7
|
+
export type GetTenantNotificationsResponse = {
|
|
8
|
+
id: string;
|
|
9
|
+
content: {
|
|
10
|
+
[key: string]: NotificationContentResponse;
|
|
11
|
+
};
|
|
7
12
|
broadcast_level: 'ACCOUNT' | 'INDIVIDUAL' | 'PLATFORM' | 'RESOURCE';
|
|
8
13
|
context: 'ACCOUNT' | 'STUDIO' | 'WORKSPACE' | 'AI';
|
|
9
14
|
target?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/notification/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;AAExD,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/notification/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;AAExD,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,IAAI,CAAA;AAI3E,MAAM,MAAM,2BAA2B,GAAG;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE;QACP,CAAC,GAAG,EAAE,MAAM,GAAG,2BAA2B,CAAC;KAC5C,CAAC;IACF,eAAe,EAAE,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;IACpE,OAAO,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,IAAI,CAAC;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAA;AAED,MAAM,MAAM,2CAA2C,GAAG;IACxD,KAAK,EAAE,8BAA8B,EAAE,CAAC;IACxC,KAAK,EAAE,MAAM,CAAC;CACf,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG,UAAU,CAAA;AAEnE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;CACpB;AAID,oBAAY,UAAU;IACpB,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;CAChD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/notification/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/notification/types.ts"],"names":[],"mappings":"AAiDA,iIAAiI;AACjI,gDAAgD;AAChD,MAAM,CAAN,IAAY,UAEX;AAFD,WAAY,UAAU;IACpB,+BAAiB,CAAA;AACnB,CAAC,EAFW,UAAU,KAAV,UAAU,QAErB"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { GetTenantNotificationsResponse } from '../../notifications.js';
|
|
1
2
|
import { LoadNotificationsFilters } from './types.js';
|
|
2
3
|
export declare function useNotificationList(initialFilters?: LoadNotificationsFilters): {
|
|
3
4
|
status: "loading" | "error" | "startup" | "idle";
|
|
4
|
-
items:
|
|
5
|
+
items: GetTenantNotificationsResponse[];
|
|
5
6
|
hasMore: boolean;
|
|
6
7
|
loadMore: () => Promise<void> | undefined;
|
|
7
8
|
refresh: () => Promise<void>;
|
|
@@ -9,5 +10,9 @@ export declare function useNotificationList(initialFilters?: LoadNotificationsFi
|
|
|
9
10
|
filters: LoadNotificationsFilters;
|
|
10
11
|
error: any;
|
|
11
12
|
};
|
|
13
|
+
export declare function useGetNotificationTitleAndDescription({ content }: GetTenantNotificationsResponse): {
|
|
14
|
+
title: string;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
12
17
|
export declare function useUnreadNotifications(): boolean;
|
|
13
18
|
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/context/notification/hooks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/context/notification/hooks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAA;AAKpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAElD,wBAAgB,mBAAmB,CAAC,cAAc,GAAE,wBAA6B;;;;;;+BA0B3B,wBAAwB;;;EAuC7E;AAED,wBAAgB,qCAAqC,CAAC,EAAE,OAAO,EAAE,EAAE,8BAA8B;;;EAQhG;AAED,wBAAgB,sBAAsB,YAWrC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useRef, useState } from 'react';
|
|
2
|
+
import { useLanguage } from '@stack-spot/portal-translate';
|
|
2
3
|
import { useManualRender } from '../../hooks/manual-render.js';
|
|
3
4
|
import { useEffectOnce } from '../../hooks/use-effect-once.js';
|
|
4
5
|
import { useNotificationController } from './context.js';
|
|
@@ -70,6 +71,14 @@ export function useNotificationList(initialFilters = {}) {
|
|
|
70
71
|
error: error.current,
|
|
71
72
|
};
|
|
72
73
|
}
|
|
74
|
+
export function useGetNotificationTitleAndDescription({ content }) {
|
|
75
|
+
const language = useLanguage();
|
|
76
|
+
const { title, description } = content?.[language] || content?.en || {};
|
|
77
|
+
return {
|
|
78
|
+
title,
|
|
79
|
+
description: description?.replace(/^\s*#+\s*/gm, ''),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
73
82
|
export function useUnreadNotifications() {
|
|
74
83
|
const [hasUnreadNotifications, setUnreadNotifications] = useState(false);
|
|
75
84
|
const controller = useNotificationController();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/context/notification/hooks.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/context/notification/hooks.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks/keyboard.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
interface
|
|
2
|
+
interface Options<T extends HTMLElement = HTMLDivElement> {
|
|
3
3
|
/**
|
|
4
4
|
* A query selector that returns every html element that must be navigable through the keyboard.
|
|
5
5
|
*/
|
|
@@ -11,8 +11,29 @@ interface Props {
|
|
|
11
11
|
/**
|
|
12
12
|
* Function to call when TAB is pressed at the last item in the list of items returned by the query selector. Will be the same as
|
|
13
13
|
* onPressEscape if not specified.
|
|
14
|
+
*
|
|
15
|
+
* Attention: has no effect if `disableTabBehavior` is true.
|
|
14
16
|
*/
|
|
15
17
|
onPressLastTab?: () => void;
|
|
18
|
+
/**
|
|
19
|
+
* Pass this function if you want any behavior when the user presses the arrow left.
|
|
20
|
+
*/
|
|
21
|
+
onPressArrowLeft?: () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Pass this function if you want any behavior when the user presses the arrow right.
|
|
24
|
+
*/
|
|
25
|
+
onPressArrowRight?: () => void;
|
|
26
|
+
/**
|
|
27
|
+
* Disables any alteration to the tab key.
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
disableTabBehavior?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* If you already have a ref to the element you want to attach the events to, you can pass it in this prop.
|
|
33
|
+
*
|
|
34
|
+
* If you pass a ref. The events won't be attached to the document, instead, they will be attached to the element referred by the ref.
|
|
35
|
+
*/
|
|
36
|
+
ref?: React.RefObject<T>;
|
|
16
37
|
}
|
|
17
38
|
/**
|
|
18
39
|
* Creates listeners for controlling a Menu UI through the keyboard.
|
|
@@ -20,11 +41,22 @@ interface Props {
|
|
|
20
41
|
* - Arrow up: previous element in the iterator returned by the query selectors. Last element, if the current element is the first.
|
|
21
42
|
* - Tab: same as Arrow down, but has a different behavior if the element is the last (see onPressLastTab).
|
|
22
43
|
* - Esc: determined by onPressEscape.
|
|
23
|
-
* @param props {@link
|
|
44
|
+
* @param props {@link Options}.
|
|
24
45
|
* @returns an object with the element controlled by the keyboard (useRef); a function to attach the keyboard events and a function to
|
|
25
46
|
* detach the keyboard events.
|
|
26
47
|
*/
|
|
27
|
-
export declare function useKeyboardControls<T extends HTMLElement = HTMLDivElement>(
|
|
48
|
+
export declare function useKeyboardControls<T extends HTMLElement = HTMLDivElement>(
|
|
49
|
+
/**
|
|
50
|
+
* Options for the keyboard controls.
|
|
51
|
+
*/
|
|
52
|
+
{ querySelectors, onPressEscape, onPressLastTab, onPressArrowLeft, onPressArrowRight, disableTabBehavior, ref, }: Options<T>,
|
|
53
|
+
/**
|
|
54
|
+
* Calls `attachKeyboardListeners` (mount) and `detachKeyboardListeners` (unmount) whenever the deps passed as parameter changes.
|
|
55
|
+
*
|
|
56
|
+
* If deps are undefined, this component doesn't automatically add these listeners and you have to use the functions returned in the
|
|
57
|
+
* result.
|
|
58
|
+
*/
|
|
59
|
+
deps?: any[]): {
|
|
28
60
|
keyboardControlledElement: import("react").RefObject<T>;
|
|
29
61
|
attachKeyboardListeners: () => void;
|
|
30
62
|
detachKeyboardListeners: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../src/hooks/keyboard.tsx"],"names":[],"mappings":";AAEA,UAAU,
|
|
1
|
+
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../src/hooks/keyboard.tsx"],"names":[],"mappings":";AAEA,UAAU,OAAO,CAAC,CAAC,SAAS,WAAW,GAAG,cAAc;IACtD;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;OAIG;IACH,GAAG,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,WAAW,GAAG,cAAc;AACxE;;GAEG;AACH,EACE,cAAc,EAAE,aAAa,EAAE,cAA8B,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,GAAG,GAC5H,EAAE,OAAO,CAAC,CAAC,CAAC;AACb;;;;;GAKG;AACH,IAAI,CAAC,EAAE,GAAG,EAAE;;;;EAiEb"}
|
package/dist/hooks/keyboard.js
CHANGED
|
@@ -1,24 +1,37 @@
|
|
|
1
|
-
import { useCallback, useRef } from 'react';
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
2
|
/**
|
|
3
3
|
* Creates listeners for controlling a Menu UI through the keyboard.
|
|
4
4
|
* - Arrow down: next element in the iterator returned by the query selectors. First element, if the current element is the last.
|
|
5
5
|
* - Arrow up: previous element in the iterator returned by the query selectors. Last element, if the current element is the first.
|
|
6
6
|
* - Tab: same as Arrow down, but has a different behavior if the element is the last (see onPressLastTab).
|
|
7
7
|
* - Esc: determined by onPressEscape.
|
|
8
|
-
* @param props {@link
|
|
8
|
+
* @param props {@link Options}.
|
|
9
9
|
* @returns an object with the element controlled by the keyboard (useRef); a function to attach the keyboard events and a function to
|
|
10
10
|
* detach the keyboard events.
|
|
11
11
|
*/
|
|
12
|
-
export function useKeyboardControls(
|
|
13
|
-
|
|
12
|
+
export function useKeyboardControls(
|
|
13
|
+
/**
|
|
14
|
+
* Options for the keyboard controls.
|
|
15
|
+
*/
|
|
16
|
+
{ querySelectors, onPressEscape, onPressLastTab = onPressEscape, onPressArrowLeft, onPressArrowRight, disableTabBehavior, ref, },
|
|
17
|
+
/**
|
|
18
|
+
* Calls `attachKeyboardListeners` (mount) and `detachKeyboardListeners` (unmount) whenever the deps passed as parameter changes.
|
|
19
|
+
*
|
|
20
|
+
* If deps are undefined, this component doesn't automatically add these listeners and you have to use the functions returned in the
|
|
21
|
+
* result.
|
|
22
|
+
*/
|
|
23
|
+
deps) {
|
|
24
|
+
const localRef = useRef(null);
|
|
25
|
+
const keyboardControlledElement = ref ?? localRef;
|
|
14
26
|
const listeners = useRef({});
|
|
15
27
|
listeners.current = { onPressEscape, onPressLastTab };
|
|
16
28
|
const keyboardControls = useCallback((event) => {
|
|
29
|
+
const eventKey = event.key;
|
|
17
30
|
const target = event?.target;
|
|
18
31
|
function getSelectableAnchors() {
|
|
19
32
|
return keyboardControlledElement.current?.querySelectorAll(querySelectors) ?? [];
|
|
20
33
|
}
|
|
21
|
-
function handleArrows(key =
|
|
34
|
+
function handleArrows(key = eventKey) {
|
|
22
35
|
const anchors = getSelectableAnchors();
|
|
23
36
|
let i = 0;
|
|
24
37
|
while (i < anchors.length && document.activeElement !== anchors[i])
|
|
@@ -36,6 +49,8 @@ export function useKeyboardControls({ querySelectors, onPressEscape, onPressLast
|
|
|
36
49
|
target?.click();
|
|
37
50
|
},
|
|
38
51
|
Tab: () => {
|
|
52
|
+
if (disableTabBehavior)
|
|
53
|
+
return;
|
|
39
54
|
const anchors = getSelectableAnchors();
|
|
40
55
|
if (document.activeElement === anchors[anchors.length - 1])
|
|
41
56
|
listeners.current.onPressLastTab?.();
|
|
@@ -45,15 +60,25 @@ export function useKeyboardControls({ querySelectors, onPressEscape, onPressLast
|
|
|
45
60
|
},
|
|
46
61
|
ArrowUp: handleArrows,
|
|
47
62
|
ArrowDown: handleArrows,
|
|
63
|
+
ArrowLeft: onPressArrowLeft,
|
|
64
|
+
ArrowRight: onPressArrowRight,
|
|
48
65
|
};
|
|
49
|
-
handlers[
|
|
66
|
+
handlers[eventKey]?.();
|
|
50
67
|
}, []);
|
|
51
68
|
const attachKeyboardListeners = useCallback(() => {
|
|
52
|
-
document
|
|
69
|
+
const element = ref?.current ?? document;
|
|
70
|
+
element.addEventListener('keydown', keyboardControls);
|
|
53
71
|
}, []);
|
|
54
72
|
const detachKeyboardListeners = useCallback(() => {
|
|
55
|
-
document
|
|
73
|
+
const element = ref?.current ?? document;
|
|
74
|
+
element.removeEventListener('keydown', keyboardControls);
|
|
56
75
|
}, []);
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (!deps)
|
|
78
|
+
return;
|
|
79
|
+
attachKeyboardListeners();
|
|
80
|
+
return detachKeyboardListeners;
|
|
81
|
+
}, deps);
|
|
57
82
|
return { keyboardControlledElement, attachKeyboardListeners, detachKeyboardListeners };
|
|
58
83
|
}
|
|
59
84
|
//# sourceMappingURL=keyboard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../../src/hooks/keyboard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../../src/hooks/keyboard.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
|
5
5
|
import { differenceInDays, parseISO } from 'date-fns'
|
|
6
6
|
import { useAnchorTag } from '../../context/anchor'
|
|
7
7
|
import { useDateFormatter } from '../../hooks/date'
|
|
8
|
+
import { useGetNotificationTitleAndDescription } from '../../context/notification/hooks'
|
|
8
9
|
import { LazyMarkdown } from '../LazyMarkdown/index'
|
|
9
10
|
import { GetTenantNotificationsResponse } from './types'
|
|
10
11
|
|
|
@@ -69,13 +70,13 @@ const getDaysAgo = (dateString: string): number => {
|
|
|
69
70
|
const NotificationContent = ({ notification, isSummary }: Props) => {
|
|
70
71
|
const { formatDate } = useDateFormatter()
|
|
71
72
|
const t = useTranslate(dictionary)
|
|
72
|
-
|
|
73
|
+
const { description } = useGetNotificationTitleAndDescription(notification)
|
|
73
74
|
const daysAgo = getDaysAgo(notification.trigger_at)
|
|
74
75
|
|
|
75
76
|
return (
|
|
76
77
|
<>
|
|
77
78
|
{!isSummary && <Flex mt={4} mb={3}>
|
|
78
|
-
<LazyMarkdown>{
|
|
79
|
+
<LazyMarkdown>{description}</LazyMarkdown>
|
|
79
80
|
</Flex>}
|
|
80
81
|
<Flex>
|
|
81
82
|
<Text appearance="microtext1" colorScheme="light.700">
|
|
@@ -185,6 +186,7 @@ type NotificationItemProps = DeprecatedNotificationItemProps | NewNotificationIt
|
|
|
185
186
|
*/
|
|
186
187
|
export const NotificationItem = ({ notification, isSummary, ...props }: NotificationItemProps) => {
|
|
187
188
|
const t = useTranslate(dictionary)
|
|
189
|
+
const { title } = useGetNotificationTitleAndDescription(notification)
|
|
188
190
|
|
|
189
191
|
function commit() {
|
|
190
192
|
if ('onCommit' in props) props.onCommit()
|
|
@@ -203,12 +205,12 @@ export const NotificationItem = ({ notification, isSummary, ...props }: Notifica
|
|
|
203
205
|
<Box sx={{ position: 'relative' }}>
|
|
204
206
|
<Flex bg="light.400" p="3 3 3 5" r="xs"
|
|
205
207
|
flexDirection="column" w="100%" sx={styles.item(statusToColor[notification.criticality], notification.committed)}>
|
|
206
|
-
<NotificationHeader title={
|
|
208
|
+
<NotificationHeader title={title} isSummary={isSummary} />
|
|
207
209
|
<NotificationContent notification={notification} isSummary={isSummary} />
|
|
208
210
|
{notification.call_to_action && <NotificationFooter
|
|
209
211
|
actionURL={notification.call_to_action}
|
|
210
212
|
onClickAction={clickAction}
|
|
211
|
-
title={
|
|
213
|
+
title={title}
|
|
212
214
|
/>}
|
|
213
215
|
</Flex>
|
|
214
216
|
<Box sx={{ position: 'absolute', top: '8px', right: '8px' }}>
|
|
@@ -2,11 +2,18 @@ export type NotificationType = 'LOW' | 'MEDIUM' | 'HIGH'
|
|
|
2
2
|
|
|
3
3
|
export type NotificationContext = 'ACCOUNT' | 'STUDIO' | 'WORKSPACE' | 'AI'
|
|
4
4
|
|
|
5
|
-
//The following
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
//The following three notification types comes from the api swagger
|
|
6
|
+
|
|
7
|
+
export type NotificationContentResponse = {
|
|
8
8
|
title: string,
|
|
9
9
|
description: string,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type GetTenantNotificationsResponse = {
|
|
13
|
+
id: string,
|
|
14
|
+
content: {
|
|
15
|
+
[key: string]: NotificationContentResponse,
|
|
16
|
+
},
|
|
10
17
|
broadcast_level: 'ACCOUNT' | 'INDIVIDUAL' | 'PLATFORM' | 'RESOURCE',
|
|
11
18
|
context: 'ACCOUNT' | 'STUDIO' | 'WORKSPACE' | 'AI',
|
|
12
19
|
target?: string,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { useCallback, useRef, useState } from 'react'
|
|
2
|
+
import { useLanguage } from '@stack-spot/portal-translate'
|
|
3
|
+
import { GetTenantNotificationsResponse } from '../../notifications'
|
|
2
4
|
import { useManualRender } from '../../hooks/manual-render'
|
|
3
5
|
import { useEffectOnce } from '../../hooks/use-effect-once'
|
|
4
6
|
import { useNotificationController } from './context'
|
|
@@ -72,6 +74,16 @@ export function useNotificationList(initialFilters: LoadNotificationsFilters = {
|
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
|
|
77
|
+
export function useGetNotificationTitleAndDescription({ content }: GetTenantNotificationsResponse) {
|
|
78
|
+
const language = useLanguage()
|
|
79
|
+
const { title, description } = content?.[language] || content?.en || {}
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
title,
|
|
83
|
+
description: description?.replace(/^\s*#+\s*/gm, ''),
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
75
87
|
export function useUnreadNotifications() {
|
|
76
88
|
const [hasUnreadNotifications, setUnreadNotifications] = useState(false)
|
|
77
89
|
const controller = useNotificationController()
|
package/src/hooks/keyboard.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useCallback, useRef } from 'react'
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react'
|
|
2
2
|
|
|
3
|
-
interface
|
|
3
|
+
interface Options<T extends HTMLElement = HTMLDivElement> {
|
|
4
4
|
/**
|
|
5
5
|
* A query selector that returns every html element that must be navigable through the keyboard.
|
|
6
6
|
*/
|
|
@@ -12,8 +12,29 @@ interface Props {
|
|
|
12
12
|
/**
|
|
13
13
|
* Function to call when TAB is pressed at the last item in the list of items returned by the query selector. Will be the same as
|
|
14
14
|
* onPressEscape if not specified.
|
|
15
|
+
*
|
|
16
|
+
* Attention: has no effect if `disableTabBehavior` is true.
|
|
15
17
|
*/
|
|
16
18
|
onPressLastTab?: () => void,
|
|
19
|
+
/**
|
|
20
|
+
* Pass this function if you want any behavior when the user presses the arrow left.
|
|
21
|
+
*/
|
|
22
|
+
onPressArrowLeft?: () => void,
|
|
23
|
+
/**
|
|
24
|
+
* Pass this function if you want any behavior when the user presses the arrow right.
|
|
25
|
+
*/
|
|
26
|
+
onPressArrowRight?: () => void,
|
|
27
|
+
/**
|
|
28
|
+
* Disables any alteration to the tab key.
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
disableTabBehavior?: boolean,
|
|
32
|
+
/**
|
|
33
|
+
* If you already have a ref to the element you want to attach the events to, you can pass it in this prop.
|
|
34
|
+
*
|
|
35
|
+
* If you pass a ref. The events won't be attached to the document, instead, they will be attached to the element referred by the ref.
|
|
36
|
+
*/
|
|
37
|
+
ref?: React.RefObject<T>,
|
|
17
38
|
}
|
|
18
39
|
|
|
19
40
|
/**
|
|
@@ -22,25 +43,39 @@ interface Props {
|
|
|
22
43
|
* - Arrow up: previous element in the iterator returned by the query selectors. Last element, if the current element is the first.
|
|
23
44
|
* - Tab: same as Arrow down, but has a different behavior if the element is the last (see onPressLastTab).
|
|
24
45
|
* - Esc: determined by onPressEscape.
|
|
25
|
-
* @param props {@link
|
|
46
|
+
* @param props {@link Options}.
|
|
26
47
|
* @returns an object with the element controlled by the keyboard (useRef); a function to attach the keyboard events and a function to
|
|
27
48
|
* detach the keyboard events.
|
|
28
49
|
*/
|
|
29
50
|
export function useKeyboardControls<T extends HTMLElement = HTMLDivElement>(
|
|
30
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Options for the keyboard controls.
|
|
53
|
+
*/
|
|
54
|
+
{
|
|
55
|
+
querySelectors, onPressEscape, onPressLastTab = onPressEscape, onPressArrowLeft, onPressArrowRight, disableTabBehavior, ref,
|
|
56
|
+
}: Options<T>,
|
|
57
|
+
/**
|
|
58
|
+
* Calls `attachKeyboardListeners` (mount) and `detachKeyboardListeners` (unmount) whenever the deps passed as parameter changes.
|
|
59
|
+
*
|
|
60
|
+
* If deps are undefined, this component doesn't automatically add these listeners and you have to use the functions returned in the
|
|
61
|
+
* result.
|
|
62
|
+
*/
|
|
63
|
+
deps?: any[],
|
|
31
64
|
) {
|
|
32
|
-
const
|
|
33
|
-
const
|
|
65
|
+
const localRef = useRef<T>(null)
|
|
66
|
+
const keyboardControlledElement = ref ?? localRef
|
|
67
|
+
const listeners = useRef<Pick<Options, 'onPressEscape' | 'onPressLastTab'>>({})
|
|
34
68
|
listeners.current = { onPressEscape, onPressLastTab }
|
|
35
69
|
|
|
36
|
-
const keyboardControls = useCallback((event:
|
|
70
|
+
const keyboardControls = useCallback((event: Event) => {
|
|
71
|
+
const eventKey = (event as KeyboardEvent).key
|
|
37
72
|
const target = event?.target as HTMLElement | null
|
|
38
73
|
|
|
39
74
|
function getSelectableAnchors() {
|
|
40
75
|
return keyboardControlledElement.current?.querySelectorAll(querySelectors) ?? []
|
|
41
76
|
}
|
|
42
77
|
|
|
43
|
-
function handleArrows(key =
|
|
78
|
+
function handleArrows(key = eventKey) {
|
|
44
79
|
const anchors = getSelectableAnchors()
|
|
45
80
|
let i = 0
|
|
46
81
|
while (i < anchors.length && document.activeElement !== anchors[i]) i++
|
|
@@ -58,6 +93,7 @@ export function useKeyboardControls<T extends HTMLElement = HTMLDivElement>(
|
|
|
58
93
|
target?.click()
|
|
59
94
|
},
|
|
60
95
|
Tab: () => {
|
|
96
|
+
if (disableTabBehavior) return
|
|
61
97
|
const anchors = getSelectableAnchors()
|
|
62
98
|
if (document.activeElement === anchors[anchors.length - 1]) listeners.current.onPressLastTab?.()
|
|
63
99
|
else handleArrows('ArrowDown')
|
|
@@ -65,18 +101,28 @@ export function useKeyboardControls<T extends HTMLElement = HTMLDivElement>(
|
|
|
65
101
|
},
|
|
66
102
|
ArrowUp: handleArrows,
|
|
67
103
|
ArrowDown: handleArrows,
|
|
104
|
+
ArrowLeft: onPressArrowLeft,
|
|
105
|
+
ArrowRight: onPressArrowRight,
|
|
68
106
|
}
|
|
69
107
|
|
|
70
|
-
handlers[
|
|
108
|
+
handlers[eventKey]?.()
|
|
71
109
|
}, [])
|
|
72
110
|
|
|
73
111
|
const attachKeyboardListeners = useCallback(() => {
|
|
74
|
-
document
|
|
112
|
+
const element = ref?.current ?? document
|
|
113
|
+
element.addEventListener('keydown', keyboardControls)
|
|
75
114
|
}, [])
|
|
76
115
|
|
|
77
116
|
const detachKeyboardListeners = useCallback(() => {
|
|
78
|
-
document
|
|
117
|
+
const element = ref?.current ?? document
|
|
118
|
+
element.removeEventListener('keydown', keyboardControls)
|
|
79
119
|
}, [])
|
|
80
120
|
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
if (!deps) return
|
|
123
|
+
attachKeyboardListeners()
|
|
124
|
+
return detachKeyboardListeners
|
|
125
|
+
}, deps)
|
|
126
|
+
|
|
81
127
|
return { keyboardControlledElement, attachKeyboardListeners, detachKeyboardListeners }
|
|
82
128
|
}
|