From 11983544e716da5b771454e4d5765410c48b0525 Mon Sep 17 00:00:00 2001 From: dawn-lc Date: Thu, 10 Apr 2025 16:29:29 +0800 Subject: [PATCH 1/7] Refactoring with TypeScript --- build/build.js | 60 ++++++ dist/toastify.css | 170 +++++++++++++++++ dist/toastify.js | 304 ++++++++++++++++++++++++++++++ dist/toastify.js.map | 7 + dist/toastify.min.css | 1 + dist/toastify.min.js | 2 + dist/toastify.min.js.map | 7 + example/script.js | 61 +++--- index.html | 8 +- src/toastify-ts.css | 202 ++++++++++++++++++++ src/toastify.ts | 389 +++++++++++++++++++++++++++++++++++++++ tsconfig.json | 12 ++ 12 files changed, 1191 insertions(+), 32 deletions(-) create mode 100644 build/build.js create mode 100644 dist/toastify.css create mode 100644 dist/toastify.js create mode 100644 dist/toastify.js.map create mode 100644 dist/toastify.min.css create mode 100644 dist/toastify.min.js create mode 100644 dist/toastify.min.js.map create mode 100644 src/toastify-ts.css create mode 100644 src/toastify.ts create mode 100644 tsconfig.json diff --git a/build/build.js b/build/build.js new file mode 100644 index 0000000..5271d01 --- /dev/null +++ b/build/build.js @@ -0,0 +1,60 @@ +const root = process.cwd(); +import { join, parse } from 'path'; +import { readFileSync, existsSync, mkdirSync } from 'fs'; +import esbuild from 'esbuild'; +function mkdir(path) { + return existsSync(path) || mkdirSync(path) +} +const sourcePath = join(root, 'src'); +const packagePath = join(root, 'package.json'); +const tsconfigPath = join(root, 'tsconfig.json'); +const packageConfig = JSON.parse(readFileSync(packagePath, 'utf8')); +const tsConfig = JSON.parse(readFileSync(tsconfigPath, 'utf8')); +const distPath = parse(packageConfig.main).dir; +const mainPath = join(sourcePath, `${packageConfig.name}.ts`); +const cssPath = join(sourcePath, `${packageConfig.name}-ts.css`); +mkdir(distPath); +esbuild.buildSync({ + allowOverwrite: true, + entryPoints: [mainPath], + outfile: join(distPath, `${packageConfig.name}.js`), + minify: false, + sourcemap: true, + platform: 'browser', + format: 'iife', + target: tsConfig.target, + charset: 'utf8' +}); +esbuild.buildSync({ + allowOverwrite: true, + entryPoints: [mainPath], + outfile: join(distPath, `${packageConfig.name}.min.js`), + minify: true, + sourcemap: true, + platform: 'browser', + format: 'iife', + target: tsConfig.target, + charset: 'utf8' +}); +esbuild.buildSync({ + allowOverwrite: true, + entryPoints: [cssPath], + outfile: join(distPath, `${packageConfig.name}.css`), + minify: false, + loader: { + '.css': 'css' + }, + platform: 'browser', + charset: 'utf8' +}); +esbuild.buildSync({ + allowOverwrite: true, + entryPoints: [cssPath], + outfile: join(distPath, `${packageConfig.name}.min.css`), + minify: true, + loader: { + '.css': 'css' + }, + platform: 'browser', + charset: 'utf8' +}); \ No newline at end of file diff --git a/dist/toastify.css b/dist/toastify.css new file mode 100644 index 0000000..c094980 --- /dev/null +++ b/dist/toastify.css @@ -0,0 +1,170 @@ +.offscreen-container { + position: absolute; + visibility: hidden; + pointer-events: none; + max-width: 480px; +} +.toast-container { + isolation: isolate; + position: fixed; + z-index: 2147483647; + display: flex; + flex-direction: column; + box-sizing: border-box; + transition: transform calc(0.6 * var(--toast-rate) * 1s) ease, opacity calc(0.6 * var(--toast-rate) * 1s) ease; +} +.toast-container.toast-top { + top: 0; +} +.toast-container.toast-bottom { + bottom: 0; +} +.toast-container.toast-left { + left: 0; + align-items: flex-start; +} +.toast-container.toast-center { + left: 50%; + transform: translateX(-50%); + align-items: center; +} +.toast-container.toast-right { + right: 0; + align-items: flex-end; +} +#toast-container-top-left .toast { + margin: 10px 0 0 10px; + transform-origin: left center; +} +#toast-container-top-center .toast { + margin: 10px 0 0 0; + transform-origin: top; +} +#toast-container-top-right .toast { + margin: 10px 10px 0 0; + transform-origin: right center; +} +#toast-container-bottom-left .toast { + margin: 0 0 10px 10px; + transform-origin: left center; +} +#toast-container-bottom-center .toast { + margin: 0 0 10px 0; + transform-origin: bottom; +} +#toast-container-bottom-right .toast { + margin: 0 10px 10px 0; + transform-origin: right center; +} +.toast { + --toast-rate: 1; + --toast-translate: 0; + --toast-scale: 1; + position: relative; + transition: transform calc(0.4s * var(--toast-rate)) cubic-bezier(0.34, 1.56, 0.64, 1), opacity calc(0.3s * var(--toast-rate)) ease; + transform: translate3d(0, var(--toast-translate), 0) scale(var(--toast-scale)); + max-width: 480px; + max-height: 0px; + will-change: transform, opacity; + backface-visibility: hidden; + contain: content; + border-radius: 6px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.25); +} +.toast-close { + position: absolute; + color: white; + top: 5px; + right: 5px; + cursor: pointer; + font-size: 12px; + line-height: 12px; + z-index: 2147483648; + transform-origin: center center; +} +.toast-content { + border-radius: 6px; + padding: 14px 18px 14px 18px; + max-width: 100%; + box-sizing: border-box; + background: rgb(55, 208, 255); + color: white; + cursor: pointer; + white-space: normal; + word-break: break-all; + overflow: hidden; + position: relative; +} +.toast-progress { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 4px; + background: rgba(255, 255, 255, 0.8); + transform: scaleX(var(--toast-progress, 1)); + transition: transform calc(0.1 * var(--toast-rate) * 1s) ease-in; + will-change: transform; + backface-visibility: hidden; +} +.toast:hover { + z-index: 2147483648; + --toast-scale: 1.15; +} +.toast-container.toast-left .toast .toast-content .toast-progress { + transform-origin: left; +} +.toast-container.toast-center .toast .toast-content .toast-progress { + transform-origin: center; +} +.toast-container.toast-right .toast .toast-content .toast-progress { + transform-origin: right; +} +.toast-container.toast-top .toast.show { + animation: toast-in-top calc(0.3 * var(--toast-rate) * 1s) ease-in-out forwards; +} +.toast-container.toast-bottom .toast.show { + animation: toast-in-bottom calc(0.3 * var(--toast-rate) * 1s) ease-in-out forwards; +} +.toast-container.toast-top .toast.hide { + animation: toast-out-top calc(0.3 * var(--toast-rate) * 1s) ease-in-out forwards; +} +.toast-container.toast-bottom .toast.hide { + animation: toast-out-bottom calc(0.3 * var(--toast-rate) * 1s) ease-in-out forwards; +} +@keyframes toast-in-top { + from { + opacity: 0; + max-height: 0px; + } + to { + max-height: var(--toast-height); + } +} +@keyframes toast-in-bottom { + from { + opacity: 0; + max-height: 0px; + } + to { + max-height: var(--toast-height); + } +} +@keyframes toast-out-top { + from { + max-height: var(--toast-height); + } + to { + opacity: 0; + max-height: 0px; + } +} +@keyframes toast-out-bottom { + from { + max-height: var(--toast-height); + } + to { + opacity: 0; + max-height: 0px; + } +} diff --git a/dist/toastify.js b/dist/toastify.js new file mode 100644 index 0000000..e146dd1 --- /dev/null +++ b/dist/toastify.js @@ -0,0 +1,304 @@ +"use strict"; +(() => { + const isNull = (obj) => obj === null; + const isUndefined = (obj) => typeof obj === "undefined"; + const isNullOrUndefined = (obj) => isUndefined(obj) || isNull(obj); + const activeToasts = /* @__PURE__ */ new Set(); + const toastTimeouts = /* @__PURE__ */ new Map(); + const toastIntervals = /* @__PURE__ */ new Map(); + const toastContainers = /* @__PURE__ */ new Map(); + function debounce(fn, delay, { immediate = false } = {}) { + let timer = null; + const debounced = function(...args) { + const callNow = immediate && !timer; + if (timer) { + clearTimeout(timer); + } + timer = setTimeout(() => { + timer = null; + if (!immediate) { + fn.apply(this, args); + } + }, delay); + if (callNow) { + fn.apply(this, args); + } + }; + debounced.cancel = () => { + if (timer) { + clearTimeout(timer); + timer = null; + } + }; + return debounced; + } + const getContainer = (gravity, position) => { + const containerId = `toast-container-${gravity}-${position}`; + if (!toastContainers.has(containerId)) { + const container = document.createElement("div"); + container.id = containerId; + container.classList.add( + "toast-container", + `toast-${gravity}`, + `toast-${position}` + ); + document.body.appendChild(container); + toastContainers.set(containerId, container); + } + return toastContainers.get(containerId); + }; + const addTimeout = (toast, callback) => { + delTimeout(toast); + const startTime = Date.now(); + const duration = toast.options.duration; + const updateRemainingTime = () => { + const elapsed = Date.now() - startTime; + const remaining = Math.max(0, duration - elapsed); + toast.progress.style.setProperty("--toast-progress", `${remaining / duration}`); + }; + const intervalId = window.setInterval(updateRemainingTime, 20); + const timeoutId = window.setTimeout(() => { + toast.progress.style.setProperty("--toast-progress", `0`); + callback(); + delTimeout(toast); + }, duration); + toastTimeouts.set(toast, timeoutId); + toastIntervals.set(toast, intervalId); + }; + const delTimeout = (toast) => { + const timeoutId = toastTimeouts.get(toast); + const intervalId = toastIntervals.get(toast); + if (!isNullOrUndefined(timeoutId)) { + clearTimeout(timeoutId); + toastTimeouts.delete(toast); + } + if (!isNullOrUndefined(intervalId)) { + clearInterval(intervalId); + toastIntervals.delete(toast); + } + }; + const offscreenContainer = document.createElement("div"); + offscreenContainer.classList.add("offscreen-container"); + document.body.appendChild(offscreenContainer); + window.addEventListener("resize", debounce(() => { + for (const toast of activeToasts) { + toast.setToastRect(); + } + }, 100)); + class Toast { + static defaults = { + gravity: "top", + position: "right", + stopOnFocus: true, + oldestFirst: true + }; + options; + root; + element; + gravity; + position; + oldestFirst; + stopOnFocus; + content; + progress; + mouseOverHandler; + mouseLeaveHandler; + closeButtonHandler; + animationEndHandler; + clickHandler; + closeButton; + /** + * Create a Toastify instance + * @param options User configuration options + */ + constructor(options) { + this.options = { + ...Toast.defaults, + ...options + }; + this.root = getContainer(this.options.gravity, this.options.position); + this.gravity = this.options.gravity; + this.position = this.options.position; + this.stopOnFocus = this.options.stopOnFocus; + this.oldestFirst = this.options.oldestFirst; + this.element = document.createElement("div"); + this.applyBaseStyles().addCloseButton().createContent().ensureCloseMethod().bindEvents(); + activeToasts.add(this); + } + applyBaseStyles() { + this.element.classList.add("toast"); + if (this.options.className) { + const classes = Array.isArray(this.options.className) ? this.options.className : [this.options.className]; + classes.forEach((cls) => this.element.classList.add(cls)); + } + return this; + } + createContent() { + this.content = document.createElement("div"); + this.content.classList.add("toast-content"); + if (this.options.text) { + this.content.textContent = this.options.text; + } + if (this.options.node) { + this.content.appendChild(this.options.node); + } + if (this.options.style) { + this.applyStyles(this.content, this.options.style); + } + if (!isNullOrUndefined(this.options.duration) && this.options.duration > 0) { + this.progress = document.createElement("div"); + this.progress.classList.add("toast-progress"); + this.content.appendChild(this.progress); + console.log(this.content.querySelector(".toast-progress")); + } + this.element.appendChild(this.content); + return this; + } + addCloseButton() { + if (this.options.close) { + this.closeButton = document.createElement("span"); + this.closeButton.className = "toast-close"; + this.closeButton.textContent = "🗙"; + this.closeButtonHandler = () => this.hide("close-button"); + this.closeButton.addEventListener("click", this.closeButtonHandler); + this.element.appendChild(this.closeButton); + } + return this; + } + setToastRect() { + if (!this.element.classList.contains("show")) offscreenContainer.appendChild(this.element); + this.element.style.removeProperty("--toast-height"); + this.element.style.removeProperty("--toast-width"); + this.element.style.setProperty("max-height", "none", "important"); + if (this.position == "center") this.element.style.setProperty("max-width", `${this.root.getBoundingClientRect().width}px`, "important"); + const { height, width } = this.element.getBoundingClientRect(); + this.element.style.setProperty("--toast-height", `${height}px`); + this.element.style.setProperty("--toast-width", `${width}px`); + this.element.style.removeProperty("max-height"); + this.element.style.removeProperty("max-width"); + if (!this.element.classList.contains("show")) offscreenContainer.removeChild(this.element); + return this; + } + ensureCloseMethod() { + if (isNullOrUndefined(this.options.duration) && isNullOrUndefined(this.options.close) && isNullOrUndefined(this.options.onClick)) { + this.options.onClick = () => this.hide("other"); + } + return this; + } + bindEvents() { + if (this.stopOnFocus && !isNullOrUndefined(this.options.duration) && this.options.duration > 0) { + this.mouseOverHandler = () => delTimeout(this); + this.mouseLeaveHandler = () => addTimeout(this, () => this.hide("timeout")); + this.element.addEventListener("mouseover", this.mouseOverHandler); + this.element.addEventListener("mouseleave", this.mouseLeaveHandler); + } + if (!isNullOrUndefined(this.options.onClick)) { + this.clickHandler = this.options.onClick.bind(this); + this.element.addEventListener("click", this.clickHandler); + } + return this; + } + applyStyles(element, styles) { + function camelToKebab(str) { + return str.replace(/([A-Z])/g, "-$1").toLowerCase(); + } + for (const key in styles) { + const value = styles[key]; + const property = camelToKebab(key); + if (isNullOrUndefined(value)) { + element.style.removeProperty(property); + continue; + } + const important = value.includes("!important"); + const cleanValue = value.replace(/\s*!important\s*/, "").trim(); + element.style.setProperty(property, cleanValue, important ? "important" : ""); + } + } + toggleAnimationState(animation) { + if (!this.element.classList.replace(animation ? "hide" : "show", animation ? "show" : "hide")) { + this.element.classList.add(animation ? "show" : "hide"); + } + return this; + } + insertToastElement() { + if (this.oldestFirst) { + this.root.insertBefore(this.element, this.root.firstChild); + } else { + if (this.root.lastChild) { + this.root.insertBefore(this.element, this.root.lastChild.nextSibling); + } else { + this.root.appendChild(this.element); + } + } + return this; + } + setupAutoHide() { + if (!isNullOrUndefined(this.options.duration) && this.options.duration > 0) { + addTimeout(this, () => this.hide("timeout")); + } + return this; + } + /** + * Display the Toast notification + * @returns this Instance for method chaining + */ + show() { + this.setToastRect().insertToastElement().toggleAnimationState(true).setupAutoHide(); + return this; + } + /** + * @deprecated This function is deprecated. Use the show() instead. + */ + showToast() { + return this.show(); + } + removeEventListeners() { + if (this.mouseOverHandler) { + this.element.removeEventListener("mouseover", this.mouseOverHandler); + } + if (this.mouseLeaveHandler) { + this.element.removeEventListener("mouseleave", this.mouseLeaveHandler); + } + if (this.clickHandler) { + this.element.removeEventListener("click", this.clickHandler); + } + if (this.options.close && this.closeButton && this.closeButtonHandler) { + this.closeButton.removeEventListener("click", this.closeButtonHandler); + } + return this; + } + /** + * Hide the current Toast with optional close reason + * @param reason The reason for closing (default: 'other') + * Triggers a CSS exit animation and removes the element after the animation completes + */ + hide(reason = "other") { + if (!this.element) return; + delTimeout(this); + activeToasts.delete(this); + this.animationEndHandler = (e) => { + if (e.animationName.startsWith("toast-out")) { + this.element.removeEventListener("animationend", this.animationEndHandler); + this.element.remove(); + this.options.onClose?.call(this, new CustomEvent("toast-close", { + detail: { reason } + })); + } + }; + this.element.addEventListener("animationend", this.animationEndHandler); + this.removeEventListeners().toggleAnimationState(false); + } + /** + * @deprecated This function is deprecated. Use the hide() instead. + */ + hideToast() { + this.hide("other"); + } + } + function createToast(options) { + return new Toast(options); + } + globalThis.Toast = createToast; + globalThis.Toastify = createToast; +})(); +//# sourceMappingURL=toastify.js.map diff --git a/dist/toastify.js.map b/dist/toastify.js.map new file mode 100644 index 0000000..c04833b --- /dev/null +++ b/dist/toastify.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../src/toastify.ts"], + "sourcesContent": ["export type Gravity = 'top' | 'bottom';\r\nexport type Position = 'left' | 'center' | 'right';\r\nexport type CloseReason = 'timeout' | 'close-button' | 'other';\r\ntype DebounceOptions = {\r\n immediate?: boolean\r\n}\r\nconst isNull = (obj: unknown): obj is null => obj === null;\r\nconst isUndefined = (obj: unknown): obj is undefined => typeof obj === 'undefined';\r\nconst isNullOrUndefined = (obj: unknown): obj is null | undefined => isUndefined(obj) || isNull(obj);\r\nconst activeToasts = new Set();\r\nconst toastTimeouts = new Map();\r\nconst toastIntervals = new Map();\r\nconst toastContainers = new Map();\r\nfunction debounce any>(\r\n fn: T,\r\n delay: number,\r\n { immediate = false }: DebounceOptions = {}\r\n) {\r\n let timer: ReturnType | null = null\r\n const debounced = function (this: any, ...args: Parameters) {\r\n const callNow = immediate && !timer\r\n if (timer) {\r\n clearTimeout(timer)\r\n }\r\n timer = setTimeout(() => {\r\n timer = null\r\n if (!immediate) {\r\n fn.apply(this, args)\r\n }\r\n }, delay)\r\n if (callNow) {\r\n fn.apply(this, args)\r\n }\r\n } as T & { cancel: () => void }\r\n debounced.cancel = () => {\r\n if (timer) {\r\n clearTimeout(timer)\r\n timer = null\r\n }\r\n }\r\n return debounced\r\n}\r\nconst getContainer = (gravity: Gravity, position: Position): HTMLElement => {\r\n const containerId = `toast-container-${gravity}-${position}`;\r\n if (!toastContainers.has(containerId)) {\r\n const container = document.createElement('div');\r\n container.id = containerId;\r\n container.classList.add(\r\n 'toast-container',\r\n `toast-${gravity}`,\r\n `toast-${position}`\r\n );\r\n document.body.appendChild(container);\r\n toastContainers.set(containerId, container);\r\n }\r\n return toastContainers.get(containerId)!;\r\n};\r\nconst addTimeout = (toast: Toast, callback: () => void): void => {\r\n delTimeout(toast);\r\n const startTime = Date.now();\r\n const duration = toast.options.duration!;\r\n const updateRemainingTime = () => {\r\n const elapsed = Date.now() - startTime;\r\n const remaining = Math.max(0, duration - elapsed);\r\n toast.progress!.style.setProperty('--toast-progress', `${remaining / duration}`);\r\n };\r\n const intervalId = window.setInterval(updateRemainingTime, 20);\r\n const timeoutId = window.setTimeout(() => {\r\n toast.progress!.style.setProperty('--toast-progress', `0`);\r\n callback();\r\n delTimeout(toast);\r\n }, duration);\r\n toastTimeouts.set(toast, timeoutId);\r\n toastIntervals.set(toast, intervalId);\r\n};\r\nconst delTimeout = (toast: Toast): void => {\r\n const timeoutId = toastTimeouts.get(toast);\r\n const intervalId = toastIntervals.get(toast);\r\n\r\n if (!isNullOrUndefined(timeoutId)) {\r\n clearTimeout(timeoutId);\r\n toastTimeouts.delete(toast);\r\n }\r\n if (!isNullOrUndefined(intervalId)) {\r\n clearInterval(intervalId);\r\n toastIntervals.delete(toast);\r\n }\r\n};\r\nconst offscreenContainer = document.createElement('div');\r\noffscreenContainer.classList.add('offscreen-container');\r\ndocument.body.appendChild(offscreenContainer);\r\n\r\nwindow.addEventListener('resize', debounce(() => {\r\n for (const toast of activeToasts) {\r\n toast.setToastRect();\r\n }\r\n}, 100));\r\nexport interface ToastOptions {\r\n root?: Element;\r\n text?: string;\r\n node?: Node;\r\n duration?: number;\r\n close?: boolean;\r\n gravity?: Gravity;\r\n position?: Position;\r\n className?: string | string[];\r\n stopOnFocus?: boolean;\r\n onClose?: (this: Toast, e: CustomEvent<{ reason: CloseReason }>) => void;\r\n onClick?: (this: Toast, e: MouseEvent) => void;\r\n style?: Partial;\r\n oldestFirst?: boolean;\r\n}\r\ninterface Options {\r\n gravity: Gravity;\r\n position: Position;\r\n stopOnFocus: boolean;\r\n oldestFirst: boolean;\r\n text?: string;\r\n node?: Node;\r\n duration?: number;\r\n close?: boolean;\r\n className?: string | string[];\r\n onClose?: (this: Toast, e: CustomEvent<{ reason: CloseReason }>) => void;\r\n onClick?: (this: Toast, e: MouseEvent) => void;\r\n style?: Partial;\r\n}\r\n/**\r\n * Toast\r\n * @example\r\n * new Toast({ text: 'Hello World' }).show();\r\n */\r\nexport class Toast {\r\n private static readonly defaults: Options = {\r\n gravity: 'top',\r\n position: 'right',\r\n stopOnFocus: true,\r\n oldestFirst: true,\r\n };\r\n public options: Options;\r\n public root: Element;\r\n public element: HTMLElement;\r\n\r\n public gravity: Gravity;\r\n public position: Position;\r\n public oldestFirst: boolean;\r\n public stopOnFocus: boolean;\r\n public content?: HTMLDivElement;\r\n public progress?: HTMLDivElement;\r\n\r\n private mouseOverHandler?: () => void;\r\n private mouseLeaveHandler?: () => void;\r\n private closeButtonHandler?: () => void;\r\n private animationEndHandler?: (e: AnimationEvent) => void;\r\n private clickHandler?: (e: MouseEvent) => void;\r\n\r\n private closeButton?: HTMLSpanElement;\r\n\r\n /**\r\n * Create a Toastify instance\r\n * @param options User configuration options\r\n */\r\n constructor(options: ToastOptions) {\r\n this.options = {\r\n ...Toast.defaults,\r\n ...options\r\n };\r\n\r\n this.root = getContainer(this.options.gravity, this.options.position);\r\n this.gravity = this.options.gravity;\r\n this.position = this.options.position;\r\n this.stopOnFocus = this.options.stopOnFocus;\r\n this.oldestFirst = this.options.oldestFirst;\r\n\r\n this.element = document.createElement('div');\r\n this.applyBaseStyles()\r\n .addCloseButton()\r\n .createContent()\r\n .ensureCloseMethod()\r\n .bindEvents();\r\n\r\n activeToasts.add(this);\r\n }\r\n\r\n private applyBaseStyles(): this {\r\n this.element.classList.add('toast');\r\n if (this.options.className) {\r\n const classes = Array.isArray(this.options.className)\r\n ? this.options.className\r\n : [this.options.className];\r\n classes.forEach(cls => this.element.classList.add(cls));\r\n }\r\n return this;\r\n }\r\n\r\n private createContent(): this {\r\n this.content = document.createElement('div');\r\n this.content.classList.add('toast-content');\r\n\r\n if (this.options.text) {\r\n this.content.textContent = this.options.text;\r\n }\r\n if (this.options.node) {\r\n this.content.appendChild(this.options.node);\r\n }\r\n if (this.options.style) {\r\n this.applyStyles(this.content, this.options.style);\r\n }\r\n if (!isNullOrUndefined(this.options.duration) && this.options.duration > 0) {\r\n this.progress = document.createElement('div');\r\n this.progress.classList.add('toast-progress');\r\n this.content.appendChild(this.progress);\r\n console.log(this.content.querySelector('.toast-progress'));\r\n }\r\n\r\n this.element.appendChild(this.content);\r\n return this;\r\n }\r\n\r\n private addCloseButton(): this {\r\n if (this.options.close) {\r\n this.closeButton = document.createElement('span');\r\n this.closeButton.className = 'toast-close';\r\n this.closeButton.textContent = '🗙';\r\n this.closeButtonHandler = () => this.hide('close-button');\r\n this.closeButton.addEventListener('click', this.closeButtonHandler);\r\n this.element.appendChild(this.closeButton);\r\n }\r\n return this;\r\n }\r\n\r\n public setToastRect(): this {\r\n // fix max-height cannot be automatically animated\r\n if (!this.element.classList.contains('show')) offscreenContainer.appendChild(this.element);\r\n this.element.style.removeProperty('--toast-height');\r\n this.element.style.removeProperty('--toast-width');\r\n this.element.style.setProperty('max-height', 'none', 'important');\r\n if (this.position == 'center') this.element.style.setProperty('max-width', `${this.root.getBoundingClientRect().width}px`, 'important');\r\n const { height, width } = this.element.getBoundingClientRect();\r\n this.element.style.setProperty('--toast-height', `${height}px`);\r\n this.element.style.setProperty('--toast-width', `${width}px`);\r\n this.element.style.removeProperty('max-height');\r\n this.element.style.removeProperty('max-width');\r\n if (!this.element.classList.contains('show')) offscreenContainer.removeChild(this.element);\r\n return this;\r\n }\r\n private ensureCloseMethod(): this {\r\n if (isNullOrUndefined(this.options.duration) && isNullOrUndefined(this.options.close) && isNullOrUndefined(this.options.onClick)) {\r\n this.options.onClick = () => this.hide('other');\r\n }\r\n return this;\r\n }\r\n\r\n private bindEvents(): this {\r\n if (this.stopOnFocus && !isNullOrUndefined(this.options.duration) && this.options.duration > 0) {\r\n this.mouseOverHandler = () => delTimeout(this);\r\n this.mouseLeaveHandler = () => addTimeout(this, () => this.hide('timeout'));\r\n this.element.addEventListener('mouseover', this.mouseOverHandler);\r\n this.element.addEventListener('mouseleave', this.mouseLeaveHandler);\r\n }\r\n if (!isNullOrUndefined(this.options.onClick)) {\r\n this.clickHandler = this.options.onClick.bind(this);\r\n this.element.addEventListener('click', this.clickHandler);\r\n }\r\n return this;\r\n }\r\n\r\n private applyStyles(element: HTMLElement, styles: Partial) {\r\n function camelToKebab(str: string): string {\r\n return str.replace(/([A-Z])/g, '-$1').toLowerCase();\r\n }\r\n for (const key in styles) {\r\n const value = styles[key];\r\n const property = camelToKebab(key);\r\n if (isNullOrUndefined(value)) {\r\n element.style.removeProperty(property);\r\n continue;\r\n }\r\n const important = value.includes('!important');\r\n const cleanValue = value.replace(/\\s*!important\\s*/, '').trim();\r\n element.style.setProperty(property, cleanValue, important ? 'important' : '');\r\n }\r\n }\r\n\r\n private toggleAnimationState(animation: boolean): this {\r\n if (!this.element.classList.replace(animation ? 'hide' : 'show', animation ? 'show' : 'hide')) {\r\n this.element.classList.add(animation ? 'show' : 'hide');\r\n }\r\n return this;\r\n }\r\n\r\n private insertToastElement(): this {\r\n if (this.oldestFirst) {\r\n this.root.insertBefore(this.element, this.root.firstChild);\r\n } else {\r\n if (this.root.lastChild) {\r\n this.root.insertBefore(this.element, this.root.lastChild.nextSibling);\r\n } else {\r\n this.root.appendChild(this.element);\r\n }\r\n }\r\n return this;\r\n }\r\n\r\n private setupAutoHide(): this {\r\n if (!isNullOrUndefined(this.options.duration) && this.options.duration > 0) {\r\n addTimeout(this, () => this.hide('timeout'));\r\n }\r\n return this;\r\n }\r\n /**\r\n * Display the Toast notification\r\n * @returns this Instance for method chaining\r\n */\r\n public show(): this {\r\n this.setToastRect()\r\n .insertToastElement()\r\n .toggleAnimationState(true)\r\n .setupAutoHide();\r\n return this;\r\n }\r\n\r\n /**\r\n * @deprecated This function is deprecated. Use the show() instead.\r\n */\r\n public showToast() {\r\n return this.show();\r\n }\r\n\r\n private removeEventListeners(): this {\r\n if (this.mouseOverHandler) {\r\n this.element.removeEventListener('mouseover', this.mouseOverHandler);\r\n }\r\n if (this.mouseLeaveHandler) {\r\n this.element.removeEventListener('mouseleave', this.mouseLeaveHandler);\r\n }\r\n if (this.clickHandler) {\r\n this.element.removeEventListener('click', this.clickHandler);\r\n }\r\n if (this.options.close && this.closeButton && this.closeButtonHandler) {\r\n this.closeButton.removeEventListener('click', this.closeButtonHandler);\r\n }\r\n return this;\r\n }\r\n\r\n /**\r\n * Hide the current Toast with optional close reason\r\n * @param reason The reason for closing (default: 'other')\r\n * Triggers a CSS exit animation and removes the element after the animation completes\r\n */\r\n public hide(reason: CloseReason = 'other'): void {\r\n if (!this.element) return;\r\n delTimeout(this);\r\n activeToasts.delete(this);\r\n this.animationEndHandler = (e: AnimationEvent) => {\r\n if (e.animationName.startsWith('toast-out')) {\r\n this.element.removeEventListener('animationend', this.animationEndHandler!);\r\n this.element.remove();\r\n this.options.onClose?.call(this, new CustomEvent('toast-close', {\r\n detail: { reason }\r\n }));\r\n }\r\n };\r\n this.element.addEventListener('animationend', this.animationEndHandler);\r\n this.removeEventListeners()\r\n .toggleAnimationState(false);\r\n }\r\n\r\n /**\r\n * @deprecated This function is deprecated. Use the hide() instead.\r\n */\r\n public hideToast(): void {\r\n this.hide('other');\r\n }\r\n}\r\n\r\nfunction createToast(options: ToastOptions): Toast {\r\n return new Toast(options);\r\n}\r\n\r\ndeclare global {\r\n function Toast(options: ToastOptions): Toast;\r\n /**\r\n * @deprecated This function is deprecated. Use the Toast() instead.\r\n */\r\n function Toastify(options: ToastOptions): Toast;\r\n}\r\n\r\nglobalThis.Toast = createToast;\r\nglobalThis.Toastify = createToast;\r\n"], + "mappings": "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", + "names": [] +} diff --git a/dist/toastify.min.css b/dist/toastify.min.css new file mode 100644 index 0000000..731b471 --- /dev/null +++ b/dist/toastify.min.css @@ -0,0 +1 @@ +.offscreen-container{position:absolute;visibility:hidden;pointer-events:none;max-width:480px}.toast-container{isolation:isolate;position:fixed;z-index:2147483647;display:flex;flex-direction:column;box-sizing:border-box;transition:transform calc(.6 * var(--toast-rate) * 1s) ease,opacity calc(.6 * var(--toast-rate) * 1s) ease}.toast-container.toast-top{top:0}.toast-container.toast-bottom{bottom:0}.toast-container.toast-left{left:0;align-items:flex-start}.toast-container.toast-center{left:50%;transform:translate(-50%);align-items:center}.toast-container.toast-right{right:0;align-items:flex-end}#toast-container-top-left .toast{margin:10px 0 0 10px;transform-origin:left center}#toast-container-top-center .toast{margin:10px 0 0;transform-origin:top}#toast-container-top-right .toast{margin:10px 10px 0 0;transform-origin:right center}#toast-container-bottom-left .toast{margin:0 0 10px 10px;transform-origin:left center}#toast-container-bottom-center .toast{margin:0 0 10px;transform-origin:bottom}#toast-container-bottom-right .toast{margin:0 10px 10px 0;transform-origin:right center}.toast{--toast-rate: 1;--toast-translate: 0;--toast-scale: 1;position:relative;transition:transform calc(.4s * var(--toast-rate)) cubic-bezier(.34,1.56,.64,1),opacity calc(.3s * var(--toast-rate)) ease;transform:translate3d(0,var(--toast-translate),0) scale(var(--toast-scale));max-width:480px;max-height:0px;will-change:transform,opacity;backface-visibility:hidden;contain:content;border-radius:6px;box-shadow:0 4px 8px #00000040}.toast-close{position:absolute;color:#fff;top:5px;right:5px;cursor:pointer;font-size:12px;line-height:12px;z-index:2147483648;transform-origin:center center}.toast-content{border-radius:6px;padding:14px 18px;max-width:100%;box-sizing:border-box;background:#37d0ff;color:#fff;cursor:pointer;white-space:normal;word-break:break-all;overflow:hidden;position:relative}.toast-progress{position:absolute;bottom:0;left:0;right:0;height:4px;background:#fffc;transform:scaleX(var(--toast-progress, 1));transition:transform calc(.1 * var(--toast-rate) * 1s) ease-in;will-change:transform;backface-visibility:hidden}.toast:hover{z-index:2147483648;--toast-scale: 1.15}.toast-container.toast-left .toast .toast-content .toast-progress{transform-origin:left}.toast-container.toast-center .toast .toast-content .toast-progress{transform-origin:center}.toast-container.toast-right .toast .toast-content .toast-progress{transform-origin:right}.toast-container.toast-top .toast.show{animation:toast-in-top calc(.3 * var(--toast-rate) * 1s) ease-in-out forwards}.toast-container.toast-bottom .toast.show{animation:toast-in-bottom calc(.3 * var(--toast-rate) * 1s) ease-in-out forwards}.toast-container.toast-top .toast.hide{animation:toast-out-top calc(.3 * var(--toast-rate) * 1s) ease-in-out forwards}.toast-container.toast-bottom .toast.hide{animation:toast-out-bottom calc(.3 * var(--toast-rate) * 1s) ease-in-out forwards}@keyframes toast-in-top{0%{opacity:0;max-height:0px}to{max-height:var(--toast-height)}}@keyframes toast-in-bottom{0%{opacity:0;max-height:0px}to{max-height:var(--toast-height)}}@keyframes toast-out-top{0%{max-height:var(--toast-height)}to{opacity:0;max-height:0px}}@keyframes toast-out-bottom{0%{max-height:var(--toast-height)}to{opacity:0;max-height:0px}} diff --git a/dist/toastify.min.js b/dist/toastify.min.js new file mode 100644 index 0000000..e6bdb7b --- /dev/null +++ b/dist/toastify.min.js @@ -0,0 +1,2 @@ +"use strict";(()=>{const g=t=>t===null,b=t=>typeof t>"u",o=t=>b(t)||g(t),u=new Set,m=new Map,v=new Map,p=new Map;function C(t,e,{immediate:s=!1}={}){let i=null;const n=function(...a){const r=s&&!i;i&&clearTimeout(i),i=setTimeout(()=>{i=null,s||t.apply(this,a)},e),r&&t.apply(this,a)};return n.cancel=()=>{i&&(clearTimeout(i),i=null)},n}const E=(t,e)=>{const s=`toast-container-${t}-${e}`;if(!p.has(s)){const i=document.createElement("div");i.id=s,i.classList.add("toast-container",`toast-${t}`,`toast-${e}`),document.body.appendChild(i),p.set(s,i)}return p.get(s)},f=(t,e)=>{l(t);const s=Date.now(),i=t.options.duration,n=()=>{const c=Date.now()-s,d=Math.max(0,i-c);t.progress.style.setProperty("--toast-progress",`${d/i}`)},a=window.setInterval(n,20),r=window.setTimeout(()=>{t.progress.style.setProperty("--toast-progress","0"),e(),l(t)},i);m.set(t,r),v.set(t,a)},l=t=>{const e=m.get(t),s=v.get(t);o(e)||(clearTimeout(e),m.delete(t)),o(s)||(clearInterval(s),v.delete(t))},h=document.createElement("div");h.classList.add("offscreen-container");document.body.appendChild(h);window.addEventListener("resize",C(()=>{for(const t of u)t.setToastRect()},100));class y{static defaults={gravity:"top",position:"right",stopOnFocus:!0,oldestFirst:!0};options;root;element;gravity;position;oldestFirst;stopOnFocus;content;progress;mouseOverHandler;mouseLeaveHandler;closeButtonHandler;animationEndHandler;clickHandler;closeButton;constructor(e){this.options={...y.defaults,...e},this.root=E(this.options.gravity,this.options.position),this.gravity=this.options.gravity,this.position=this.options.position,this.stopOnFocus=this.options.stopOnFocus,this.oldestFirst=this.options.oldestFirst,this.element=document.createElement("div"),this.applyBaseStyles().addCloseButton().createContent().ensureCloseMethod().bindEvents(),u.add(this)}applyBaseStyles(){return this.element.classList.add("toast"),this.options.className&&(Array.isArray(this.options.className)?this.options.className:[this.options.className]).forEach(s=>this.element.classList.add(s)),this}createContent(){return this.content=document.createElement("div"),this.content.classList.add("toast-content"),this.options.text&&(this.content.textContent=this.options.text),this.options.node&&this.content.appendChild(this.options.node),this.options.style&&this.applyStyles(this.content,this.options.style),!o(this.options.duration)&&this.options.duration>0&&(this.progress=document.createElement("div"),this.progress.classList.add("toast-progress"),this.content.appendChild(this.progress),console.log(this.content.querySelector(".toast-progress"))),this.element.appendChild(this.content),this}addCloseButton(){return this.options.close&&(this.closeButton=document.createElement("span"),this.closeButton.className="toast-close",this.closeButton.textContent="🗙",this.closeButtonHandler=()=>this.hide("close-button"),this.closeButton.addEventListener("click",this.closeButtonHandler),this.element.appendChild(this.closeButton)),this}setToastRect(){this.element.classList.contains("show")||h.appendChild(this.element),this.element.style.removeProperty("--toast-height"),this.element.style.removeProperty("--toast-width"),this.element.style.setProperty("max-height","none","important"),this.position=="center"&&this.element.style.setProperty("max-width",`${this.root.getBoundingClientRect().width}px`,"important");const{height:e,width:s}=this.element.getBoundingClientRect();return this.element.style.setProperty("--toast-height",`${e}px`),this.element.style.setProperty("--toast-width",`${s}px`),this.element.style.removeProperty("max-height"),this.element.style.removeProperty("max-width"),this.element.classList.contains("show")||h.removeChild(this.element),this}ensureCloseMethod(){return o(this.options.duration)&&o(this.options.close)&&o(this.options.onClick)&&(this.options.onClick=()=>this.hide("other")),this}bindEvents(){return this.stopOnFocus&&!o(this.options.duration)&&this.options.duration>0&&(this.mouseOverHandler=()=>l(this),this.mouseLeaveHandler=()=>f(this,()=>this.hide("timeout")),this.element.addEventListener("mouseover",this.mouseOverHandler),this.element.addEventListener("mouseleave",this.mouseLeaveHandler)),o(this.options.onClick)||(this.clickHandler=this.options.onClick.bind(this),this.element.addEventListener("click",this.clickHandler)),this}applyStyles(e,s){function i(n){return n.replace(/([A-Z])/g,"-$1").toLowerCase()}for(const n in s){const a=s[n],r=i(n);if(o(a)){e.style.removeProperty(r);continue}const c=a.includes("!important"),d=a.replace(/\s*!important\s*/,"").trim();e.style.setProperty(r,d,c?"important":"")}}toggleAnimationState(e){return this.element.classList.replace(e?"hide":"show",e?"show":"hide")||this.element.classList.add(e?"show":"hide"),this}insertToastElement(){return this.oldestFirst?this.root.insertBefore(this.element,this.root.firstChild):this.root.lastChild?this.root.insertBefore(this.element,this.root.lastChild.nextSibling):this.root.appendChild(this.element),this}setupAutoHide(){return!o(this.options.duration)&&this.options.duration>0&&f(this,()=>this.hide("timeout")),this}show(){return this.setToastRect().insertToastElement().toggleAnimationState(!0).setupAutoHide(),this}showToast(){return this.show()}removeEventListeners(){return this.mouseOverHandler&&this.element.removeEventListener("mouseover",this.mouseOverHandler),this.mouseLeaveHandler&&this.element.removeEventListener("mouseleave",this.mouseLeaveHandler),this.clickHandler&&this.element.removeEventListener("click",this.clickHandler),this.options.close&&this.closeButton&&this.closeButtonHandler&&this.closeButton.removeEventListener("click",this.closeButtonHandler),this}hide(e="other"){this.element&&(l(this),u.delete(this),this.animationEndHandler=s=>{s.animationName.startsWith("toast-out")&&(this.element.removeEventListener("animationend",this.animationEndHandler),this.element.remove(),this.options.onClose?.call(this,new CustomEvent("toast-close",{detail:{reason:e}})))},this.element.addEventListener("animationend",this.animationEndHandler),this.removeEventListeners().toggleAnimationState(!1))}hideToast(){this.hide("other")}}function T(t){return new y(t)}globalThis.Toast=T;globalThis.Toastify=T;})(); +//# sourceMappingURL=toastify.min.js.map diff --git a/dist/toastify.min.js.map b/dist/toastify.min.js.map new file mode 100644 index 0000000..89e9d62 --- /dev/null +++ b/dist/toastify.min.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../src/toastify.ts"], + "sourcesContent": ["export type Gravity = 'top' | 'bottom';\r\nexport type Position = 'left' | 'center' | 'right';\r\nexport type CloseReason = 'timeout' | 'close-button' | 'other';\r\ntype DebounceOptions = {\r\n immediate?: boolean\r\n}\r\nconst isNull = (obj: unknown): obj is null => obj === null;\r\nconst isUndefined = (obj: unknown): obj is undefined => typeof obj === 'undefined';\r\nconst isNullOrUndefined = (obj: unknown): obj is null | undefined => isUndefined(obj) || isNull(obj);\r\nconst activeToasts = new Set();\r\nconst toastTimeouts = new Map();\r\nconst toastIntervals = new Map();\r\nconst toastContainers = new Map();\r\nfunction debounce any>(\r\n fn: T,\r\n delay: number,\r\n { immediate = false }: DebounceOptions = {}\r\n) {\r\n let timer: ReturnType | null = null\r\n const debounced = function (this: any, ...args: Parameters) {\r\n const callNow = immediate && !timer\r\n if (timer) {\r\n clearTimeout(timer)\r\n }\r\n timer = setTimeout(() => {\r\n timer = null\r\n if (!immediate) {\r\n fn.apply(this, args)\r\n }\r\n }, delay)\r\n if (callNow) {\r\n fn.apply(this, args)\r\n }\r\n } as T & { cancel: () => void }\r\n debounced.cancel = () => {\r\n if (timer) {\r\n clearTimeout(timer)\r\n timer = null\r\n }\r\n }\r\n return debounced\r\n}\r\nconst getContainer = (gravity: Gravity, position: Position): HTMLElement => {\r\n const containerId = `toast-container-${gravity}-${position}`;\r\n if (!toastContainers.has(containerId)) {\r\n const container = document.createElement('div');\r\n container.id = containerId;\r\n container.classList.add(\r\n 'toast-container',\r\n `toast-${gravity}`,\r\n `toast-${position}`\r\n );\r\n document.body.appendChild(container);\r\n toastContainers.set(containerId, container);\r\n }\r\n return toastContainers.get(containerId)!;\r\n};\r\nconst addTimeout = (toast: Toast, callback: () => void): void => {\r\n delTimeout(toast);\r\n const startTime = Date.now();\r\n const duration = toast.options.duration!;\r\n const updateRemainingTime = () => {\r\n const elapsed = Date.now() - startTime;\r\n const remaining = Math.max(0, duration - elapsed);\r\n toast.progress!.style.setProperty('--toast-progress', `${remaining / duration}`);\r\n };\r\n const intervalId = window.setInterval(updateRemainingTime, 20);\r\n const timeoutId = window.setTimeout(() => {\r\n toast.progress!.style.setProperty('--toast-progress', `0`);\r\n callback();\r\n delTimeout(toast);\r\n }, duration);\r\n toastTimeouts.set(toast, timeoutId);\r\n toastIntervals.set(toast, intervalId);\r\n};\r\nconst delTimeout = (toast: Toast): void => {\r\n const timeoutId = toastTimeouts.get(toast);\r\n const intervalId = toastIntervals.get(toast);\r\n\r\n if (!isNullOrUndefined(timeoutId)) {\r\n clearTimeout(timeoutId);\r\n toastTimeouts.delete(toast);\r\n }\r\n if (!isNullOrUndefined(intervalId)) {\r\n clearInterval(intervalId);\r\n toastIntervals.delete(toast);\r\n }\r\n};\r\nconst offscreenContainer = document.createElement('div');\r\noffscreenContainer.classList.add('offscreen-container');\r\ndocument.body.appendChild(offscreenContainer);\r\n\r\nwindow.addEventListener('resize', debounce(() => {\r\n for (const toast of activeToasts) {\r\n toast.setToastRect();\r\n }\r\n}, 100));\r\nexport interface ToastOptions {\r\n root?: Element;\r\n text?: string;\r\n node?: Node;\r\n duration?: number;\r\n close?: boolean;\r\n gravity?: Gravity;\r\n position?: Position;\r\n className?: string | string[];\r\n stopOnFocus?: boolean;\r\n onClose?: (this: Toast, e: CustomEvent<{ reason: CloseReason }>) => void;\r\n onClick?: (this: Toast, e: MouseEvent) => void;\r\n style?: Partial;\r\n oldestFirst?: boolean;\r\n}\r\ninterface Options {\r\n gravity: Gravity;\r\n position: Position;\r\n stopOnFocus: boolean;\r\n oldestFirst: boolean;\r\n text?: string;\r\n node?: Node;\r\n duration?: number;\r\n close?: boolean;\r\n className?: string | string[];\r\n onClose?: (this: Toast, e: CustomEvent<{ reason: CloseReason }>) => void;\r\n onClick?: (this: Toast, e: MouseEvent) => void;\r\n style?: Partial;\r\n}\r\n/**\r\n * Toast\r\n * @example\r\n * new Toast({ text: 'Hello World' }).show();\r\n */\r\nexport class Toast {\r\n private static readonly defaults: Options = {\r\n gravity: 'top',\r\n position: 'right',\r\n stopOnFocus: true,\r\n oldestFirst: true,\r\n };\r\n public options: Options;\r\n public root: Element;\r\n public element: HTMLElement;\r\n\r\n public gravity: Gravity;\r\n public position: Position;\r\n public oldestFirst: boolean;\r\n public stopOnFocus: boolean;\r\n public content?: HTMLDivElement;\r\n public progress?: HTMLDivElement;\r\n\r\n private mouseOverHandler?: () => void;\r\n private mouseLeaveHandler?: () => void;\r\n private closeButtonHandler?: () => void;\r\n private animationEndHandler?: (e: AnimationEvent) => void;\r\n private clickHandler?: (e: MouseEvent) => void;\r\n\r\n private closeButton?: HTMLSpanElement;\r\n\r\n /**\r\n * Create a Toastify instance\r\n * @param options User configuration options\r\n */\r\n constructor(options: ToastOptions) {\r\n this.options = {\r\n ...Toast.defaults,\r\n ...options\r\n };\r\n\r\n this.root = getContainer(this.options.gravity, this.options.position);\r\n this.gravity = this.options.gravity;\r\n this.position = this.options.position;\r\n this.stopOnFocus = this.options.stopOnFocus;\r\n this.oldestFirst = this.options.oldestFirst;\r\n\r\n this.element = document.createElement('div');\r\n this.applyBaseStyles()\r\n .addCloseButton()\r\n .createContent()\r\n .ensureCloseMethod()\r\n .bindEvents();\r\n\r\n activeToasts.add(this);\r\n }\r\n\r\n private applyBaseStyles(): this {\r\n this.element.classList.add('toast');\r\n if (this.options.className) {\r\n const classes = Array.isArray(this.options.className)\r\n ? this.options.className\r\n : [this.options.className];\r\n classes.forEach(cls => this.element.classList.add(cls));\r\n }\r\n return this;\r\n }\r\n\r\n private createContent(): this {\r\n this.content = document.createElement('div');\r\n this.content.classList.add('toast-content');\r\n\r\n if (this.options.text) {\r\n this.content.textContent = this.options.text;\r\n }\r\n if (this.options.node) {\r\n this.content.appendChild(this.options.node);\r\n }\r\n if (this.options.style) {\r\n this.applyStyles(this.content, this.options.style);\r\n }\r\n if (!isNullOrUndefined(this.options.duration) && this.options.duration > 0) {\r\n this.progress = document.createElement('div');\r\n this.progress.classList.add('toast-progress');\r\n this.content.appendChild(this.progress);\r\n console.log(this.content.querySelector('.toast-progress'));\r\n }\r\n\r\n this.element.appendChild(this.content);\r\n return this;\r\n }\r\n\r\n private addCloseButton(): this {\r\n if (this.options.close) {\r\n this.closeButton = document.createElement('span');\r\n this.closeButton.className = 'toast-close';\r\n this.closeButton.textContent = '🗙';\r\n this.closeButtonHandler = () => this.hide('close-button');\r\n this.closeButton.addEventListener('click', this.closeButtonHandler);\r\n this.element.appendChild(this.closeButton);\r\n }\r\n return this;\r\n }\r\n\r\n public setToastRect(): this {\r\n // fix max-height cannot be automatically animated\r\n if (!this.element.classList.contains('show')) offscreenContainer.appendChild(this.element);\r\n this.element.style.removeProperty('--toast-height');\r\n this.element.style.removeProperty('--toast-width');\r\n this.element.style.setProperty('max-height', 'none', 'important');\r\n if (this.position == 'center') this.element.style.setProperty('max-width', `${this.root.getBoundingClientRect().width}px`, 'important');\r\n const { height, width } = this.element.getBoundingClientRect();\r\n this.element.style.setProperty('--toast-height', `${height}px`);\r\n this.element.style.setProperty('--toast-width', `${width}px`);\r\n this.element.style.removeProperty('max-height');\r\n this.element.style.removeProperty('max-width');\r\n if (!this.element.classList.contains('show')) offscreenContainer.removeChild(this.element);\r\n return this;\r\n }\r\n private ensureCloseMethod(): this {\r\n if (isNullOrUndefined(this.options.duration) && isNullOrUndefined(this.options.close) && isNullOrUndefined(this.options.onClick)) {\r\n this.options.onClick = () => this.hide('other');\r\n }\r\n return this;\r\n }\r\n\r\n private bindEvents(): this {\r\n if (this.stopOnFocus && !isNullOrUndefined(this.options.duration) && this.options.duration > 0) {\r\n this.mouseOverHandler = () => delTimeout(this);\r\n this.mouseLeaveHandler = () => addTimeout(this, () => this.hide('timeout'));\r\n this.element.addEventListener('mouseover', this.mouseOverHandler);\r\n this.element.addEventListener('mouseleave', this.mouseLeaveHandler);\r\n }\r\n if (!isNullOrUndefined(this.options.onClick)) {\r\n this.clickHandler = this.options.onClick.bind(this);\r\n this.element.addEventListener('click', this.clickHandler);\r\n }\r\n return this;\r\n }\r\n\r\n private applyStyles(element: HTMLElement, styles: Partial) {\r\n function camelToKebab(str: string): string {\r\n return str.replace(/([A-Z])/g, '-$1').toLowerCase();\r\n }\r\n for (const key in styles) {\r\n const value = styles[key];\r\n const property = camelToKebab(key);\r\n if (isNullOrUndefined(value)) {\r\n element.style.removeProperty(property);\r\n continue;\r\n }\r\n const important = value.includes('!important');\r\n const cleanValue = value.replace(/\\s*!important\\s*/, '').trim();\r\n element.style.setProperty(property, cleanValue, important ? 'important' : '');\r\n }\r\n }\r\n\r\n private toggleAnimationState(animation: boolean): this {\r\n if (!this.element.classList.replace(animation ? 'hide' : 'show', animation ? 'show' : 'hide')) {\r\n this.element.classList.add(animation ? 'show' : 'hide');\r\n }\r\n return this;\r\n }\r\n\r\n private insertToastElement(): this {\r\n if (this.oldestFirst) {\r\n this.root.insertBefore(this.element, this.root.firstChild);\r\n } else {\r\n if (this.root.lastChild) {\r\n this.root.insertBefore(this.element, this.root.lastChild.nextSibling);\r\n } else {\r\n this.root.appendChild(this.element);\r\n }\r\n }\r\n return this;\r\n }\r\n\r\n private setupAutoHide(): this {\r\n if (!isNullOrUndefined(this.options.duration) && this.options.duration > 0) {\r\n addTimeout(this, () => this.hide('timeout'));\r\n }\r\n return this;\r\n }\r\n /**\r\n * Display the Toast notification\r\n * @returns this Instance for method chaining\r\n */\r\n public show(): this {\r\n this.setToastRect()\r\n .insertToastElement()\r\n .toggleAnimationState(true)\r\n .setupAutoHide();\r\n return this;\r\n }\r\n\r\n /**\r\n * @deprecated This function is deprecated. Use the show() instead.\r\n */\r\n public showToast() {\r\n return this.show();\r\n }\r\n\r\n private removeEventListeners(): this {\r\n if (this.mouseOverHandler) {\r\n this.element.removeEventListener('mouseover', this.mouseOverHandler);\r\n }\r\n if (this.mouseLeaveHandler) {\r\n this.element.removeEventListener('mouseleave', this.mouseLeaveHandler);\r\n }\r\n if (this.clickHandler) {\r\n this.element.removeEventListener('click', this.clickHandler);\r\n }\r\n if (this.options.close && this.closeButton && this.closeButtonHandler) {\r\n this.closeButton.removeEventListener('click', this.closeButtonHandler);\r\n }\r\n return this;\r\n }\r\n\r\n /**\r\n * Hide the current Toast with optional close reason\r\n * @param reason The reason for closing (default: 'other')\r\n * Triggers a CSS exit animation and removes the element after the animation completes\r\n */\r\n public hide(reason: CloseReason = 'other'): void {\r\n if (!this.element) return;\r\n delTimeout(this);\r\n activeToasts.delete(this);\r\n this.animationEndHandler = (e: AnimationEvent) => {\r\n if (e.animationName.startsWith('toast-out')) {\r\n this.element.removeEventListener('animationend', this.animationEndHandler!);\r\n this.element.remove();\r\n this.options.onClose?.call(this, new CustomEvent('toast-close', {\r\n detail: { reason }\r\n }));\r\n }\r\n };\r\n this.element.addEventListener('animationend', this.animationEndHandler);\r\n this.removeEventListeners()\r\n .toggleAnimationState(false);\r\n }\r\n\r\n /**\r\n * @deprecated This function is deprecated. Use the hide() instead.\r\n */\r\n public hideToast(): void {\r\n this.hide('other');\r\n }\r\n}\r\n\r\nfunction createToast(options: ToastOptions): Toast {\r\n return new Toast(options);\r\n}\r\n\r\ndeclare global {\r\n function Toast(options: ToastOptions): Toast;\r\n /**\r\n * @deprecated This function is deprecated. Use the Toast() instead.\r\n */\r\n function Toastify(options: ToastOptions): Toast;\r\n}\r\n\r\nglobalThis.Toast = createToast;\r\nglobalThis.Toastify = createToast;\r\n"], + "mappings": "mBAMA,MAAMA,EAAUC,GAA8BA,IAAQ,KAChDC,EAAeD,GAAmC,OAAOA,EAAQ,IACjEE,EAAqBF,GAA0CC,EAAYD,CAAG,GAAKD,EAAOC,CAAG,EAC7FG,EAAe,IAAI,IACnBC,EAAgB,IAAI,IACpBC,EAAiB,IAAI,IACrBC,EAAkB,IAAI,IAC5B,SAASC,EACLC,EACAC,EACA,CAAE,UAAAC,EAAY,EAAM,EAAqB,CAAC,EAC5C,CACE,IAAIC,EAA8C,KAClD,MAAMC,EAAY,YAAwBC,EAAqB,CAC3D,MAAMC,EAAUJ,GAAa,CAACC,EAC1BA,GACA,aAAaA,CAAK,EAEtBA,EAAQ,WAAW,IAAM,CACrBA,EAAQ,KACHD,GACDF,EAAG,MAAM,KAAMK,CAAI,CAE3B,EAAGJ,CAAK,EACJK,GACAN,EAAG,MAAM,KAAMK,CAAI,CAE3B,EACA,OAAAD,EAAU,OAAS,IAAM,CACjBD,IACA,aAAaA,CAAK,EAClBA,EAAQ,KAEhB,EACOC,CACX,CACA,MAAMG,EAAe,CAACC,EAAkBC,IAAoC,CACxE,MAAMC,EAAc,mBAAmBF,CAAO,IAAIC,CAAQ,GAC1D,GAAI,CAACX,EAAgB,IAAIY,CAAW,EAAG,CACnC,MAAMC,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,GAAKD,EACfC,EAAU,UAAU,IAChB,kBACA,SAASH,CAAO,GAChB,SAASC,CAAQ,EACrB,EACA,SAAS,KAAK,YAAYE,CAAS,EACnCb,EAAgB,IAAIY,EAAaC,CAAS,CAC9C,CACA,OAAOb,EAAgB,IAAIY,CAAW,CAC1C,EACME,EAAa,CAACC,EAAcC,IAA+B,CAC7DC,EAAWF,CAAK,EAChB,MAAMG,EAAY,KAAK,IAAI,EACrBC,EAAWJ,EAAM,QAAQ,SACzBK,EAAsB,IAAM,CAC9B,MAAMC,EAAU,KAAK,IAAI,EAAIH,EACvBI,EAAY,KAAK,IAAI,EAAGH,EAAWE,CAAO,EAChDN,EAAM,SAAU,MAAM,YAAY,mBAAoB,GAAGO,EAAYH,CAAQ,EAAE,CACnF,EACMI,EAAa,OAAO,YAAYH,EAAqB,EAAE,EACvDI,EAAY,OAAO,WAAW,IAAM,CACtCT,EAAM,SAAU,MAAM,YAAY,mBAAoB,GAAG,EACzDC,EAAS,EACTC,EAAWF,CAAK,CACpB,EAAGI,CAAQ,EACXrB,EAAc,IAAIiB,EAAOS,CAAS,EAClCzB,EAAe,IAAIgB,EAAOQ,CAAU,CACxC,EACMN,EAAcF,GAAuB,CACvC,MAAMS,EAAY1B,EAAc,IAAIiB,CAAK,EACnCQ,EAAaxB,EAAe,IAAIgB,CAAK,EAEtCnB,EAAkB4B,CAAS,IAC5B,aAAaA,CAAS,EACtB1B,EAAc,OAAOiB,CAAK,GAEzBnB,EAAkB2B,CAAU,IAC7B,cAAcA,CAAU,EACxBxB,EAAe,OAAOgB,CAAK,EAEnC,EACMU,EAAqB,SAAS,cAAc,KAAK,EACvDA,EAAmB,UAAU,IAAI,qBAAqB,EACtD,SAAS,KAAK,YAAYA,CAAkB,EAE5C,OAAO,iBAAiB,SAAUxB,EAAS,IAAM,CAC7C,UAAWc,KAASlB,EAChBkB,EAAM,aAAa,CAE3B,EAAG,GAAG,CAAC,EAmCA,MAAMW,CAAM,CACf,OAAwB,SAAoB,CACxC,QAAS,MACT,SAAU,QACV,YAAa,GACb,YAAa,EACjB,EACO,QACA,KACA,QAEA,QACA,SACA,YACA,YACA,QACA,SAEC,iBACA,kBACA,mBACA,oBACA,aAEA,YAMR,YAAYC,EAAuB,CAC/B,KAAK,QAAU,CACX,GAAGD,EAAM,SACT,GAAGC,CACP,EAEA,KAAK,KAAOlB,EAAa,KAAK,QAAQ,QAAS,KAAK,QAAQ,QAAQ,EACpE,KAAK,QAAU,KAAK,QAAQ,QAC5B,KAAK,SAAW,KAAK,QAAQ,SAC7B,KAAK,YAAc,KAAK,QAAQ,YAChC,KAAK,YAAc,KAAK,QAAQ,YAEhC,KAAK,QAAU,SAAS,cAAc,KAAK,EAC3C,KAAK,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,WAAW,EAEhBZ,EAAa,IAAI,IAAI,CACzB,CAEQ,iBAAwB,CAC5B,YAAK,QAAQ,UAAU,IAAI,OAAO,EAC9B,KAAK,QAAQ,YACG,MAAM,QAAQ,KAAK,QAAQ,SAAS,EAC9C,KAAK,QAAQ,UACb,CAAC,KAAK,QAAQ,SAAS,GACrB,QAAQ+B,GAAO,KAAK,QAAQ,UAAU,IAAIA,CAAG,CAAC,EAEnD,IACX,CAEQ,eAAsB,CAC1B,YAAK,QAAU,SAAS,cAAc,KAAK,EAC3C,KAAK,QAAQ,UAAU,IAAI,eAAe,EAEtC,KAAK,QAAQ,OACb,KAAK,QAAQ,YAAc,KAAK,QAAQ,MAExC,KAAK,QAAQ,MACb,KAAK,QAAQ,YAAY,KAAK,QAAQ,IAAI,EAE1C,KAAK,QAAQ,OACb,KAAK,YAAY,KAAK,QAAS,KAAK,QAAQ,KAAK,EAEjD,CAAChC,EAAkB,KAAK,QAAQ,QAAQ,GAAK,KAAK,QAAQ,SAAW,IACrE,KAAK,SAAW,SAAS,cAAc,KAAK,EAC5C,KAAK,SAAS,UAAU,IAAI,gBAAgB,EAC5C,KAAK,QAAQ,YAAY,KAAK,QAAQ,EACtC,QAAQ,IAAI,KAAK,QAAQ,cAAc,iBAAiB,CAAC,GAG7D,KAAK,QAAQ,YAAY,KAAK,OAAO,EAC9B,IACX,CAEQ,gBAAuB,CAC3B,OAAI,KAAK,QAAQ,QACb,KAAK,YAAc,SAAS,cAAc,MAAM,EAChD,KAAK,YAAY,UAAY,cAC7B,KAAK,YAAY,YAAc,KAC/B,KAAK,mBAAqB,IAAM,KAAK,KAAK,cAAc,EACxD,KAAK,YAAY,iBAAiB,QAAS,KAAK,kBAAkB,EAClE,KAAK,QAAQ,YAAY,KAAK,WAAW,GAEtC,IACX,CAEO,cAAqB,CAEnB,KAAK,QAAQ,UAAU,SAAS,MAAM,GAAG6B,EAAmB,YAAY,KAAK,OAAO,EACzF,KAAK,QAAQ,MAAM,eAAe,gBAAgB,EAClD,KAAK,QAAQ,MAAM,eAAe,eAAe,EACjD,KAAK,QAAQ,MAAM,YAAY,aAAc,OAAQ,WAAW,EAC5D,KAAK,UAAY,UAAU,KAAK,QAAQ,MAAM,YAAY,YAAa,GAAG,KAAK,KAAK,sBAAsB,EAAE,KAAK,KAAM,WAAW,EACtI,KAAM,CAAE,OAAAI,EAAQ,MAAAC,CAAM,EAAI,KAAK,QAAQ,sBAAsB,EAC7D,YAAK,QAAQ,MAAM,YAAY,iBAAkB,GAAGD,CAAM,IAAI,EAC9D,KAAK,QAAQ,MAAM,YAAY,gBAAiB,GAAGC,CAAK,IAAI,EAC5D,KAAK,QAAQ,MAAM,eAAe,YAAY,EAC9C,KAAK,QAAQ,MAAM,eAAe,WAAW,EACxC,KAAK,QAAQ,UAAU,SAAS,MAAM,GAAGL,EAAmB,YAAY,KAAK,OAAO,EAClF,IACX,CACQ,mBAA0B,CAC9B,OAAI7B,EAAkB,KAAK,QAAQ,QAAQ,GAAKA,EAAkB,KAAK,QAAQ,KAAK,GAAKA,EAAkB,KAAK,QAAQ,OAAO,IAC3H,KAAK,QAAQ,QAAU,IAAM,KAAK,KAAK,OAAO,GAE3C,IACX,CAEQ,YAAmB,CACvB,OAAI,KAAK,aAAe,CAACA,EAAkB,KAAK,QAAQ,QAAQ,GAAK,KAAK,QAAQ,SAAW,IACzF,KAAK,iBAAmB,IAAMqB,EAAW,IAAI,EAC7C,KAAK,kBAAoB,IAAMH,EAAW,KAAM,IAAM,KAAK,KAAK,SAAS,CAAC,EAC1E,KAAK,QAAQ,iBAAiB,YAAa,KAAK,gBAAgB,EAChE,KAAK,QAAQ,iBAAiB,aAAc,KAAK,iBAAiB,GAEjElB,EAAkB,KAAK,QAAQ,OAAO,IACvC,KAAK,aAAe,KAAK,QAAQ,QAAQ,KAAK,IAAI,EAClD,KAAK,QAAQ,iBAAiB,QAAS,KAAK,YAAY,GAErD,IACX,CAEQ,YAAYmC,EAAsBC,EAAsC,CAC5E,SAASC,EAAaC,EAAqB,CACvC,OAAOA,EAAI,QAAQ,WAAY,KAAK,EAAE,YAAY,CACtD,CACA,UAAWC,KAAOH,EAAQ,CACtB,MAAMI,EAAQJ,EAAOG,CAAG,EAClBE,EAAWJ,EAAaE,CAAG,EACjC,GAAIvC,EAAkBwC,CAAK,EAAG,CAC1BL,EAAQ,MAAM,eAAeM,CAAQ,EACrC,QACJ,CACA,MAAMC,EAAYF,EAAM,SAAS,YAAY,EACvCG,EAAaH,EAAM,QAAQ,mBAAoB,EAAE,EAAE,KAAK,EAC9DL,EAAQ,MAAM,YAAYM,EAAUE,EAAYD,EAAY,YAAc,EAAE,CAChF,CACJ,CAEQ,qBAAqBE,EAA0B,CACnD,OAAK,KAAK,QAAQ,UAAU,QAAQA,EAAY,OAAS,OAAQA,EAAY,OAAS,MAAM,GACxF,KAAK,QAAQ,UAAU,IAAIA,EAAY,OAAS,MAAM,EAEnD,IACX,CAEQ,oBAA2B,CAC/B,OAAI,KAAK,YACL,KAAK,KAAK,aAAa,KAAK,QAAS,KAAK,KAAK,UAAU,EAErD,KAAK,KAAK,UACV,KAAK,KAAK,aAAa,KAAK,QAAS,KAAK,KAAK,UAAU,WAAW,EAEpE,KAAK,KAAK,YAAY,KAAK,OAAO,EAGnC,IACX,CAEQ,eAAsB,CAC1B,MAAI,CAAC5C,EAAkB,KAAK,QAAQ,QAAQ,GAAK,KAAK,QAAQ,SAAW,GACrEkB,EAAW,KAAM,IAAM,KAAK,KAAK,SAAS,CAAC,EAExC,IACX,CAKO,MAAa,CAChB,YAAK,aAAa,EACb,mBAAmB,EACnB,qBAAqB,EAAI,EACzB,cAAc,EACZ,IACX,CAKO,WAAY,CACf,OAAO,KAAK,KAAK,CACrB,CAEQ,sBAA6B,CACjC,OAAI,KAAK,kBACL,KAAK,QAAQ,oBAAoB,YAAa,KAAK,gBAAgB,EAEnE,KAAK,mBACL,KAAK,QAAQ,oBAAoB,aAAc,KAAK,iBAAiB,EAErE,KAAK,cACL,KAAK,QAAQ,oBAAoB,QAAS,KAAK,YAAY,EAE3D,KAAK,QAAQ,OAAS,KAAK,aAAe,KAAK,oBAC/C,KAAK,YAAY,oBAAoB,QAAS,KAAK,kBAAkB,EAElE,IACX,CAOO,KAAK2B,EAAsB,QAAe,CACxC,KAAK,UACVxB,EAAW,IAAI,EACfpB,EAAa,OAAO,IAAI,EACxB,KAAK,oBAAuB6C,GAAsB,CAC1CA,EAAE,cAAc,WAAW,WAAW,IACtC,KAAK,QAAQ,oBAAoB,eAAgB,KAAK,mBAAoB,EAC1E,KAAK,QAAQ,OAAO,EACpB,KAAK,QAAQ,SAAS,KAAK,KAAM,IAAI,YAAY,cAAe,CAC5D,OAAQ,CAAE,OAAAD,CAAO,CACrB,CAAC,CAAC,EAEV,EACA,KAAK,QAAQ,iBAAiB,eAAgB,KAAK,mBAAmB,EACtE,KAAK,qBAAqB,EACrB,qBAAqB,EAAK,EACnC,CAKO,WAAkB,CACrB,KAAK,KAAK,OAAO,CACrB,CACJ,CAEA,SAASE,EAAYhB,EAA8B,CAC/C,OAAO,IAAID,EAAMC,CAAO,CAC5B,CAUA,WAAW,MAAQgB,EACnB,WAAW,SAAWA", + "names": ["isNull", "obj", "isUndefined", "isNullOrUndefined", "activeToasts", "toastTimeouts", "toastIntervals", "toastContainers", "debounce", "fn", "delay", "immediate", "timer", "debounced", "args", "callNow", "getContainer", "gravity", "position", "containerId", "container", "addTimeout", "toast", "callback", "delTimeout", "startTime", "duration", "updateRemainingTime", "elapsed", "remaining", "intervalId", "timeoutId", "offscreenContainer", "Toast", "options", "cls", "height", "width", "element", "styles", "camelToKebab", "str", "key", "value", "property", "important", "cleanValue", "animation", "reason", "e", "createToast"] +} diff --git a/example/script.js b/example/script.js index 8d290ff..a080897 100644 --- a/example/script.js +++ b/example/script.js @@ -1,36 +1,38 @@ var bgColors = [ - "linear-gradient(to right, #00b09b, #96c93d)", - "linear-gradient(to right, #ff5f6d, #ffc371)", - ], - i = 0; + "linear-gradient(to right, #00b09b, #96c93d)", + "linear-gradient(to right, #ff5f6d, #ffc371)", +]; +var gravity = ["top", "bottom"]; +var position = ["left", "center", "right"]; -Toastify({ +Toast({ text: "Hi", - duration: 4500, - destination: "https://github.com/apvarun/toastify-js", - newWindow: true, gravity: "top", position: 'left', -}).showToast(); + onClick(e) { + console.log(e); + window.open("https://github.com/apvarun/toastify-js"); + this.hide(); + } +}).show(); -setTimeout(function() { - Toastify({ +setTimeout(function () { + Toast({ text: "Simple JavaScript Toasts", gravity: "top", position: 'center', style: { background: '#0f3443' } - }).showToast(); + }).show(); }, 1000); // Options for the toast var options = { text: "Happy toasting!", duration: 2500, - callback: function() { + onClose() { console.log("Toast hidden"); - Toastify.reposition(); }, close: true, style: { @@ -39,15 +41,15 @@ var options = { }; // Initializing the toast -var myToast = Toastify(options); +var myToast = Toast(options); // Toast after delay -setTimeout(function() { - myToast.showToast(); +setTimeout(function () { + myToast.show(); }, 4500); -setTimeout(function() { - Toastify({ +setTimeout(function () { + Toast({ text: "Highly customizable", gravity: "bottom", position: 'left', @@ -55,18 +57,21 @@ setTimeout(function() { style: { background: "linear-gradient(to right, #ff5f6d, #ffc371)", } - }).showToast(); + }).show(); }, 3000); -// Displaying toast on manual action `Try` -document.getElementById("new-toast").addEventListener("click", function() { - Toastify({ - text: "I am a toast", + +document.getElementById("new-toast").addEventListener("click", function () { + let g = gravity.at(Math.floor(Math.random() * gravity.length)) + let p = position.at(Math.floor(Math.random() * position.length)) + Toast({ + text: `I am a ${g} ${p} toast`, duration: 3000, - close: i % 3 ? true : false, + gravity: g, + position: p, + close: Math.random() >= 0.5, style: { - background: bgColors[i % 2], + background: bgColors[Math.floor(Math.random() * bgColors.length)], } - }).showToast(); - i++; + }).show(); }); diff --git a/index.html b/index.html index 49174ee..8f741b5 100644 --- a/index.html +++ b/index.html @@ -10,7 +10,7 @@ - + @@ -28,10 +28,10 @@

Toastify JS

Usage

-

Toastify({

+

Toast({

text: "This is a toast",

duration: 3000

-

}).showToast();

+

}).show();

@@ -42,7 +42,7 @@

Usage

- +