@canonical/react-components 2.2.3 → 2.3.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/dist/components/NotificationProvider/NotificationProvider.js +3 -2
- package/dist/components/NotificationProvider/messageBuilder.js +4 -4
- package/dist/components/NotificationProvider/types.d.ts +1 -1
- package/dist/components/{Notification → Notifications/Notification}/Notification.d.ts +1 -1
- package/dist/components/{Notification → Notifications/Notification}/Notification.js +2 -2
- package/dist/components/Notifications/ToastNotification/Animate.d.ts +11 -0
- package/dist/components/Notifications/ToastNotification/Animate.js +58 -0
- package/dist/components/Notifications/ToastNotification/Toast.scss +116 -0
- package/dist/components/Notifications/ToastNotification/ToastNotification.d.ts +10 -0
- package/dist/components/Notifications/ToastNotification/ToastNotification.js +63 -0
- package/dist/components/Notifications/ToastNotification/ToastNotification.stories.d.ts +6 -0
- package/dist/components/Notifications/ToastNotification/ToastNotification.stories.js +63 -0
- package/dist/components/Notifications/ToastNotification/ToastNotificationList.d.ts +21 -0
- package/dist/components/Notifications/ToastNotification/ToastNotificationList.js +215 -0
- package/dist/components/Notifications/ToastNotification/ToastNotificationProvider.d.ts +74 -0
- package/dist/components/Notifications/ToastNotification/ToastNotificationProvider.js +206 -0
- package/dist/components/Notifications/ToastNotification/index.d.ts +5 -0
- package/dist/components/Notifications/ToastNotification/index.js +35 -0
- package/dist/components/Notifications/index.d.ts +4 -0
- package/dist/components/Notifications/index.js +45 -0
- package/dist/components/Slider/Slider.js +1 -0
- package/dist/esm/components/NotificationProvider/NotificationProvider.js +2 -1
- package/dist/esm/components/NotificationProvider/messageBuilder.js +1 -1
- package/dist/esm/components/NotificationProvider/types.d.ts +1 -1
- package/dist/esm/components/{Notification → Notifications/Notification}/Notification.d.ts +1 -1
- package/dist/esm/components/{Notification → Notifications/Notification}/Notification.js +2 -2
- package/dist/esm/components/Notifications/Notification/Notification.test.d.ts +1 -0
- package/dist/esm/components/Notifications/ToastNotification/Animate.d.ts +11 -0
- package/dist/esm/components/Notifications/ToastNotification/Animate.js +51 -0
- package/dist/esm/components/Notifications/ToastNotification/Toast.scss +116 -0
- package/dist/esm/components/Notifications/ToastNotification/ToastNotification.d.ts +10 -0
- package/dist/esm/components/Notifications/ToastNotification/ToastNotification.js +56 -0
- package/dist/esm/components/Notifications/ToastNotification/ToastNotification.stories.d.ts +6 -0
- package/dist/esm/components/Notifications/ToastNotification/ToastNotification.stories.js +54 -0
- package/dist/esm/components/Notifications/ToastNotification/ToastNotification.test.d.ts +1 -0
- package/dist/esm/components/Notifications/ToastNotification/ToastNotificationList.d.ts +21 -0
- package/dist/esm/components/Notifications/ToastNotification/ToastNotificationList.js +208 -0
- package/dist/esm/components/Notifications/ToastNotification/ToastNotificationProvider.d.ts +74 -0
- package/dist/esm/components/Notifications/ToastNotification/ToastNotificationProvider.js +201 -0
- package/dist/esm/components/Notifications/ToastNotification/index.d.ts +5 -0
- package/dist/esm/components/Notifications/ToastNotification/index.js +4 -0
- package/dist/esm/components/Notifications/index.d.ts +4 -0
- package/dist/esm/components/Notifications/index.js +2 -0
- package/dist/esm/components/Slider/Slider.js +1 -0
- package/dist/esm/hooks/index.d.ts +1 -0
- package/dist/esm/hooks/index.js +1 -0
- package/dist/esm/hooks/usePrefersReducedMotion.d.ts +6 -0
- package/dist/esm/hooks/usePrefersReducedMotion.js +23 -0
- package/dist/esm/hooks/usePrefersReducedMotion.test.d.ts +1 -0
- package/dist/esm/index.d.ts +5 -3
- package/dist/esm/index.js +3 -2
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/usePrefersReducedMotion.d.ts +6 -0
- package/dist/hooks/usePrefersReducedMotion.js +30 -0
- package/dist/hooks/usePrefersReducedMotion.test.d.ts +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +38 -3
- package/package.json +1 -1
- /package/dist/components/{Notification → Notifications/Notification}/Notification.stories.d.ts +0 -0
- /package/dist/components/{Notification → Notifications/Notification}/Notification.stories.js +0 -0
- /package/dist/components/{Notification → Notifications/Notification}/Notification.test.d.ts +0 -0
- /package/dist/components/{Notification → Notifications/Notification}/index.d.ts +0 -0
- /package/dist/components/{Notification → Notifications/Notification}/index.js +0 -0
- /package/dist/{esm/components/Notification/Notification.test.d.ts → components/Notifications/ToastNotification/ToastNotification.test.d.ts} +0 -0
- /package/dist/esm/components/{Notification → Notifications/Notification}/Notification.stories.d.ts +0 -0
- /package/dist/esm/components/{Notification → Notifications/Notification}/Notification.stories.js +0 -0
- /package/dist/esm/components/{Notification → Notifications/Notification}/index.d.ts +0 -0
- /package/dist/esm/components/{Notification → Notifications/Notification}/index.js +0 -0
|
@@ -8,7 +8,8 @@ exports.useNotify = useNotify;
|
|
|
8
8
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
9
|
var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal"));
|
|
10
10
|
var _messageBuilder = require("./messageBuilder");
|
|
11
|
-
var
|
|
11
|
+
var _Notifications = _interopRequireDefault(require("../Notifications"));
|
|
12
|
+
var _Notification = require("../Notifications/Notification/Notification");
|
|
12
13
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
14
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
14
15
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
@@ -85,7 +86,7 @@ const NotificationConsumer = () => {
|
|
|
85
86
|
} = notify.notification;
|
|
86
87
|
return /*#__PURE__*/_react.default.createElement("div", {
|
|
87
88
|
ref: ref
|
|
88
|
-
}, /*#__PURE__*/_react.default.createElement(
|
|
89
|
+
}, /*#__PURE__*/_react.default.createElement(_Notifications.default, {
|
|
89
90
|
title: title !== null && title !== void 0 ? title : _Notification.DefaultTitles[type],
|
|
90
91
|
actions: actions,
|
|
91
92
|
severity: type,
|
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.success = exports.queue = exports.info = exports.failure = void 0;
|
|
7
7
|
var _react = _interopRequireDefault(require("react"));
|
|
8
|
-
var
|
|
8
|
+
var _Notifications = require("../Notifications");
|
|
9
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
10
|
const queue = notification => {
|
|
11
11
|
return {
|
|
@@ -19,7 +19,7 @@ const info = (message, title) => {
|
|
|
19
19
|
return {
|
|
20
20
|
message,
|
|
21
21
|
title,
|
|
22
|
-
type:
|
|
22
|
+
type: _Notifications.NotificationSeverity.INFORMATION
|
|
23
23
|
};
|
|
24
24
|
};
|
|
25
25
|
exports.info = info;
|
|
@@ -27,7 +27,7 @@ const success = (message, title) => {
|
|
|
27
27
|
return {
|
|
28
28
|
message,
|
|
29
29
|
title,
|
|
30
|
-
type:
|
|
30
|
+
type: _Notifications.NotificationSeverity.POSITIVE
|
|
31
31
|
};
|
|
32
32
|
};
|
|
33
33
|
exports.success = success;
|
|
@@ -36,7 +36,7 @@ const failure = (title, error, message, actions) => {
|
|
|
36
36
|
actions,
|
|
37
37
|
message: error && error instanceof Error ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, message, " ", error.message) : message,
|
|
38
38
|
title,
|
|
39
|
-
type:
|
|
39
|
+
type: _Notifications.NotificationSeverity.NEGATIVE
|
|
40
40
|
};
|
|
41
41
|
};
|
|
42
42
|
exports.failure = failure;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
import { ValueOf } from "../../types";
|
|
3
|
-
import { NotificationSeverity } from "../
|
|
3
|
+
import { NotificationSeverity } from "../Notifications";
|
|
4
4
|
export interface NotifyProviderProps {
|
|
5
5
|
state?: {
|
|
6
6
|
queuedNotification: NotificationType | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { ElementType } from "react";
|
|
2
2
|
import type { HTMLProps, ReactNode } from "react";
|
|
3
|
-
import type { ClassName, PropsWithSpread, ValueOf } from "
|
|
3
|
+
import type { ClassName, PropsWithSpread, ValueOf } from "../../../types";
|
|
4
4
|
export declare enum Label {
|
|
5
5
|
Close = "Close notification"
|
|
6
6
|
}
|
|
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = exports.NotificationSeverity = exports.Label = exports.DefaultTitles = void 0;
|
|
7
7
|
var _classnames = _interopRequireDefault(require("classnames"));
|
|
8
8
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
-
var _Button = _interopRequireWildcard(require("
|
|
10
|
-
var _utils = require("
|
|
9
|
+
var _Button = _interopRequireWildcard(require("../../Button"));
|
|
10
|
+
var _utils = require("../../../utils");
|
|
11
11
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
12
12
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
13
13
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FC, PropsWithChildren } from "react";
|
|
2
|
+
interface Props {
|
|
3
|
+
show: boolean;
|
|
4
|
+
from: Keyframe;
|
|
5
|
+
to: Keyframe;
|
|
6
|
+
exitAnimation?: Keyframe[];
|
|
7
|
+
options?: KeyframeAnimationOptions;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
declare const Animate: FC<PropsWithChildren<Props>>;
|
|
11
|
+
export default Animate;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _hooks = require("../../../hooks");
|
|
9
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
10
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
11
|
+
const Animate = _ref => {
|
|
12
|
+
let {
|
|
13
|
+
show,
|
|
14
|
+
children,
|
|
15
|
+
from,
|
|
16
|
+
to,
|
|
17
|
+
exitAnimation,
|
|
18
|
+
options = {
|
|
19
|
+
duration: 500,
|
|
20
|
+
fill: "forwards"
|
|
21
|
+
},
|
|
22
|
+
className
|
|
23
|
+
} = _ref;
|
|
24
|
+
const containerRef = (0, _react.useRef)(null);
|
|
25
|
+
const preferReducedMotion = (0, _hooks.usePrefersReducedMotion)();
|
|
26
|
+
|
|
27
|
+
// This state is used so that we trigger a extra render cycle
|
|
28
|
+
// to animate the child component when it is being unmounted
|
|
29
|
+
const [removeState, setRemove] = (0, _react.useState)(!show);
|
|
30
|
+
(0, _react.useLayoutEffect)(() => {
|
|
31
|
+
const element = containerRef.current;
|
|
32
|
+
if (show) {
|
|
33
|
+
setRemove(false);
|
|
34
|
+
if (!element || preferReducedMotion) return;
|
|
35
|
+
element.animate([from, to], options);
|
|
36
|
+
} else {
|
|
37
|
+
if (!element) return;
|
|
38
|
+
if (preferReducedMotion) {
|
|
39
|
+
setRemove(true);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const animation = element.animate(exitAnimation || [to, from], options);
|
|
43
|
+
animation.onfinish = () => {
|
|
44
|
+
setRemove(true);
|
|
45
|
+
// This is important, else the next render cycle due to setRemove will cause flickering effect
|
|
46
|
+
element.style.display = "none";
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}, [show, removeState]);
|
|
50
|
+
if (removeState) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
54
|
+
ref: containerRef,
|
|
55
|
+
className: className
|
|
56
|
+
}, children);
|
|
57
|
+
};
|
|
58
|
+
var _default = exports.default = Animate;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
@import "vanilla-framework/scss/settings";
|
|
2
|
+
@import "vanilla-framework/scss/build";
|
|
3
|
+
|
|
4
|
+
.toast-animate {
|
|
5
|
+
position: relative;
|
|
6
|
+
z-index: 101;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.toast-notification,
|
|
10
|
+
.toast-notification-list {
|
|
11
|
+
bottom: 3.5rem;
|
|
12
|
+
margin: 0 1.5rem;
|
|
13
|
+
position: absolute;
|
|
14
|
+
right: 0;
|
|
15
|
+
|
|
16
|
+
@media screen and (min-width: $breakpoint-small) and (max-width: $breakpoint-large) {
|
|
17
|
+
width: 500px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@media screen and (min-width: $breakpoint-large) {
|
|
21
|
+
width: 600px;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.toast-notification {
|
|
26
|
+
box-shadow: 0 0 calc($sp-unit * 4) $sp-unit rgb(0 0 0 / 15%);
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
z-index: 101;
|
|
29
|
+
|
|
30
|
+
@media screen and (max-width: $breakpoint-small) {
|
|
31
|
+
left: 0;
|
|
32
|
+
margin: 1.5rem auto;
|
|
33
|
+
max-width: 400px;
|
|
34
|
+
width: 95vw;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.toast-notification-list {
|
|
39
|
+
background-color: white;
|
|
40
|
+
box-shadow: 0 0 calc($sp-unit * 4) $sp-unit rgb(0 0 0 / 22%);
|
|
41
|
+
max-height: calc(100vh - 4.5rem);
|
|
42
|
+
overflow: auto;
|
|
43
|
+
padding: 0 0.5rem;
|
|
44
|
+
z-index: 102;
|
|
45
|
+
|
|
46
|
+
.individual-notification {
|
|
47
|
+
margin: 0.5rem 0;
|
|
48
|
+
overflow: hidden;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.dismiss {
|
|
52
|
+
align-items: center;
|
|
53
|
+
background-color: white;
|
|
54
|
+
bottom: 0;
|
|
55
|
+
display: flex;
|
|
56
|
+
justify-content: space-between;
|
|
57
|
+
padding: 0.5rem 0;
|
|
58
|
+
padding-left: 0.8rem;
|
|
59
|
+
position: sticky;
|
|
60
|
+
z-index: 10;
|
|
61
|
+
|
|
62
|
+
.dismiss-button {
|
|
63
|
+
align-items: center;
|
|
64
|
+
display: flex;
|
|
65
|
+
|
|
66
|
+
.dismiss-text {
|
|
67
|
+
align-items: center;
|
|
68
|
+
display: flex;
|
|
69
|
+
gap: $sph--x-small;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.filters {
|
|
74
|
+
display: flex;
|
|
75
|
+
|
|
76
|
+
.filter-button {
|
|
77
|
+
align-items: center;
|
|
78
|
+
border: none;
|
|
79
|
+
display: flex;
|
|
80
|
+
gap: $sph--x-small;
|
|
81
|
+
justify-content: center;
|
|
82
|
+
margin-right: $sph--small !important;
|
|
83
|
+
padding: calc(0.4rem - 1px);
|
|
84
|
+
|
|
85
|
+
/* stylelint-disable max-nesting-depth */
|
|
86
|
+
/* stylelint-disable-next-line selector-max-type */
|
|
87
|
+
span {
|
|
88
|
+
padding: 0;
|
|
89
|
+
text-align: center;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* stylelint-disable-next-line selector-class-pattern */
|
|
93
|
+
.p-icon--info--notification {
|
|
94
|
+
@extend %icon;
|
|
95
|
+
@include vf-icon-info-coloured-themed;
|
|
96
|
+
}
|
|
97
|
+
/* stylelint-enable max-nesting-depth */
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@media screen and (max-width: $breakpoint-small) {
|
|
102
|
+
align-items: flex-start;
|
|
103
|
+
flex-direction: column;
|
|
104
|
+
gap: 0.5rem;
|
|
105
|
+
margin-bottom: 0.5rem;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@media screen and (max-width: $breakpoint-small) {
|
|
110
|
+
bottom: 2rem;
|
|
111
|
+
left: 0;
|
|
112
|
+
margin: 1.5rem auto;
|
|
113
|
+
max-width: 400px;
|
|
114
|
+
width: 95vw;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ToastNotificationType } from "./ToastNotificationProvider";
|
|
2
|
+
import type { FC } from "react";
|
|
3
|
+
import "./Toast.scss";
|
|
4
|
+
interface Props {
|
|
5
|
+
notification: ToastNotificationType;
|
|
6
|
+
onDismiss: (notification?: ToastNotificationType[]) => void;
|
|
7
|
+
show: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare const ToastNotification: FC<Props>;
|
|
10
|
+
export default ToastNotification;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
8
|
+
var _ = _interopRequireDefault(require("./.."));
|
|
9
|
+
var _Notification = require("../Notification/Notification");
|
|
10
|
+
var _reactDom = require("react-dom");
|
|
11
|
+
var _Animate = _interopRequireDefault(require("./Animate"));
|
|
12
|
+
var _react = _interopRequireDefault(require("react"));
|
|
13
|
+
require("./Toast.scss");
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
const ToastNotification = _ref => {
|
|
16
|
+
var _notification$title;
|
|
17
|
+
let {
|
|
18
|
+
notification,
|
|
19
|
+
onDismiss,
|
|
20
|
+
show
|
|
21
|
+
} = _ref;
|
|
22
|
+
if (!notification) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/_react.default.createElement(_Animate.default, {
|
|
26
|
+
show: show,
|
|
27
|
+
from: {
|
|
28
|
+
opacity: 0
|
|
29
|
+
},
|
|
30
|
+
to: {
|
|
31
|
+
opacity: 1
|
|
32
|
+
},
|
|
33
|
+
exitAnimation: [{
|
|
34
|
+
opacity: 1,
|
|
35
|
+
transform: "translateY(0)"
|
|
36
|
+
}, {
|
|
37
|
+
opacity: 0,
|
|
38
|
+
transform: "translateY(50px)"
|
|
39
|
+
}],
|
|
40
|
+
options: {
|
|
41
|
+
duration: 200
|
|
42
|
+
},
|
|
43
|
+
className: "toast-animate"
|
|
44
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
45
|
+
className: "toast-notification"
|
|
46
|
+
}, /*#__PURE__*/_react.default.createElement(_.default, {
|
|
47
|
+
title: (_notification$title = notification.title) !== null && _notification$title !== void 0 ? _notification$title : _Notification.DefaultTitles[notification.type],
|
|
48
|
+
actions: notification.actions,
|
|
49
|
+
severity: notification.type,
|
|
50
|
+
onDismiss: () => {
|
|
51
|
+
onDismiss([notification]);
|
|
52
|
+
},
|
|
53
|
+
className: "u-no-margin--bottom",
|
|
54
|
+
timestamp: notification.timestamp,
|
|
55
|
+
titleElement: "div",
|
|
56
|
+
role: "alert"
|
|
57
|
+
}, notification.message))), document.body));
|
|
58
|
+
};
|
|
59
|
+
ToastNotification.propTypes = {
|
|
60
|
+
onDismiss: _propTypes.default.func.isRequired,
|
|
61
|
+
show: _propTypes.default.bool.isRequired
|
|
62
|
+
};
|
|
63
|
+
var _default = exports.default = ToastNotification;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { ToastNotificationProvider } from "./index";
|
|
3
|
+
declare const meta: Meta<typeof ToastNotificationProvider>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof ToastNotificationProvider>;
|
|
6
|
+
export declare const Default: Story;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.Default = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _index = require("./index");
|
|
9
|
+
var _Button = _interopRequireDefault(require("../../Button"));
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
12
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
13
|
+
const meta = {
|
|
14
|
+
component: _index.ToastNotificationProvider,
|
|
15
|
+
tags: ["autodocs"]
|
|
16
|
+
};
|
|
17
|
+
var _default = exports.default = meta;
|
|
18
|
+
const Default = exports.Default = {
|
|
19
|
+
name: "Default",
|
|
20
|
+
render: () => /*#__PURE__*/_react.default.createElement(ToastNotificationStoryWrapper, null)
|
|
21
|
+
};
|
|
22
|
+
const ToastNotificationStoryWrapper = () => {
|
|
23
|
+
(0, _react.useEffect)(() => {
|
|
24
|
+
const root = document.getElementById("storybook-root");
|
|
25
|
+
if (root) {
|
|
26
|
+
root.style.height = "90vh";
|
|
27
|
+
}
|
|
28
|
+
}, []);
|
|
29
|
+
return /*#__PURE__*/_react.default.createElement(_index.ToastNotificationProvider, null, /*#__PURE__*/_react.default.createElement(PreloadedList, null));
|
|
30
|
+
};
|
|
31
|
+
const PreloadedList = () => {
|
|
32
|
+
const toastNotify = (0, _index.useToastNotification)();
|
|
33
|
+
(0, _react.useEffect)(() => {
|
|
34
|
+
toastNotify.success("Settings saved successfully");
|
|
35
|
+
toastNotify.info("Your changes are syncing in the background");
|
|
36
|
+
toastNotify.failure("Save failed", new Error("500 Internal Server Error"), "Please try again.");
|
|
37
|
+
toastNotify.toggleListView();
|
|
38
|
+
}, []);
|
|
39
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
40
|
+
style: {
|
|
41
|
+
margin: "2rem auto",
|
|
42
|
+
display: "flex",
|
|
43
|
+
flexDirection: "column",
|
|
44
|
+
flexWrap: "wrap",
|
|
45
|
+
alignContent: "flex-start",
|
|
46
|
+
gap: "0.75rem"
|
|
47
|
+
}
|
|
48
|
+
}, /*#__PURE__*/_react.default.createElement(_Button.default, {
|
|
49
|
+
onClick: () => toastNotify.success("Your changes have been saved.", [{
|
|
50
|
+
label: "Undo",
|
|
51
|
+
onClick: () => console.log("Undo clicked")
|
|
52
|
+
}])
|
|
53
|
+
}, "Add Success"), /*#__PURE__*/_react.default.createElement(_Button.default, {
|
|
54
|
+
onClick: () => toastNotify.info("Your changes are syncing in the background.", "Syncing")
|
|
55
|
+
}, "Add Info"), /*#__PURE__*/_react.default.createElement(_Button.default, {
|
|
56
|
+
onClick: () => toastNotify.failure("Save failed", new Error("500 Internal Server Error"), "Please try again.", [{
|
|
57
|
+
label: "Retry",
|
|
58
|
+
onClick: () => console.log("Retry clicked")
|
|
59
|
+
}])
|
|
60
|
+
}, "Add Error"), /*#__PURE__*/_react.default.createElement(_Button.default, {
|
|
61
|
+
onClick: toastNotify.toggleListView
|
|
62
|
+
}, "Toggle List View"));
|
|
63
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ValueOf } from "../../../types";
|
|
2
|
+
import { GroupedNotificationCount, ToastNotificationType } from "./ToastNotificationProvider";
|
|
3
|
+
import type { FC } from "react";
|
|
4
|
+
import type { NotificationSeverity } from "../../Notifications/Notification";
|
|
5
|
+
import "./Toast.scss";
|
|
6
|
+
export type FilterTypes = ValueOf<typeof NotificationSeverity>;
|
|
7
|
+
export declare const severityOrder: readonly ["positive", "caution", "negative", "information"];
|
|
8
|
+
export declare const iconLookup: {
|
|
9
|
+
readonly positive: "success";
|
|
10
|
+
readonly information: "info--notification";
|
|
11
|
+
readonly caution: "warning";
|
|
12
|
+
readonly negative: "error";
|
|
13
|
+
};
|
|
14
|
+
interface Props {
|
|
15
|
+
notifications: ToastNotificationType[];
|
|
16
|
+
onDismiss: (notification?: ToastNotificationType[]) => void;
|
|
17
|
+
groupedCount: GroupedNotificationCount;
|
|
18
|
+
show: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare const ToastNotificationList: FC<Props>;
|
|
21
|
+
export default ToastNotificationList;
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.severityOrder = exports.iconLookup = exports.default = void 0;
|
|
7
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
8
|
+
var _Button = _interopRequireDefault(require("../../Button"));
|
|
9
|
+
var _Icon = _interopRequireWildcard(require("../../Icon"));
|
|
10
|
+
var _Notification = _interopRequireDefault(require("../Notification"));
|
|
11
|
+
var _Notification2 = require("../Notification/Notification");
|
|
12
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
13
|
+
var _reactDom = require("react-dom");
|
|
14
|
+
var _Animate = _interopRequireDefault(require("./Animate"));
|
|
15
|
+
var _hooks = require("../../../hooks");
|
|
16
|
+
require("./Toast.scss");
|
|
17
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
18
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
19
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
20
|
+
const severityOrder = exports.severityOrder = ["positive", "caution", "negative", "information"];
|
|
21
|
+
const iconLookup = exports.iconLookup = {
|
|
22
|
+
positive: _Icon.ICONS.success,
|
|
23
|
+
// custom name for info icon to override default color from vanilla
|
|
24
|
+
information: "info--notification",
|
|
25
|
+
caution: _Icon.ICONS.warning,
|
|
26
|
+
negative: _Icon.ICONS.error
|
|
27
|
+
};
|
|
28
|
+
const ToastNotificationList = _ref => {
|
|
29
|
+
let {
|
|
30
|
+
notifications,
|
|
31
|
+
onDismiss,
|
|
32
|
+
groupedCount = {},
|
|
33
|
+
show
|
|
34
|
+
} = _ref;
|
|
35
|
+
const [filters, setFilters] = (0, _react.useState)(new Set());
|
|
36
|
+
const prevNotificationsSize = (0, _react.useRef)(notifications.length);
|
|
37
|
+
const containerRef = (0, _react.useRef)(null);
|
|
38
|
+
const hasFilters = !!filters.size;
|
|
39
|
+
const preferReducedMotion = (0, _hooks.usePrefersReducedMotion)();
|
|
40
|
+
(0, _react.useLayoutEffect)(() => {
|
|
41
|
+
adjustScrollPosition();
|
|
42
|
+
}, [notifications]);
|
|
43
|
+
|
|
44
|
+
// this layout effect is used to maintain scroll position of the
|
|
45
|
+
// notification list when new notifications are added to the list
|
|
46
|
+
// for only when the scroll is at the top
|
|
47
|
+
const adjustScrollPosition = () => {
|
|
48
|
+
const notificationsRemoved = notifications.length < prevNotificationsSize.current;
|
|
49
|
+
prevNotificationsSize.current = notifications.length;
|
|
50
|
+
if (!notifications.length || notificationsRemoved) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const container = containerRef.current;
|
|
54
|
+
const lastNotification = notifications[notifications.length - 1];
|
|
55
|
+
const notificationEl = document.getElementById(lastNotification.id);
|
|
56
|
+
if (container && notificationEl) {
|
|
57
|
+
const currentScrollY = container.scrollTop;
|
|
58
|
+
const offsetHeight = notificationEl.getBoundingClientRect().height + parseFloat(window.getComputedStyle(notificationEl).marginTop) + parseFloat(window.getComputedStyle(notificationEl).marginBottom);
|
|
59
|
+
// only adjust the scroll height if the scroll is at the top
|
|
60
|
+
if (currentScrollY === 0) {
|
|
61
|
+
container.scrollTop = currentScrollY + offsetHeight;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const handleFilterSelect = filter => {
|
|
66
|
+
setFilters(prevFilters => {
|
|
67
|
+
const newFilters = new Set(prevFilters);
|
|
68
|
+
if (!newFilters.has(filter)) {
|
|
69
|
+
newFilters.add(filter);
|
|
70
|
+
} else {
|
|
71
|
+
newFilters.delete(filter);
|
|
72
|
+
}
|
|
73
|
+
return newFilters;
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
const handleGroupedDismiss = () => {
|
|
77
|
+
if (hasFilters) {
|
|
78
|
+
const notificationsToClear = notifications.filter(notification => filters.has(notification.type));
|
|
79
|
+
onDismiss(notificationsToClear);
|
|
80
|
+
setFilters(new Set());
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
onDismiss();
|
|
84
|
+
};
|
|
85
|
+
const getSeverityFilters = () => {
|
|
86
|
+
const filterButtons = severityOrder.map(severity => {
|
|
87
|
+
if (groupedCount[severity]) {
|
|
88
|
+
return /*#__PURE__*/_react.default.createElement("button", {
|
|
89
|
+
"aria-label": "Filter ".concat(severity, " notifications"),
|
|
90
|
+
"aria-pressed": filters.has(severity),
|
|
91
|
+
key: severity,
|
|
92
|
+
className: "u-no-margin u-no-border filter-button",
|
|
93
|
+
onClick: () => {
|
|
94
|
+
handleFilterSelect(severity);
|
|
95
|
+
}
|
|
96
|
+
}, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
97
|
+
name: iconLookup[severity]
|
|
98
|
+
}), /*#__PURE__*/_react.default.createElement("span", null, groupedCount[severity]));
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
101
|
+
});
|
|
102
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
103
|
+
className: "filters"
|
|
104
|
+
}, filterButtons, hasFilters && /*#__PURE__*/_react.default.createElement("button", {
|
|
105
|
+
className: "u-no-margin--bottom u-no-border",
|
|
106
|
+
onClick: () => {
|
|
107
|
+
setFilters(new Set());
|
|
108
|
+
}
|
|
109
|
+
}, "Clear filters"));
|
|
110
|
+
};
|
|
111
|
+
const getDismissText = () => {
|
|
112
|
+
if (hasFilters) {
|
|
113
|
+
const validFilters = Object.keys(groupedCount);
|
|
114
|
+
let totalCount = 0;
|
|
115
|
+
for (const filter of validFilters) {
|
|
116
|
+
if (filters.has(filter)) {
|
|
117
|
+
totalCount += groupedCount[filter] || 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const dismissText = /*#__PURE__*/_react.default.createElement("span", {
|
|
121
|
+
className: "dismiss-text"
|
|
122
|
+
}, "Dismiss ", totalCount);
|
|
123
|
+
return dismissText;
|
|
124
|
+
}
|
|
125
|
+
return /*#__PURE__*/_react.default.createElement("span", null, "Dismiss all");
|
|
126
|
+
};
|
|
127
|
+
const handleDismissNotification = notification => {
|
|
128
|
+
if (preferReducedMotion) {
|
|
129
|
+
onDismiss([notification]);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// animate the notification dismissal before updating states to delay unmounting
|
|
134
|
+
const element = document.getElementById("li-".concat(notification.id));
|
|
135
|
+
if (element) {
|
|
136
|
+
element.style.transformOrigin = "center";
|
|
137
|
+
element.style.overflow = "hidden";
|
|
138
|
+
const animation = element.animate([{
|
|
139
|
+
height: "".concat(element.scrollHeight, "px"),
|
|
140
|
+
opacity: 1
|
|
141
|
+
}, {
|
|
142
|
+
height: "0px",
|
|
143
|
+
opacity: 0
|
|
144
|
+
}], {
|
|
145
|
+
duration: 200,
|
|
146
|
+
easing: "linear",
|
|
147
|
+
fill: "forwards"
|
|
148
|
+
});
|
|
149
|
+
animation.onfinish = () => {
|
|
150
|
+
element.style.display = "none";
|
|
151
|
+
onDismiss([notification]);
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// Only filter input data if there are filters present
|
|
157
|
+
const filteredNotifications = hasFilters ? notifications.filter(notification => filters.has(notification.type)) : notifications;
|
|
158
|
+
|
|
159
|
+
// Don't assign alert role for notifications when expanded since we don't want
|
|
160
|
+
// screen readers to announce every existing notification
|
|
161
|
+
const notificationEls = filteredNotifications.map((_, index, array) => {
|
|
162
|
+
var _notification$title;
|
|
163
|
+
const lastNotificationIndex = array.length - 1;
|
|
164
|
+
// This will map notifications in reverse order
|
|
165
|
+
const notification = array[lastNotificationIndex - index];
|
|
166
|
+
return /*#__PURE__*/_react.default.createElement("li", {
|
|
167
|
+
key: notification.id,
|
|
168
|
+
id: "li-".concat(notification.id)
|
|
169
|
+
}, /*#__PURE__*/_react.default.createElement(_Notification.default, {
|
|
170
|
+
id: notification.id,
|
|
171
|
+
title: (_notification$title = notification.title) !== null && _notification$title !== void 0 ? _notification$title : _Notification2.DefaultTitles[notification.type],
|
|
172
|
+
actions: notification.actions,
|
|
173
|
+
severity: notification.type,
|
|
174
|
+
onDismiss: () => {
|
|
175
|
+
handleDismissNotification(notification);
|
|
176
|
+
},
|
|
177
|
+
className: "u-no-margin--bottom individual-notification",
|
|
178
|
+
timestamp: notification.timestamp,
|
|
179
|
+
titleElement: "div"
|
|
180
|
+
}, notification.message));
|
|
181
|
+
});
|
|
182
|
+
return /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/_react.default.createElement(_Animate.default, {
|
|
183
|
+
show: show,
|
|
184
|
+
from: {
|
|
185
|
+
opacity: 0,
|
|
186
|
+
transform: "translateY(5vh)"
|
|
187
|
+
},
|
|
188
|
+
to: {
|
|
189
|
+
opacity: 1,
|
|
190
|
+
transform: "translateY(0)"
|
|
191
|
+
},
|
|
192
|
+
options: {
|
|
193
|
+
duration: 100
|
|
194
|
+
},
|
|
195
|
+
className: "toast-animate"
|
|
196
|
+
}, /*#__PURE__*/_react.default.createElement("ul", {
|
|
197
|
+
className: "toast-notification-list",
|
|
198
|
+
"aria-label": "Notifications list",
|
|
199
|
+
ref: containerRef
|
|
200
|
+
}, notificationEls, /*#__PURE__*/_react.default.createElement("li", {
|
|
201
|
+
className: "dismiss"
|
|
202
|
+
}, getSeverityFilters(), /*#__PURE__*/_react.default.createElement(_Button.default, {
|
|
203
|
+
className: "u-no-margin--bottom dismiss-button",
|
|
204
|
+
onClick: handleGroupedDismiss,
|
|
205
|
+
hasIcon: true
|
|
206
|
+
}, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
207
|
+
name: "tidy"
|
|
208
|
+
}), getDismissText())))), document.body);
|
|
209
|
+
};
|
|
210
|
+
ToastNotificationList.propTypes = {
|
|
211
|
+
notifications: _propTypes.default.array.isRequired,
|
|
212
|
+
onDismiss: _propTypes.default.func.isRequired,
|
|
213
|
+
show: _propTypes.default.bool.isRequired
|
|
214
|
+
};
|
|
215
|
+
var _default = exports.default = ToastNotificationList;
|