UNPKG

@datalayer/core

Version:

[![Datalayer](https://assets.datalayer.tech/datalayer-25.svg)](https://datalayer.io)

144 lines (143 loc) 5.72 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; /* * Copyright (c) 2023-2025 Datalayer, Inc. * Distributed under the terms of the Modified BSD License. */ import React from 'react'; import { toast } from 'react-toastify'; import { Notification } from '@jupyterlab/apputils'; import { Button } from '@primer/react'; import { JupyterReactTheme } from '@datalayer/jupyter-react'; import { isInsideJupyterLab } from '../utils'; const TOAST_POSITION = 'bottom-right'; const displayType2Class = { accent: 'primary', link: 'invisible', warn: 'danger', default: 'default', }; /** * Create a button with customized callback in a toast */ function ToastButton({ action, closeToast }) { const clickHandler = (event) => { action.callback(event); if (!event.defaultPrevented) { closeToast(); } }; return (_jsx(Button, { title: action.caption ?? action.label, onClick: clickHandler, variant: displayType2Class[action.displayType ?? 'default'], size: "small", children: action.label })); } /** * Helper function to construct the notification content * * @param message Message to print in the notification * @param closeHandler Function closing the notification * @param actions Toast actions */ function createContent(message, closeHandler, actions) { return (_jsxs(_Fragment, { children: [_jsx("div", { className: "jp-toast-message", children: message.split('\n').map((part, index) => (_jsxs(React.Fragment, { children: [index > 0 ? _jsx("br", {}) : null, part] }, `part-${index}`))) }), (actions?.length ?? 0) > 0 && (_jsxs("div", { className: "jp-toast-buttonBar", children: [_jsx("div", { className: "jp-toast-spacer" }), actions.map((action, idx) => { return (_jsx(JupyterReactTheme, { children: _jsx(ToastButton, { action: action, closeToast: closeHandler }, 'button-' + idx) })); })] }))] })); } export const useToast = () => { // This CANNOT use Jupyter React hooks as it may be used outside Jupyter React context. const insideJupyterLab = isInsideJupyterLab(); const enqueueToast = (message, options = { variant: 'info' }) => { const { actions, autoClose } = options; switch (options.variant) { case 'info': { return insideJupyterLab ? Notification.info(message, { autoClose: autoClose ?? 5000, actions, }) : toast.info(({ closeToast }) => createContent(message, () => { if (closeToast) closeToast(); }, actions), { autoClose, position: TOAST_POSITION }); } case 'success': { return insideJupyterLab ? Notification.success(message, { autoClose: autoClose ?? 5000, actions, }) : toast.success(({ closeToast }) => createContent(message, () => { if (closeToast) closeToast(); }, actions), { autoClose, position: TOAST_POSITION }); } case 'warning': { return insideJupyterLab ? Notification.warning(message, { autoClose: autoClose ?? false, actions, }) : toast.warning(({ closeToast }) => createContent(message, () => { if (closeToast) closeToast(); }, actions), { autoClose: autoClose ?? false, position: TOAST_POSITION }); } case 'error': { return insideJupyterLab ? Notification.error(message, { autoClose: autoClose ?? false, actions, }) : toast.error(({ closeToast }) => createContent(message, () => { if (closeToast) closeToast(); }, actions), { autoClose: autoClose ?? false, position: TOAST_POSITION }); } } }; const trackAsyncTask = (promise, options) => { return insideJupyterLab ? Notification.promise(promise, options) : toast.promise(promise, { error: { render: options.error.message, ...options.error.options }, pending: options.pending.message, success: { render: options.success.message, ...options.success.options, }, }, { position: TOAST_POSITION, ...options.pending.options, }); }; return Object.freeze({ /** * Emit a message as a toast. * * @param message Toast message * @param options Toast option * @returns Toast id */ enqueueToast, /** * Dismiss a toast * * @param id Toast id */ dismiss: (id) => { if (insideJupyterLab) { Notification.dismiss(id); } else { toast.dismiss(id); } }, /** * Track the progress of an asynchronous task * and display a message depending on the outcome. * * @param promise Asynchronous task * @param options Task progress options * @returns Toast id */ trackAsyncTask, }); }; export default useToast;