All files Notification.tsx

100% Statements 42/42
80% Branches 16/20
100% Functions 11/11
100% Lines 42/42
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117                                  3x           9x 9x                             9x 9x 8x 8x 5x   5x 15x       9x             9x 35x 25x 25x 25x 25x     10x       9x 9x 1x 1x 1x     9x 9x 9x   9x 9x 9x     9x 9x 1x     9x 9x 9x 9x     9x   3x               9x 1x   8x         8x    
import { defaultOptions } from './DialogOptions';
 
/** The options for [[Notification]] */
export interface NotificationOptions {
    autoClose?: boolean;
    clickClose?: boolean;
    closeDelay?: number;
    theme?: string;
    placement?: string;
    maxItems?: number;
    square?: boolean;
    message: string;
}
 
/**
 * The notification component for popping up notifications.
 */
export class Notification {
    private static refContainer: HTMLElement;
 
    private ref?: HTMLElement;
    private finalOptions: NotificationOptions;
 
    constructor(options: NotificationOptions) {
        this.finalOptions = {
            autoClose: defaultOptions.notificationAutoClose,
            clickClose: defaultOptions.notificationClickClose,
            closeDelay: defaultOptions.notificationCloseDelay,
            theme: defaultOptions.notificationTheme,
            placement: defaultOptions.notificationPlacement,
            maxItems: defaultOptions.notificationMaxItems,
            square: defaultOptions.notificationSquare,
            ...options,
        };
    }
 
    /**
     * Shows a notification
     */
    public show = () => {
        if (Notification.refContainer) {
            const itemCount  = Notification.refContainer.querySelectorAll(".notification-item").length;
            if ( itemCount>= this.finalOptions.maxItems!) {
                const needRemovedItems = Array.from(Notification.refContainer.querySelectorAll(".notification-item"))
                    .slice(0, itemCount - this.finalOptions.maxItems! + 1) as HTMLElement[];
                needRemovedItems.forEach((item: HTMLElement) => {
                    this.close(item);
                });
            }
        }
        return this.renderItem(this.finalOptions.message);
    }
 
    /**
     * Closes the notification
     * @param item The notification item typed [[HTMLElement]]
     */
    public close = (item?: HTMLElement) => {
        if (item) {
            const css = item.getAttribute("class")!.replace("notification-item-show", "notification-item-hidden");
            item.setAttribute("class", `${css}`);
            setTimeout(() => {
                item.remove();
            }, 500);
        } else {
            this.close(this.ref);
        }
    }
 
    private renderItem = (message: string) => {
        if (!Notification.refContainer) {
            Notification.refContainer = document.createElement("div");
            Notification.refContainer.setAttribute("class", `bn-notification-container ${this.finalOptions.placement} ${this.finalOptions.square ? "square" : ""}`);
            document.body.appendChild(Notification.refContainer);
        }
 
        this.ref = document.createElement("div");
        this.ref.setAttribute("class", `notification-item ${this.finalOptions.theme}`);
        this.ref.innerHTML = message;
 
        Eif (this.finalOptions.autoClose) {
            setTimeout(() => {
                this.close();
            }, this.finalOptions.closeDelay);
        }
        Eif (this.finalOptions.clickClose) {
            this.ref.addEventListener("click", (ev: MouseEvent) => {
                this.close();
            });
        }
        Notification.refContainer.appendChild(this.ref);
        setTimeout(() => {
            Eif (this.ref) {
                this.ref.setAttribute("class", `${this.ref.getAttribute("class")} notification-item-show`);
            }
        }, 100);
        return this.ref;
    }
}
 
/**
 * Shows a notification with options.
 * @param messageOrOptions The notification message or [[NotificationOptions]]
 * @param theme The notification theme, can be `success`, `warning`, `error` and `default`
 */
export function notify(messageOrOptions: string | NotificationOptions, theme?: string) {
    if (typeof messageOrOptions === "object") {
        new Notification(messageOrOptions).show();
    } else {
        const notification = new Notification({
            theme: theme || "default",
            autoClose: true,
            message: messageOrOptions,
        });
        notification.show();
    }
}