From 0cedd728195f50a8458180b4c6a226299d263de0 Mon Sep 17 00:00:00 2001
From: Brad Martin <bradwaynemartin@gmail.com>
Date: Thu, 23 Mar 2017 11:29:09 -0500
Subject: [PATCH] restructure TS

---
 README.md        |  19 ++++-
 dist/index.d.ts  |  31 --------
 dist/mystical.js |   2 +-
 package.json     |   4 +-
 src/index.d.ts   |  31 --------
 src/index.ts     | 201 +++++++++++++++++++++++------------------------
 6 files changed, 117 insertions(+), 171 deletions(-)

diff --git a/README.md b/README.md
index dfa0507..1a50d7c 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,8 @@
 [![npm](https://img.shields.io/npm/v/mystical-notification.svg)](https://www.npmjs.com/package/mystical-notification)
 [![npm](https://img.shields.io/npm/dt/mystical-notification.svg?label=npm%20downloads)](https://www.npmjs.com/package/mystical-notification)
 # Mystical-Notification
-#### Just some notification crap I needed for a web app. Could use some TLC.
+## What is it?
+ Fully customizable alert notifications. Current types are *alert* and *confirm*. Two positions for now are *top* and *bottom*.
 
 
 
@@ -31,17 +32,27 @@ mystical.Mystical.alert({
 ```
 
 ### Public Methods
-- `alert(options: MysticalOptions)` - show simple notification
+- `alert(options: AlertOptions)` - shows simple alert notification
+- `confirm(options: ConfirmOptions)` - shows a confirmation notification
 
 
-### MysticalOptions 
+### Options Interfaces 
 ```ts
-interface MysticalOptions {
+interface AlertOptions {
     template: string;
     backgroundColor?: string;
     color?: string;
     position?: string; // top or bottom for now
 }
+
+interface ConfirmOptions {
+    template: string;
+    backgroundColor?: string;
+    color?: string;
+    position?: string;
+    positiveText?: string;
+    negativeText?: string;
+}
 ```
 ### Contributing
 - `git clone https://github.com/bradmartin/mystical-notification.git`
diff --git a/dist/index.d.ts b/dist/index.d.ts
index 0a0e393..37ac845 100644
--- a/dist/index.d.ts
+++ b/dist/index.d.ts
@@ -1,9 +1,4 @@
 export declare class Mystical {
-    private static bgColor;
-    private static fgColor;
-    private static position;
-    private static positiveText;
-    private static negativeText;
     /**
      * Creates a simple notification
      * @param opts [MysticalOptions] - The mystical notifications options.
@@ -14,32 +9,6 @@ export declare class Mystical {
      * @param opts [ConfirmOptions]
      */
     static confirm(opts: ConfirmOptions): Promise<boolean>;
-    private static startTransition(defaults, note, top, bottom);
-    private static setInitStyles(defaults, note);
-    /**
-     * Starts the CSS transition and then removes from DOM
-     * @param id - note to remove
-     * @param position - note position
-     */
-    private static removeNoteFromDom(id, position);
-    /**
-     * Helper for setTimeout with 0
-     */
-    private static tick();
-    /**
-     * Helper for setTimeout with passed duration
-     * @param time [number] - milliseconds to wait
-     */
-    private static wait(time);
-    /**
-     * Returns an object with the options object settings - since several args are optional
-     * @param opts
-     */
-    private static createDefaultOpts(opts);
-    /**
-     * Generate random ID
-     */
-    private static generateRandomId();
 }
 export interface AlertOptions {
     template: string;
diff --git a/dist/mystical.js b/dist/mystical.js
index 216167b..a22f8a1 100644
--- a/dist/mystical.js
+++ b/dist/mystical.js
@@ -1 +1 @@
-!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.mystical=e():t.mystical=e()}(this,function(){return function(t){function e(n){if(o[n])return o[n].exports;var i=o[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var o={};return e.m=t,e.c=o,e.i=function(t){return t},e.d=function(t,o,n){e.o(t,o)||Object.defineProperty(t,o,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var o=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(o,"a",o),o},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=0)}([function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(){}return t.alert=function(t){var e=this,o=this.createDefaultOpts(t),n=document.createElement("div");n.id=this.generateRandomId(),n.tabIndex=-1,n.style.cssText="background-color: "+o.bg+"; border: none; user-select: none; -webkit-tap-highlight-color: rgba(255, 255, 255, 0); outline: none; cursor: pointer; color: "+o.fg+"; position: fixed; left: 0; padding: 10px; width: 100%; transition: all 0.5s ease; margin: 0 auto; overflow-x: hidden;",n.onclick=function(){e.removeNoteFromDom(n.id,o.pos)},n.onkeydown=function(t){13!==t.keyCode&&27!==t.keyCode||e.removeNoteFromDom(n.id,o.pos)},n.innerHTML='\n                <div style="position: relative">\n                    '+t.template+"\n                </div>\n        ";var i=this.setInitStyles(o,n);document.body.appendChild(n),n.focus(),this.startTransition(o,n,i.top,i.bottom)},t.confirm=function(t){var e=this;return new Promise(function(o,n){var i=e.createDefaultOpts(t),r=document.createElement("div");r.id=e.generateRandomId(),r.tabIndex=-1,r.style.cssText="background-color: "+i.bg+"; border: none; user-select: none; -webkit-tap-highlight-color: rgba(255, 255, 255, 0); outline: none; color: "+i.fg+"; position: fixed; left: 0; padding: 10px; width: 100%; transition: all 0.5s ease; margin: 0 auto; overflow-x: hidden;",r.onkeydown=function(t){13!==t.keyCode&&27!==t.keyCode||(e.removeNoteFromDom(r.id,i.pos),o(!1))};var s=e.generateRandomId(),c=e.generateRandomId(),a="color: "+i.fg+"; background-color: "+i.bg+"; cursor: pointer; border: none; background: transparent; outline: none; margin-right: 10px; font-size: 1.1em";r.innerHTML='\n                <div style="position: relative">\n                    '+t.template+'\n                    <div style="display:inline-block; text-align: center; margin: auto; width: 100%">\n                        <button id="'+s+'" style="'+a+'">'+i.posText+'</button>\n                        <button id="'+c+'"  style="'+a+'">'+i.negText+"</button>\n                    </div>\n                </div>\n        ";var u=e.setInitStyles(i,r);document.body.appendChild(r),r.focus(),document.getElementById(s).onclick=function(){o(!0),e.removeNoteFromDom(r.id,i.pos)},document.getElementById(c).onclick=function(){o(!1),e.removeNoteFromDom(r.id,i.pos)},e.startTransition(i,r,u.top,u.bottom)})},t.startTransition=function(t,e,o,n){"top"===t.pos?this.tick().then(function(){e.style.top=o,e.style.opacity="1"}):this.tick().then(function(){e.style.bottom=n,e.style.opacity="1"})},t.setInitStyles=function(t,e){var o,n;return"top"===t.pos?(o="0px",n="",e.style.top="-200px"):(o="",n="0%",e.style.bottom="-200px"),{top:o,bottom:n}},t.removeNoteFromDom=function(t,e){var o=document.getElementById(t);"top"===e?o.style.top="-150px":o.style.bottom="-150px",this.wait(500).then(function(){o&&document.body.removeChild(o)})},t.tick=function(){return new Promise(function(t){setTimeout(t,0)})},t.wait=function(t){return new Promise(function(e){setTimeout(e,t)})},t.createDefaultOpts=function(t){return{bg:t.backgroundColor?t.backgroundColor:this.bgColor,fg:t.color?t.color:this.fgColor,pos:t.position?t.position:this.position,posText:t.positiveText?t.positiveText:this.positiveText,negText:t.negativeText?t.negativeText:this.negativeText}},t.generateRandomId=function(){return"mystical-"+(Math.floor(9e4*Math.random())+1e4)},t}();n.bgColor="#333",n.fgColor="#fff",n.position="top",n.positiveText="Yes",n.negativeText="No",e.Mystical=n}])});
\ No newline at end of file
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.mystical=e():t.mystical=e()}(this,function(){return function(t){function e(n){if(o[n])return o[n].exports;var i=o[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var o={};return e.m=t,e.c=o,e.i=function(t){return t},e.d=function(t,o,n){e.o(t,o)||Object.defineProperty(t,o,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var o=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(o,"a",o),o},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=0)}([function(t,e,o){"use strict";function n(t,e,o,n){"top"===t.pos?c().then(function(){e.style.top=o,e.style.opacity="1"}):c().then(function(){e.style.bottom=n,e.style.opacity="1"})}function i(t,e){var o,n;return"top"===t.pos?(o="0px",n="",e.style.top="-200px"):(o="",n="0%",e.style.bottom="-200px"),{top:o,bottom:n}}function r(t,e){var o=document.getElementById(t);"top"===e?o.style.top="-150px":o.style.bottom="-150px",u(500).then(function(){o&&document.body.removeChild(o)})}function c(){return new Promise(function(t){setTimeout(t,0)})}function u(t){return new Promise(function(e){setTimeout(e,t)})}function d(t){return{bg:t.backgroundColor?t.backgroundColor:"#333",fg:t.color?t.color:"#fff",pos:t.position?t.position:"top",posText:t.positiveText?t.positiveText:"Yes",negText:t.negativeText?t.negativeText:"No"}}function l(){return"mystical-"+(Math.floor(9e4*Math.random())+1e4)}Object.defineProperty(e,"__esModule",{value:!0});var s=function(){function t(){}return t.alert=function(t){var e=d(t),o=document.createElement("div");o.id=l(),o.tabIndex=-1,o.style.cssText="background-color: "+e.bg+"; z-index: 99999999; border: none; user-select: none; -webkit-tap-highlight-color: rgba(255, 255, 255, 0); outline: none; cursor: pointer; color: "+e.fg+"; position: fixed; left: 0; padding: 10px; width: 100%; transition: all 0.5s ease; margin: 0 auto; overflow-x: hidden;",o.onclick=function(){r(o.id,e.pos)},o.onkeydown=function(t){13!==t.keyCode&&27!==t.keyCode||r(o.id,e.pos)},o.innerHTML='\n                <div style="position: relative">\n                    '+t.template+"\n                </div>\n        ";var c=i(e,o);document.body.appendChild(o),o.focus(),n(e,o,c.top,c.bottom)},t.confirm=function(t){return new Promise(function(e,o){var c=d(t),u=document.createElement("div");u.id=l(),u.tabIndex=-1,u.style.cssText="background-color: "+c.bg+"; z-index: 99999999; border: none; user-select: none; -webkit-tap-highlight-color: rgba(255, 255, 255, 0); outline: none; color: "+c.fg+"; position: fixed; left: 0; padding: 10px; width: 100%; transition: all 0.5s ease; margin: 0 auto; overflow-x: hidden;",u.onkeydown=function(t){13!==t.keyCode&&27!==t.keyCode||(r(u.id,c.pos),e(!1))};var s=l(),a=l(),p="color: "+c.fg+"; background-color: "+c.bg+"; cursor: pointer; border: none; background: transparent; outline: none; margin-right: 10px; font-size: 1.1em";u.innerHTML='\n                <div style="position: relative">\n                    '+t.template+'\n                    <div style="display:inline-block; text-align: center; margin: auto; width: 100%">\n                        <button id="'+s+'" style="'+p+'">'+c.posText+'</button>\n                        <button id="'+a+'"  style="'+p+'">'+c.negText+"</button>\n                    </div>\n                </div>\n        ";var f=i(c,u);document.body.appendChild(u),u.focus(),document.getElementById(s).onclick=function(){e(!0),r(u.id,c.pos)},document.getElementById(a).onclick=function(){e(!1),r(u.id,c.pos)},n(c,u,f.top,f.bottom)})},t}();e.Mystical=s}])});
\ No newline at end of file
diff --git a/package.json b/package.json
index b6f2efb..9cafcf8 100644
--- a/package.json
+++ b/package.json
@@ -1,9 +1,9 @@
 {
   "name": "mystical-notification",
-  "version": "0.3.0",
+  "version": "0.3.1",
   "description": "Web alerts I needed.",
   "main": "dist/mystical",
-  "typings": "index.d.ts",
+  "typings": "dist/index.d.ts",
   "repository": {
     "type": "git",
     "url": "https://github.com/bradmartin/mystical-notification"
diff --git a/src/index.d.ts b/src/index.d.ts
index 0a0e393..37ac845 100644
--- a/src/index.d.ts
+++ b/src/index.d.ts
@@ -1,9 +1,4 @@
 export declare class Mystical {
-    private static bgColor;
-    private static fgColor;
-    private static position;
-    private static positiveText;
-    private static negativeText;
     /**
      * Creates a simple notification
      * @param opts [MysticalOptions] - The mystical notifications options.
@@ -14,32 +9,6 @@ export declare class Mystical {
      * @param opts [ConfirmOptions]
      */
     static confirm(opts: ConfirmOptions): Promise<boolean>;
-    private static startTransition(defaults, note, top, bottom);
-    private static setInitStyles(defaults, note);
-    /**
-     * Starts the CSS transition and then removes from DOM
-     * @param id - note to remove
-     * @param position - note position
-     */
-    private static removeNoteFromDom(id, position);
-    /**
-     * Helper for setTimeout with 0
-     */
-    private static tick();
-    /**
-     * Helper for setTimeout with passed duration
-     * @param time [number] - milliseconds to wait
-     */
-    private static wait(time);
-    /**
-     * Returns an object with the options object settings - since several args are optional
-     * @param opts
-     */
-    private static createDefaultOpts(opts);
-    /**
-     * Generate random ID
-     */
-    private static generateRandomId();
 }
 export interface AlertOptions {
     template: string;
diff --git a/src/index.ts b/src/index.ts
index 31eebdd..8327be0 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,31 +1,26 @@
 export class Mystical {
-    private static bgColor: string = "#333"
-    private static fgColor: string = "#fff"
-    private static position: string = "top"
-    private static positiveText: string = "Yes"
-    private static negativeText: string = "No"
 
     /**
      * Creates a simple notification
      * @param opts [MysticalOptions] - The mystical notifications options.
      */
     public static alert(opts: AlertOptions) {
-        const defaults = this.createDefaultOpts(opts)
+        const defaults = createDefaultOpts(opts)
 
         // create the main note div
         const note = document.createElement("div") as HTMLDivElement
-        note.id = this.generateRandomId()
+        note.id = generateRandomId()
         note.tabIndex = -1
-        note.style.cssText = `background-color: ${defaults.bg}; border: none; user-select: none; -webkit-tap-highlight-color: rgba(255, 255, 255, 0); outline: none; cursor: pointer; color: ${defaults.fg}; position: fixed; left: 0; padding: 10px; width: 100%; transition: all 0.5s ease; margin: 0 auto; overflow-x: hidden;`
+        note.style.cssText = `background-color: ${defaults.bg}; z-index: 99999999; border: none; user-select: none; -webkit-tap-highlight-color: rgba(255, 255, 255, 0); outline: none; cursor: pointer; color: ${defaults.fg}; position: fixed; left: 0; padding: 10px; width: 100%; transition: all 0.5s ease; margin: 0 auto; overflow-x: hidden;`
 
         // add click event
         note.onclick = () => {
-            this.removeNoteFromDom(note.id, defaults.pos)
+            removeNoteFromDom(note.id, defaults.pos)
         }
         // close on enter and escape key press
         note.onkeydown = (ev: KeyboardEvent) => {
             if (ev.keyCode === 13 || ev.keyCode === 27) {
-                this.removeNoteFromDom(note.id, defaults.pos)
+                removeNoteFromDom(note.id, defaults.pos)
             }
         }
 
@@ -34,14 +29,14 @@ export class Mystical {
                     ${opts.template}
                 </div>
         `
-        const iStyles = this.setInitStyles(defaults, note)
+        const iStyles = setInitStyles(defaults, note)
 
         // add the note div to the DOM
         document.body.appendChild(note)
         note.focus()
 
         // after the note div is on the DOM - to trigger the CSS transition
-        this.startTransition(defaults, note, iStyles.top, iStyles.bottom)
+        startTransition(defaults, note, iStyles.top, iStyles.bottom)
 
     }
 
@@ -52,24 +47,24 @@ export class Mystical {
     public static confirm(opts: ConfirmOptions): Promise<boolean> {
         return new Promise((resolve, reject) => {
 
-            const defaults = this.createDefaultOpts(opts)
+            const defaults = createDefaultOpts(opts)
 
             // create the main note div
             const note = document.createElement("div") as HTMLDivElement
-            note.id = this.generateRandomId()
+            note.id = generateRandomId()
             note.tabIndex = -1
-            note.style.cssText = `background-color: ${defaults.bg}; border: none; user-select: none; -webkit-tap-highlight-color: rgba(255, 255, 255, 0); outline: none; color: ${defaults.fg}; position: fixed; left: 0; padding: 10px; width: 100%; transition: all 0.5s ease; margin: 0 auto; overflow-x: hidden;`
+            note.style.cssText = `background-color: ${defaults.bg}; z-index: 99999999; border: none; user-select: none; -webkit-tap-highlight-color: rgba(255, 255, 255, 0); outline: none; color: ${defaults.fg}; position: fixed; left: 0; padding: 10px; width: 100%; transition: all 0.5s ease; margin: 0 auto; overflow-x: hidden;`
 
             // close on enter and escape key press
             note.onkeydown = (ev: KeyboardEvent) => {
                 if (ev.keyCode === 13 || ev.keyCode === 27) {
-                    this.removeNoteFromDom(note.id, defaults.pos)
+                    removeNoteFromDom(note.id, defaults.pos)
                     resolve(false)
                 }
             }
 
-            const positiveBtnId = this.generateRandomId()
-            const negativeBtnId = this.generateRandomId()
+            const positiveBtnId = generateRandomId()
+            const negativeBtnId = generateRandomId()
             const buttonStyle = `color: ${defaults.fg}; background-color: ${defaults.bg}; cursor: pointer; border: none; background: transparent; outline: none; margin-right: 10px; font-size: 1.1em`
 
             note.innerHTML = `
@@ -82,7 +77,7 @@ export class Mystical {
                 </div>
         `
 
-            const iStyles = this.setInitStyles(defaults, note)
+            const iStyles = setInitStyles(defaults, note)
 
             // add the note div to the DOM
             document.body.appendChild(note)
@@ -92,117 +87,119 @@ export class Mystical {
             const positiveBtn = document.getElementById(positiveBtnId)
             positiveBtn.onclick = () => {
                 resolve(true)
-                this.removeNoteFromDom(note.id, defaults.pos)
+                removeNoteFromDom(note.id, defaults.pos)
             }
 
             // negative btn event
             const negativeBtn = document.getElementById(negativeBtnId)
             negativeBtn.onclick = () => {
                 resolve(false)
-                this.removeNoteFromDom(note.id, defaults.pos)
+                removeNoteFromDom(note.id, defaults.pos)
             }
 
             // after the note div is on the DOM - to trigger the CSS transition
-            this.startTransition(defaults, note, iStyles.top, iStyles.bottom)
+            startTransition(defaults, note, iStyles.top, iStyles.bottom)
 
         })
 
     }
 
 
-    private static startTransition(defaults, note, top, bottom) {
-        // set the top/bottom which will start the transition
-        if (defaults.pos === "top") {
-            this.tick().then(() => {
-                note.style.top = top
-                note.style.opacity = "1"
-            })
-        } else {
-            this.tick().then(() => {
-                note.style.bottom = bottom
-                note.style.opacity = "1"
-            })
-        }
-    }
 
-    private static setInitStyles(defaults, note) {
-        let top: any
-        let bottom: any
-        // set initial top/bottom position
-        if (defaults.pos === "top") {
-            top = "0px"
-            bottom = ""
-            note.style.top = "-200px"
-        } else {
-            top = ""
-            bottom = "0%"
-            note.style.bottom = "-200px"
-        }
-
-        return { top: top, bottom: bottom }
-    }
-
-    /**
-     * Starts the CSS transition and then removes from DOM
-     * @param id - note to remove
-     * @param position - note position
-     */
-    private static removeNoteFromDom(id, position) {
-        let note = document.getElementById(id)
-        if (position === "top") {
-            note.style.top = "-150px"
-        } else {
-            note.style.bottom = "-150px"
-        }
+}
 
-        this.wait(500).then(() => {
-            if (note)
-                document.body.removeChild(note)
+function startTransition(defaults, note, top, bottom) {
+    // set the top/bottom which will start the transition
+    if (defaults.pos === "top") {
+        tick().then(() => {
+            note.style.top = top
+            note.style.opacity = "1"
         })
-    }
-
-    /**
-     * Helper for setTimeout with 0
-     */
-    private static tick(): Promise<any> {
-        return new Promise((resolve) => {
-            setTimeout(resolve, 0)
+    } else {
+        tick().then(() => {
+            note.style.bottom = bottom
+            note.style.opacity = "1"
         })
     }
+}
 
-    /**
-     * Helper for setTimeout with passed duration
-     * @param time [number] - milliseconds to wait
-     */
-    private static wait(time: number): Promise<any> {
-        return new Promise((resolve) => {
-            setTimeout(resolve, time)
-        })
+function setInitStyles(defaults, note) {
+    let top: any
+    let bottom: any
+    // set initial top/bottom position
+    if (defaults.pos === "top") {
+        top = "0px"
+        bottom = ""
+        note.style.top = "-200px"
+    } else {
+        top = ""
+        bottom = "0%"
+        note.style.bottom = "-200px"
     }
 
-    /**
-     * Returns an object with the options object settings - since several args are optional
-     * @param opts 
-     */
-    private static createDefaultOpts(opts) {
-        const bg = opts.backgroundColor ? opts.backgroundColor : this.bgColor
-        const fg = opts.color ? opts.color : this.fgColor
-        const pos = opts.position ? opts.position : this.position
-        const posText = opts.positiveText ? opts.positiveText : this.positiveText
-        const negText = opts.negativeText ? opts.negativeText : this.negativeText
-        return { bg, fg, pos, posText, negText }
-    }
+    return { top: top, bottom: bottom }
+}
 
-    /**
-     * Generate random ID
-     */
-    private static generateRandomId() {
-        const x = Math.floor(Math.random() * 90000) + 10000
-        return `mystical-${x}`
+/**
+ * Starts the CSS transition and then removes from DOM
+ * @param id - note to remove
+ * @param position - note position
+ */
+function removeNoteFromDom(id, position) {
+    let note = document.getElementById(id)
+    if (position === "top") {
+        note.style.top = "-150px"
+    } else {
+        note.style.bottom = "-150px"
     }
 
+    wait(500).then(() => {
+        if (note)
+            document.body.removeChild(note)
+    })
+}
+
+/**
+ * Helper for setTimeout with 0
+ */
+function tick(): Promise<any> {
+    return new Promise((resolve) => {
+        setTimeout(resolve, 0)
+    })
+}
+
+/**
+ * Helper for setTimeout with passed duration
+ * @param time [number] - milliseconds to wait
+ */
+function wait(time: number): Promise<any> {
+    return new Promise((resolve) => {
+        setTimeout(resolve, time)
+    })
+}
+
+/**
+ * Returns an object with the options object settings - since several args are optional
+ * @param opts 
+ */
+function createDefaultOpts(opts) {
+    const bg = opts.backgroundColor ? opts.backgroundColor : "#333"
+    const fg = opts.color ? opts.color : "#fff"
+    const pos = opts.position ? opts.position : "top"
+    const posText = opts.positiveText ? opts.positiveText : "Yes"
+    const negText = opts.negativeText ? opts.negativeText : "No"
+    return { bg, fg, pos, posText, negText }
+}
+
+/**
+ * Generate random ID
+ */
+function generateRandomId() {
+    const x = Math.floor(Math.random() * 90000) + 10000
+    return `mystical-${x}`
 }
 
+
 export interface AlertOptions {
     template: string;
     backgroundColor?: string;