UNPKG

@magicbell/magicbell-react

Version:

React components for building a notification inbox for your app

77 lines 4.36 kB
"use strict"; 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