@magicbell/magicbell-react
Version:
React components for building a notification inbox for your app
77 lines • 4.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = ClickableNotification;
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
/** @jsxImportSource @emotion/react */
const react_1 = require("@emotion/react");
const react_headless_1 = require("@magicbell/react-headless");
const MagicBellThemeContext_js_1 = require("../../context/MagicBellThemeContext.js");
const index_js_1 = tslib_1.__importDefault(require("../NotificationContent/index.js"));
const index_js_2 = tslib_1.__importDefault(require("../NotificationMenu/index.js"));
const index_js_3 = tslib_1.__importDefault(require("../NotificationState/index.js"));
const index_js_4 = tslib_1.__importDefault(require("../Timestamp/index.js"));
const eventHandlers_js_1 = require("./eventHandlers.js");
const NotificationTitle_js_1 = tslib_1.__importDefault(require("./NotificationTitle.js"));
const StyledContainer_js_1 = tslib_1.__importDefault(require("./StyledContainer.js"));
const actionableTags = new Set(['A', 'BUTTON', 'INPUT', 'TEXTAREA', 'SELECT']);
function isActionableElement(event) {
let el = event.target;
while (el && el !== event.currentTarget) {
if (actionableTags.has(el.tagName.toUpperCase())) {
const isMenu = el.dataset.magicbellTarget === 'notification-menu';
return [true, isMenu];
}
el = el.parentElement;
}
return [false, false];
}
/**
* Component that renders a notification. When the notification is clicked the
* `onClick` callback is called and the notification is marked as read.
*
* @example
* <ClickableNotification notification={notification} onClick={openActionUrl} />
*/
function ClickableNotification({ notification: rawNotification, onClick, prose }) {
const { notification: { default: theme }, } = (0, MagicBellThemeContext_js_1.useTheme)();
const notification = (0, react_headless_1.useNotification)(rawNotification);
const handleClick = (event) => {
// ignore event when user clicks inside the menu
if (event.isDefaultPrevented())
return;
const [isAction, isMenu] = isActionableElement(event);
let markAsReadPromise;
// don't mark as read when the user clicks the menu
if (!isMenu) {
markAsReadPromise = notification.markAsRead();
}
// We don't want to invoke the action url when the user clicks a link or button inside the notification.
// Notification content should take precedence.
if (isAction)
return;
const onClickResult = onClick?.(notification);
if (onClickResult === false)
return;
if (notification.actionUrl) {
// We wait for the markAsRead before navigating to the new url, to prevent race conditions
// between mark and read, and fetching new data on page reload. But let's not wait forever.
const timeout = new Promise((resolve) => setTimeout(resolve, 1_000));
Promise.race([markAsReadPromise, timeout]).then(() => (0, eventHandlers_js_1.openActionUrl)(notification));
}
};
const content = (0, react_1.css) `
margin: 0 8px !important;
width: 100%;
`;
const actions = (0, react_1.css) `
display: flex;
padding: 0 5px !important;
flex-direction: column;
align-items: flex-end;
margin-left: auto !important;
font-size: ${theme.fontSize} !important;
`;
return ((0, jsx_runtime_1.jsxs)(StyledContainer_js_1.default, { role: "button", "aria-labelledby": `magicbell-notification-title-${notification.id}`, notification: notification, onClick: handleClick, children: [(0, jsx_runtime_1.jsx)(index_js_3.default, { notification: notification }), (0, jsx_runtime_1.jsxs)("div", { css: content, children: [(0, jsx_runtime_1.jsx)(NotificationTitle_js_1.default, { notification: notification }), (0, jsx_runtime_1.jsx)(index_js_1.default, { notification: notification, prose: prose })] }), (0, jsx_runtime_1.jsxs)("div", { css: actions, children: [notification.sentAt ? (0, jsx_runtime_1.jsx)(index_js_4.default, { date: notification.sentAt, tooltipPlacement: "left" }) : (0, jsx_runtime_1.jsx)("div", {}), (0, jsx_runtime_1.jsx)(index_js_2.default, { notification: notification })] })] }));
}
//# sourceMappingURL=ClickableNotification.js.map