release: v0.3.0 — 自定义动画真实生效、max超限修复、钩子系统完整化、destroy全量清理

- 自定义动画:animations.register() 注册的动画动态注入 keyframes 真实生效(此前仅存 Map 实际 fallback slide)
- max 超限:通过实例注册表真正 close() 最早的 toast(此前仅删内存记录,DOM 残留)
- 钩子收敛:beforeClose/beforeUpdate 支持返回 false 拦截;接入 click/hover/dragStart/dragEnd/animationStart/animationEnd/progressStart/progressEnd/configChange/themeChange/localeChange/beforeInit/afterInit/beforeDestroy/afterDestroy;HOOK_NAMES 移除永不触发的声明
- destroy() 全量清理:hooks、实例注册表、全部 metona-toast-* 样式标签;动画注册表真正清空
- applyThemeVariables 重复注入修复;init() 支持插件对象并复活 _destroyed;AnimationConfig 类型放宽
- VERSION 统一到 constants.ts 唯一维护;删除失效 scripts;新增 .gitattributes 统一 LF
- docs.html 补 v0.2.1 新 API 文档;CHANGELOG 更新;测试 309 用例全过
This commit is contained in:
tianhao
2026-08-08 14:23:41 +08:00
parent cb8dd623db
commit 2937ce5e2d
30 changed files with 1098 additions and 372 deletions
+26 -12
View File
@@ -1,11 +1,11 @@
/**
* MetonaToast API — meToast 核心 API 对象
* @module api
* @version 0.2.1
* @version 0.3.0
*/
import { Toast, _containerCache } from './toast.js';
import { DEFAULTS } from './constants.js';
import { DEFAULTS, VERSION } from './constants.js';
import { escapeHTML } from './utils.js';
import { t, setCurrentLocale } from './i18n.js';
import { applyTheme } from './themes.js';
@@ -48,16 +48,13 @@ const normalizeArgs = (args: unknown[], defaultType = 'default'): ToastOptions =
};
};
/** 版本号常量 */
const VERSION = '0.2.1';
/**
* meToast API 对象
*/
const meToast: MeToast = {
_toasts: new Map<string, ToastInstance>(),
_config: { ...DEFAULTS } as unknown as ToastConfig,
version: '0.2.1',
version: VERSION,
configure(opts: Partial<ToastConfig>): MeToast {
if (!opts || typeof opts !== 'object') return this;
@@ -71,6 +68,7 @@ const meToast: MeToast = {
setCurrentLocale(opts.locale);
}
Toast.trigger('configChange');
return this;
},
@@ -588,6 +586,9 @@ const meToast: MeToast = {
// ====== 以下方法依赖子模块(themes/i18n/plugins/animations),由 index.ts 注入 ======
init(options: InitOptions = {}): MeToast {
Toast.trigger('beforeInit');
this._destroyed = false;
if (options.config) {
this.configure(options.config);
}
@@ -599,9 +600,11 @@ const meToast: MeToast = {
}
if (options.plugins && Array.isArray(options.plugins)) {
options.plugins.forEach((p) => {
this.use(p as string);
this.use(p);
});
}
Toast.trigger('afterInit');
return this;
},
@@ -623,6 +626,7 @@ const meToast: MeToast = {
updateConfig(config: Partial<ToastConfig>): MeToast {
if (config && typeof config === 'object') {
Object.assign(this._config, config);
Toast.trigger('configChange');
}
return this;
},
@@ -631,6 +635,7 @@ const meToast: MeToast = {
const keys = Object.keys(this._config);
keys.forEach(k => delete (this._config as Record<string, unknown>)[k]);
Object.assign(this._config, DEFAULTS);
Toast.trigger('configChange');
return this;
},
@@ -670,6 +675,8 @@ const meToast: MeToast = {
destroy(): void {
if (this._destroyed) return;
this._destroyed = true;
Toast.trigger('beforeDestroy');
this.dismiss();
// 清理子模块
@@ -687,21 +694,28 @@ const meToast: MeToast = {
if (this.i18n && typeof this.i18n.clearLocaleListeners === 'function') {
this.i18n.clearLocaleListeners();
}
if (this.animations && typeof this.animations.cancelAll === 'function') {
this.animations.cancelAll();
if (this.animations && typeof this.animations.destroy === 'function') {
this.animations.destroy();
}
// 清理 DOM
// 清理 DOM 与静态资源
if (typeof document !== 'undefined') {
const containers = document.querySelectorAll('.met-container');
containers.forEach((c) => { if (c.parentNode) c.parentNode.removeChild(c); });
const style = document.getElementById('metona-toast-styles');
if (style && style.parentNode) style.parentNode.removeChild(style);
['metona-toast-styles', 'metona-toast-theme-css', 'metona-toast-custom-styles', 'metona-toast-anim-styles'].forEach((id) => {
const el = document.getElementById(id);
if (el && el.parentNode) el.parentNode.removeChild(el);
});
}
this._toasts.clear();
_containerCache.clear();
Toast._registry.clear();
// afterDestroy 必须在清理 hooks 之前触发
Toast.trigger('afterDestroy');
Toast._hooks.clear();
},
// 子模块引用(由 index.ts 注入实际实现)