Files
MetonaToast/src/index.js
T

277 lines
6.1 KiB
JavaScript

/**
* MetonaToast - 轻量级Toast通知库
* @module metona-toast
* @version 2.0.0
* @author metona
* @description 轻量、零依赖、精致美观的Toast通知库。单文件,开箱即用。
* @license MIT
*/
import { meToast, Toast } from './core.js';
import { animationUtils } from './animations.js';
import { themeUtils } from './themes.js';
import { i18nUtils } from './i18n.js';
import { pluginUtils, presetPlugins } from './plugins.js';
import { DEFAULTS } from './constants.js';
// 版本信息
const VERSION = '2.0.0';
/**
* 主对象增强
*/
const enhancedMeToast = {
...meToast,
version: VERSION,
animations: animationUtils,
themes: themeUtils,
i18n: i18nUtils,
plugins: pluginUtils,
presetPlugins,
/**
* 安装插件,并连接必要的生命周期钩子
*/
use(plugin, options = {}) {
if (typeof plugin === 'string') {
const preset = presetPlugins[plugin];
if (!preset) {
console.warn(`Preset plugin "${plugin}" not found`);
return this;
}
this.plugins.register(plugin, { ...preset, ...options });
// 连接插件钩子
if (plugin === 'accessibility') {
Toast.on('afterShow', (toast) => preset.announce(toast));
}
if (plugin === 'persistence') {
const saved = preset.install();
if (saved) this.configure(saved);
Toast.on('afterClose', () => { preset.save(this.getConfig()); });
}
} else if (plugin && typeof plugin === 'object') {
const name = plugin.name || 'custom';
this.plugins.register(name, { ...plugin, ...options });
}
return this;
},
/**
* 初始化
*/
init(options = {}) {
if (options.config) {
this.configure(options.config);
}
if (options.theme) {
this.themes.switchTheme(options.theme);
}
if (options.locale) {
this.i18n.switchLocale(options.locale);
}
if (options.plugins && Array.isArray(options.plugins)) {
options.plugins.forEach((plugin) => {
this.use(plugin);
});
}
return this;
},
/**
* 销毁
*/
destroy() {
this.dismiss();
if (this.plugins && typeof this.plugins.destroy === 'function') {
this.plugins.destroy();
}
if (this.themes) {
if (typeof this.themes.clearThemeListeners === 'function') {
this.themes.clearThemeListeners();
}
if (typeof this.themes.unwatchSystemTheme === 'function') {
this.themes.unwatchSystemTheme();
}
}
if (this.i18n && typeof this.i18n.clearLocaleListeners === 'function') {
this.i18n.clearLocaleListeners();
}
if (this.animations && typeof this.animations.cancelAll === 'function') {
this.animations.cancelAll();
}
if (typeof document !== 'undefined') {
const containers = document.querySelectorAll('.met-container');
containers.forEach((c) => c.parentNode && c.parentNode.removeChild(c));
const style = document.getElementById('metona-toast-styles');
if (style) style.parentNode.removeChild(style);
}
this._toasts.clear();
},
/**
* 获取状态
*/
getStatus() {
return {
version: VERSION,
toasts: this._toasts.size,
theme: this.themes?.getCurrentTheme?.() || 'auto',
locale: this.i18n?.getCurrentLocale?.() || 'zh-CN',
plugins: this.plugins?.getNames?.() || [],
animations: this.animations?.getActiveCount?.() || 0,
};
},
/**
* 获取配置
*/
getConfig() {
return { ...this._config };
},
/**
* 更新配置
*/
updateConfig(config) {
if (config && typeof config === 'object') {
this._config = { ...this._config, ...config };
}
return this;
},
/**
* 重置配置
*/
resetConfig() {
this._config = { ...DEFAULTS };
return this;
},
/**
* 获取Toast列表
*/
getToasts() {
return Array.from(this._toasts.values());
},
/**
* 检查是否有Toast
*/
hasToasts() {
return this._toasts.size > 0;
},
/**
* 获取Toast
*/
getToast(id) {
if (!id) return null;
return this._toasts.get(id) || null;
},
/**
* 关闭所有Toast
*/
closeAll() {
this._toasts.forEach((t) => t.close());
},
/**
* 清除所有Toast
*/
clearAll() {
this._toasts.forEach((t) => t.close());
},
/**
* 暂停所有Toast
*/
pauseAll() {
this._toasts.forEach((t) => t._pause());
},
/**
* 恢复所有Toast
*/
resumeAll() {
this._toasts.forEach((t) => t._resume());
},
/**
* 更新所有Toast
*/
updateAll(partial) {
if (partial && typeof partial === 'object') {
this._toasts.forEach((t) => t.update(partial));
}
},
/**
* 查找Toast
*/
findToasts(predicate) {
if (typeof predicate !== 'function') return [];
return Array.from(this._toasts.values()).filter(predicate);
},
/**
* 按类型查找Toast
*/
findByType(type) {
return this.findToasts((t) => t.type === type);
},
/**
* 按位置查找Toast
*/
findByPosition(position) {
return this.findToasts((t) => t.config.position === position);
},
};
// 初始化主题和国际化
if (typeof themeUtils.initTheme === 'function') {
themeUtils.initTheme();
}
if (typeof i18nUtils.initI18n === 'function') {
i18nUtils.initI18n();
}
// 浏览器环境全局注册
if (typeof window !== 'undefined') {
window.MeToast = enhancedMeToast;
window.Met = enhancedMeToast;
window.metonaToast = enhancedMeToast;
// Notification API — 页面不可见时自动发送系统通知
enhancedMeToast._notify = (toast) => {
if (typeof Notification === 'undefined' || Notification.permission !== 'granted') return;
if (!document.hidden) return;
try {
new Notification(toast.title || toast.type, { body: toast.message, icon: '/favicon.ico' });
} catch (_) {}
};
Toast.on('afterShow', (toast) => {
if (toast.config.notifyWhenHidden) enhancedMeToast._notify(toast);
});
}
// 导出
export default enhancedMeToast;
export { enhancedMeToast as meToast, enhancedMeToast as Met, enhancedMeToast as MeToast, Toast, VERSION };