tethys.backend/resources/js/utils/toast.ts

227 lines
6.4 KiB
TypeScript
Raw Normal View History

import Toastify from 'toastify-js';
// import { t } from './utils/l10n.js';
import './toast.css';
/**
* Enum of available Toast types
*/
export enum ToastType {
ERROR = 'toast-error',
WARNING = 'toast-warning',
INFO = 'toast-info',
SUCCESS = 'toast-success',
PERMANENT = 'toast-error',
UNDO = 'toast-undo',
}
/** @deprecated Use ToastAriaLive.OFF */
export const TOAST_ARIA_LIVE_OFF = 'off';
/** @deprecated Use ToastAriaLive.POLITE */
export const TOAST_ARIA_LIVE_POLITE = 'polite';
/** @deprecated Use ToastAriaLive.ASSERTIVE */
export const TOAST_ARIA_LIVE_ASSERTIVE = 'assertive';
export enum ToastAriaLive {
OFF = TOAST_ARIA_LIVE_OFF,
POLITE = TOAST_ARIA_LIVE_POLITE,
ASSERTIVE = TOAST_ARIA_LIVE_ASSERTIVE,
}
/** Timeout in ms of a undo toast */
export const TOAST_UNDO_TIMEOUT = 10000;
/** Default timeout in ms of toasts */
export const TOAST_DEFAULT_TIMEOUT = 4000;
/** Timeout value to show a toast permanently */
export const TOAST_PERMANENT_TIMEOUT = -1;
/**
* Type of a toast
* @see https://apvarun.github.io/toastify-js/
* @notExported
*/
type Toast = ReturnType<typeof Toastify>;
export interface ToastOptions {
/**
* Defines the timeout in milliseconds after which the toast is closed. Set to -1 to have a persistent toast.
*/
timeout?: number;
/**
* Set to true to allow HTML content inside of the toast text
* @default false
*/
isHTML?: boolean;
/**
* Set a type of {ToastType} to style the modal
*/
type?: ToastType;
/**
* Provide a function that is called after the toast is removed
*/
onRemove?: () => void;
/**
* Provide a function that is called when the toast is clicked
*/
onClick?: () => void;
/**
* Make the toast closable
*/
close?: boolean;
/**
* Specify the element to attach the toast element to (for testing)
*/
selector?: string;
/**
* Whether the messages should be announced to screen readers.
* See the following docs for an explanation when to use which:
* https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions
*
* By default, errors are announced assertive and other messages "polite".
*/
ariaLive?: ToastAriaLive;
}
/**
* Show a toast message
*
* @param data Message to be shown in the toast, any HTML is removed by default
* @param options
*/
export function showMessage(data: string | Node, options?: ToastOptions): Toast {
options = Object.assign(
{
timeout: TOAST_DEFAULT_TIMEOUT,
isHTML: false,
type: undefined,
// An undefined selector defaults to the body element
selector: undefined,
onRemove: () => {},
onClick: undefined,
close: true,
},
options,
);
if (typeof data === 'string' && !options.isHTML) {
// fime mae sure that text is extracted
const element = document.createElement('div');
element.innerHTML = data;
data = element.innerText;
}
let classes = options.type ?? '';
if (typeof options.onClick === 'function') {
classes += ' toast-with-click ';
}
const isNode = data instanceof Node;
let ariaLive: ToastAriaLive = ToastAriaLive.POLITE;
if (options.ariaLive) {
ariaLive = options.ariaLive;
} else if (options.type === ToastType.ERROR || options.type === ToastType.UNDO) {
ariaLive = ToastAriaLive.ASSERTIVE;
}
const toast = Toastify({
[!isNode ? 'text' : 'node']: data,
duration: options.timeout,
callback: options.onRemove,
onClick: options.onClick,
close: options.close,
gravity: 'top',
selector: options.selector,
position: 'right',
backgroundColor: '',
className: 'dialogs ' + classes,
escapeMarkup: !options.isHTML,
ariaLive,
});
toast.showToast();
return toast;
}
/**
* Show a toast message with error styling
*
* @param text Message to be shown in the toast, any HTML is removed by default
* @param options
*/
export function showError(text: string, options?: ToastOptions): Toast {
return showMessage(text, { ...options, type: ToastType.ERROR })
}
export default {
updatableNotification: null,
getDefaultNotificationFunction: null,
/**
* Shows a notification that disappears after x seconds, default is
* 7 seconds
*
* @param {string} text Message to show
* @param {Array} [options] options array
* @param {number} [options.timeout=7] timeout in seconds, if this is 0 it will show the message permanently
* @param {boolean} [options.isHTML=false] an indicator for HTML notifications (true) or text (false)
* @param {string} [options.type] notification type
* @return {JQuery} the toast element
*/
showTemporary(text, options = { timeout: 3000 }) {
options = options || {};
options.timeout = options.timeout || TOAST_DEFAULT_TIMEOUT;
const toast = showMessage(text, options);
toast.toastElement.toastify = toast;
// return $(toast.toastElement)
},
/**
* Show a toast message with error styling
*
* @param text Message to be shown in the toast, any HTML is removed by default
* @param options
*/
showError(text: string, options?: ToastOptions): Toast {
return showMessage(text, { ...options, type: ToastType.ERROR });
},
/**
* Show a toast message with warning styling
*
* @param text Message to be shown in the toast, any HTML is removed by default
* @param options
*/
showWarning(text: string, options?: ToastOptions): Toast {
return showMessage(text, { ...options, type: ToastType.WARNING });
},
/**
* Show a toast message with info styling
*
* @param text Message to be shown in the toast, any HTML is removed by default
* @param options
*/
showInfo(text: string, options?: ToastOptions): Toast {
return showMessage(text, { ...options, type: ToastType.INFO });
},
/**
* Show a toast message with success styling
*
* @param text Message to be shown in the toast, any HTML is removed by default
* @param options
*/
showSuccess(text: string, options?: ToastOptions): Toast {
return showMessage(text, { ...options, type: ToastType.SUCCESS });
},
};