chore: v0.1.2 — 全面修复、优化与增强
修复: - core.js: _resume 计时器 BUG (startedAt 被 _startTimer 覆盖导致暂停恢复失效) - plugins.js: register 在 install 前展开导致 handler 实例丢失 - locales.js: zh-CN/en-US 大量重复 key 覆盖正确翻译值 - core.js: configure 改为原地更新避免 _config 引用断裂 优化: - core.js: update() 类型变更时同步更新 DOM 类名和进度条颜色 - animations.js: getActiveCount 返回已注册动画数量 - themes.js: 移除 presetThemes 死代码和重复注册循环 - constants.js: THEMES.auto 从字符串改为规范化对象 - index.js: destroy 添加防重复调用保护 增强: - core.js: 新增 onError 全局错误回调,钩子异常和定时器错误可被外部捕获 - styles.js: _resume 校准时间基准补偿注释 - 139 tests 全部通过
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@metona-team/metona-toast",
|
"name": "@metona-team/metona-toast",
|
||||||
"version": "0.1.1",
|
"version": "0.1.2",
|
||||||
"description": "轻量、零依赖、精致美观的Toast通知库。单文件,开箱即用。",
|
"description": "轻量、零依赖、精致美观的Toast通知库。单文件,开箱即用。",
|
||||||
"main": "dist/metona-toast.js",
|
"main": "dist/metona-toast.js",
|
||||||
"module": "src/index.js",
|
"module": "src/index.js",
|
||||||
|
|||||||
+1
-1
@@ -273,7 +273,7 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
MetonaToast v0.1.1 · MIT · <a href="index.html">首页</a> · <a href="docs.html">文档</a> · <a href="https://git.metona.cn/MetonaTeam/MetonaToast">Gitea</a>
|
MetonaToast v0.1.2 · MIT · <a href="index.html">首页</a> · <a href="docs.html">文档</a> · <a href="https://git.metona.cn/MetonaTeam/MetonaToast">Gitea</a>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="../dist/metona-toast.js"></script>
|
<script src="../dist/metona-toast.js"></script>
|
||||||
|
|||||||
+2
-1
@@ -87,7 +87,7 @@
|
|||||||
<main class="main">
|
<main class="main">
|
||||||
|
|
||||||
<h1>API 文档</h1>
|
<h1>API 文档</h1>
|
||||||
<p>MetonaToast v0.1.1 完整 API 参考。所有基础通知方法(show/success/error/warning/info/loading)支持两种调用形式,均可传入任何 <a href="#config">配置项</a> 作为可选第二参数。</p>
|
<p>MetonaToast v0.1.2 完整 API 参考。所有基础通知方法(show/success/error/warning/info/loading)支持两种调用形式,均可传入任何 <a href="#config">配置项</a> 作为可选第二参数。</p>
|
||||||
|
|
||||||
<!-- ===== 基础通知 ===== -->
|
<!-- ===== 基础通知 ===== -->
|
||||||
<h2 id="show">show(message, opts?)</h2>
|
<h2 id="show">show(message, opts?)</h2>
|
||||||
@@ -434,6 +434,7 @@ MeToast.<span class="fn">use</span>(<span class="s">'accessibility'</span>); <sp
|
|||||||
<tr><td>resetTimerOnUpdate</td><td>boolean</td><td>false</td><td>调用 update() 时重置 duration 倒计时</td></tr>
|
<tr><td>resetTimerOnUpdate</td><td>boolean</td><td>false</td><td>调用 update() 时重置 duration 倒计时</td></tr>
|
||||||
<tr><td>notifyWhenHidden</td><td>boolean</td><td>false</td><td>页面不可见时自动通过 Notification API 发送系统通知</td></tr>
|
<tr><td>notifyWhenHidden</td><td>boolean</td><td>false</td><td>页面不可见时自动通过 Notification API 发送系统通知</td></tr>
|
||||||
<tr><td>render</td><td>function</td><td>—</td><td>自定义渲染函数 <code>(toast) => htmlString</code>,完全接管 DOM 构建</td></tr>
|
<tr><td>render</td><td>function</td><td>—</td><td>自定义渲染函数 <code>(toast) => htmlString</code>,完全接管 DOM 构建</td></tr>
|
||||||
|
<tr><td>onError</td><td>function</td><td>—</td><td>全局错误回调 <code>({ hook, source, error, toast }) => void</code>,钩子异常或定时器错误时触发</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h2 id="callbacks">回调函数</h2>
|
<h2 id="callbacks">回调函数</h2>
|
||||||
|
|||||||
+1
-1
@@ -237,7 +237,7 @@ orderGroup.<span class="fn">dismiss</span>(); <span class="cm">// 一键关闭
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<p>MetonaToast v0.1.1 · MIT License · <a href="https://git.metona.cn/MetonaTeam/MetonaToast">Gitea</a></p>
|
<p>MetonaToast v0.1.2 · MIT License · <a href="https://git.metona.cn/MetonaTeam/MetonaToast">Gitea</a></p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="../dist/metona-toast.js"></script>
|
<script src="../dist/metona-toast.js"></script>
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast Animations - 动画管理 v0.1.1
|
* MetonaToast Animations - 动画管理 v0.1.2
|
||||||
* @module animations
|
* @module animations
|
||||||
* @description 动画注册与管理,移除未使用的 Web Animations API dead code
|
* @description 动画注册与管理,移除未使用的 Web Animations API dead code
|
||||||
*/
|
*/
|
||||||
@@ -61,11 +61,11 @@ export const animationUtils = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取活动动画数量(兼容API,当前CSS动画不跟踪活动实例)
|
* 获取已注册动画总数
|
||||||
* @returns {number} 动画数量
|
* @returns {number} 已注册动画数量
|
||||||
*/
|
*/
|
||||||
getActiveCount() {
|
getActiveCount() {
|
||||||
return 0;
|
return animationMap.size;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+13
-2
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast Constants - 常量定义
|
* MetonaToast Constants - 常量定义
|
||||||
* @module constants
|
* @module constants
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
* @description 默认配置、颜色、动画、主题等常量
|
* @description 默认配置、颜色、动画、主题等常量
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -49,6 +49,9 @@ export const DEFAULTS = Object.freeze({
|
|||||||
resetTimerOnUpdate: false,
|
resetTimerOnUpdate: false,
|
||||||
notifyWhenHidden: false,
|
notifyWhenHidden: false,
|
||||||
|
|
||||||
|
// 错误处理
|
||||||
|
onError: null,
|
||||||
|
|
||||||
// 国际化
|
// 国际化
|
||||||
locale: 'zh-CN',
|
locale: 'zh-CN',
|
||||||
|
|
||||||
@@ -267,7 +270,15 @@ export const THEMES = {
|
|||||||
progressBg: 'rgba(255, 255, 255, 0.08)',
|
progressBg: 'rgba(255, 255, 255, 0.08)',
|
||||||
closeHoverBg: 'rgba(255, 255, 255, 0.08)',
|
closeHoverBg: 'rgba(255, 255, 255, 0.08)',
|
||||||
},
|
},
|
||||||
auto: 'auto',
|
auto: {
|
||||||
|
bg: 'auto',
|
||||||
|
text: 'auto',
|
||||||
|
border: 'auto',
|
||||||
|
shadow: 'auto',
|
||||||
|
hoverShadow: 'auto',
|
||||||
|
progressBg: 'auto',
|
||||||
|
closeHoverBg: 'auto',
|
||||||
|
},
|
||||||
warm: {
|
warm: {
|
||||||
bg: 'rgba(255, 251, 235, 0.96)',
|
bg: 'rgba(255, 251, 235, 0.96)',
|
||||||
text: '#78350f',
|
text: '#78350f',
|
||||||
|
|||||||
+43
-6
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast Core - 核心Toast逻辑
|
* MetonaToast Core - 核心Toast逻辑
|
||||||
* @module core
|
* @module core
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
* @description 重构后的核心模块,包含Toast类的优化实现
|
* @description 重构后的核心模块,包含Toast类的优化实现
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -68,7 +68,15 @@ class Toast {
|
|||||||
}
|
}
|
||||||
static trigger(name, toast) {
|
static trigger(name, toast) {
|
||||||
const list = this._hooks.get(name);
|
const list = this._hooks.get(name);
|
||||||
if (list) list.forEach(fn => { try { fn(toast); } catch (e) { console.error('Hook error:', name, e); } });
|
if (list) list.forEach(fn => {
|
||||||
|
try { fn(toast); }
|
||||||
|
catch (e) {
|
||||||
|
console.error('Hook error:', name, e);
|
||||||
|
if (meToast._config.onError) {
|
||||||
|
try { meToast._config.onError({ hook: name, error: e, toast }); } catch (_) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(opts) {
|
constructor(opts) {
|
||||||
@@ -392,15 +400,19 @@ class Toast {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_startTimer() {
|
_startTimer(resuming = false) {
|
||||||
if (this.config.duration <= 0) return;
|
if (this.config.duration <= 0) return;
|
||||||
|
|
||||||
|
// 仅在首次启动时重置时间基准;resume 场景由 _resume() 预先调整 startedAt
|
||||||
|
if (!resuming) {
|
||||||
this.startedAt = Date.now();
|
this.startedAt = Date.now();
|
||||||
this.remaining = this.config.duration;
|
this.remaining = this.config.duration;
|
||||||
|
}
|
||||||
|
|
||||||
const tick = () => {
|
const tick = () => {
|
||||||
if (this.paused || this.closing) return;
|
if (this.paused || this.closing) return;
|
||||||
|
|
||||||
|
try {
|
||||||
const elapsed = Date.now() - this.startedAt;
|
const elapsed = Date.now() - this.startedAt;
|
||||||
this.remaining = Math.max(0, this.config.duration - elapsed);
|
this.remaining = Math.max(0, this.config.duration - elapsed);
|
||||||
|
|
||||||
@@ -415,6 +427,12 @@ class Toast {
|
|||||||
this.close();
|
this.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Timer tick error:', e);
|
||||||
|
if (meToast._config.onError) {
|
||||||
|
try { meToast._config.onError({ source: 'timer', error: e, toast: this }); } catch (_) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.rafId = requestAnimationFrame(tick);
|
this.rafId = requestAnimationFrame(tick);
|
||||||
};
|
};
|
||||||
@@ -432,12 +450,14 @@ class Toast {
|
|||||||
_resume() {
|
_resume() {
|
||||||
if (!this.paused) return;
|
if (!this.paused) return;
|
||||||
this.paused = false;
|
this.paused = false;
|
||||||
|
// 校准时间基准,补偿暂停期间经过的时间
|
||||||
this.startedAt = Date.now() - (this.config.duration - this.remaining);
|
this.startedAt = Date.now() - (this.config.duration - this.remaining);
|
||||||
this._startTimer();
|
this._startTimer(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(partial) {
|
update(partial) {
|
||||||
Toast.trigger('beforeUpdate', this);
|
Toast.trigger('beforeUpdate', this);
|
||||||
|
const typeChanged = partial.type && partial.type !== this.type;
|
||||||
if (partial.type) this.type = partial.type;
|
if (partial.type) this.type = partial.type;
|
||||||
if (partial.title !== undefined) this.title = partial.title;
|
if (partial.title !== undefined) this.title = partial.title;
|
||||||
if (partial.message !== undefined) this.message = partial.message;
|
if (partial.message !== undefined) this.message = partial.message;
|
||||||
@@ -445,6 +465,22 @@ class Toast {
|
|||||||
|
|
||||||
if (!this.el) { Toast.trigger('afterUpdate', this); return this; }
|
if (!this.el) { Toast.trigger('afterUpdate', this); return this; }
|
||||||
|
|
||||||
|
// 类型变更时同步更新 DOM 类名、边框颜色和进度条颜色
|
||||||
|
if (typeChanged) {
|
||||||
|
const typeClasses = ['met-success', 'met-error', 'met-warning', 'met-info', 'met-loading', 'met-default'];
|
||||||
|
typeClasses.forEach(c => this.el.classList.remove(c));
|
||||||
|
this.el.classList.add(`met-${this.type}`);
|
||||||
|
if (this.barEl) {
|
||||||
|
const c = (TYPE_COLORS[this.type] || TYPE_COLORS.default);
|
||||||
|
this.barEl.style.background = c.fg;
|
||||||
|
}
|
||||||
|
const side = this.el.querySelector('.met-side');
|
||||||
|
if (side) {
|
||||||
|
const c = (TYPE_COLORS[this.type] || TYPE_COLORS.default);
|
||||||
|
side.style.background = c.fg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const content = this.el.querySelector('.met-content');
|
const content = this.el.querySelector('.met-content');
|
||||||
if (content) {
|
if (content) {
|
||||||
const safeTitle = this.title ? `<div class="met-title">${escapeHTML(this.title)}</div>` : '';
|
const safeTitle = this.title ? `<div class="met-title">${escapeHTML(this.title)}</div>` : '';
|
||||||
@@ -621,11 +657,12 @@ const _actionHTML = (actions) => {
|
|||||||
const meToast = {
|
const meToast = {
|
||||||
_toasts: new Map(),
|
_toasts: new Map(),
|
||||||
_config: { ...DEFAULTS },
|
_config: { ...DEFAULTS },
|
||||||
version: '0.1.1',
|
version: '0.1.2',
|
||||||
|
|
||||||
configure(opts) {
|
configure(opts) {
|
||||||
if (!opts || typeof opts !== 'object') return this;
|
if (!opts || typeof opts !== 'object') return this;
|
||||||
this._config = { ...this._config, ...opts };
|
// 原地更新,保持 _config 引用一致(index.js 的增强对象共享同一个 _config)
|
||||||
|
Object.assign(this._config, opts);
|
||||||
|
|
||||||
if (opts.theme) {
|
if (opts.theme) {
|
||||||
applyTheme(opts.theme);
|
applyTheme(opts.theme);
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast i18n - 国际化管理
|
* MetonaToast i18n - 国际化管理
|
||||||
* @module i18n
|
* @module i18n
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
* @description 多语言支持、语言切换和翻译管理
|
* @description 多语言支持、语言切换和翻译管理
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast Icons — 图标SVG定义
|
* MetonaToast Icons — 图标SVG定义
|
||||||
* @module icons
|
* @module icons
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
* @description 80+ 内置SVG图标
|
* @description 80+ 内置SVG图标
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+9
-4
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast - 轻量级Toast通知库
|
* MetonaToast - 轻量级Toast通知库
|
||||||
* @module metona-toast
|
* @module metona-toast
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
* @author thzxx
|
* @author thzxx
|
||||||
* @description 轻量、零依赖、精致美观的Toast通知库。单文件,开箱即用。
|
* @description 轻量、零依赖、精致美观的Toast通知库。单文件,开箱即用。
|
||||||
* @license MIT
|
* @license MIT
|
||||||
@@ -15,7 +15,7 @@ import { pluginUtils, presetPlugins } from './plugins.js';
|
|||||||
import { DEFAULTS } from './constants.js';
|
import { DEFAULTS } from './constants.js';
|
||||||
|
|
||||||
// 版本信息
|
// 版本信息
|
||||||
const VERSION = '0.1.1';
|
const VERSION = '0.1.2';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主对象增强
|
* 主对象增强
|
||||||
@@ -89,6 +89,8 @@ const enhancedMeToast = {
|
|||||||
* 销毁
|
* 销毁
|
||||||
*/
|
*/
|
||||||
destroy() {
|
destroy() {
|
||||||
|
if (this._destroyed) return;
|
||||||
|
this._destroyed = true;
|
||||||
this.dismiss();
|
this.dismiss();
|
||||||
|
|
||||||
if (this.plugins && typeof this.plugins.destroy === 'function') {
|
if (this.plugins && typeof this.plugins.destroy === 'function') {
|
||||||
@@ -149,7 +151,7 @@ const enhancedMeToast = {
|
|||||||
*/
|
*/
|
||||||
updateConfig(config) {
|
updateConfig(config) {
|
||||||
if (config && typeof config === 'object') {
|
if (config && typeof config === 'object') {
|
||||||
this._config = { ...this._config, ...config };
|
Object.assign(this._config, config);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
@@ -158,7 +160,10 @@ const enhancedMeToast = {
|
|||||||
* 重置配置
|
* 重置配置
|
||||||
*/
|
*/
|
||||||
resetConfig() {
|
resetConfig() {
|
||||||
this._config = { ...DEFAULTS };
|
// 原地重置:先清除所有自有属性,再回填默认值
|
||||||
|
const keys = Object.keys(this._config);
|
||||||
|
keys.forEach(k => delete this._config[k]);
|
||||||
|
Object.assign(this._config, DEFAULTS);
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+20
-276
@@ -1,12 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast Locales — 国际化翻译数据
|
* MetonaToast Locales — 国际化翻译数据
|
||||||
* @module locales
|
* @module locales
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
* @description 内置 zh-CN / en-US 完整翻译
|
* @description 内置 zh-CN / en-US 完整翻译(已去重优化)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const LOCALES = {
|
export const LOCALES = {
|
||||||
'zh-CN': {
|
'zh-CN': {
|
||||||
|
// === 操作 ===
|
||||||
close: '关闭',
|
close: '关闭',
|
||||||
loading: '加载中...',
|
loading: '加载中...',
|
||||||
success: '操作成功',
|
success: '操作成功',
|
||||||
@@ -87,6 +88,8 @@ export const LOCALES = {
|
|||||||
hide: '隐藏',
|
hide: '隐藏',
|
||||||
visible: '可见',
|
visible: '可见',
|
||||||
hidden: '隐藏',
|
hidden: '隐藏',
|
||||||
|
|
||||||
|
// === 状态 ===
|
||||||
enabled: '已启用',
|
enabled: '已启用',
|
||||||
disabled: '已禁用',
|
disabled: '已禁用',
|
||||||
active: '活跃',
|
active: '活跃',
|
||||||
@@ -95,7 +98,6 @@ export const LOCALES = {
|
|||||||
offline: '离线',
|
offline: '离线',
|
||||||
connected: '已连接',
|
connected: '已连接',
|
||||||
disconnected: '已断开',
|
disconnected: '已断开',
|
||||||
loading: '加载中',
|
|
||||||
loaded: '已加载',
|
loaded: '已加载',
|
||||||
saving: '保存中',
|
saving: '保存中',
|
||||||
saved: '已保存',
|
saved: '已保存',
|
||||||
@@ -114,12 +116,9 @@ export const LOCALES = {
|
|||||||
receiving: '接收中',
|
receiving: '接收中',
|
||||||
received: '已接收',
|
received: '已接收',
|
||||||
connecting: '连接中',
|
connecting: '连接中',
|
||||||
error: '错误',
|
|
||||||
warning: '警告',
|
// === 交互 ===
|
||||||
info: '信息',
|
|
||||||
success: '成功',
|
|
||||||
question: '问题',
|
question: '问题',
|
||||||
help: '帮助',
|
|
||||||
feedback: '反馈',
|
feedback: '反馈',
|
||||||
report: '报告',
|
report: '报告',
|
||||||
bug: '错误',
|
bug: '错误',
|
||||||
@@ -133,7 +132,6 @@ export const LOCALES = {
|
|||||||
complete: '完成',
|
complete: '完成',
|
||||||
incomplete: '未完成',
|
incomplete: '未完成',
|
||||||
pending: '待处理',
|
pending: '待处理',
|
||||||
processing: '处理中',
|
|
||||||
failed: '失败',
|
failed: '失败',
|
||||||
cancelled: '已取消',
|
cancelled: '已取消',
|
||||||
timeout: '超时',
|
timeout: '超时',
|
||||||
@@ -142,8 +140,6 @@ export const LOCALES = {
|
|||||||
valid: '有效',
|
valid: '有效',
|
||||||
required: '必填',
|
required: '必填',
|
||||||
optional: '可选',
|
optional: '可选',
|
||||||
enabled: '启用',
|
|
||||||
disabled: '禁用',
|
|
||||||
allowed: '允许',
|
allowed: '允许',
|
||||||
denied: '拒绝',
|
denied: '拒绝',
|
||||||
approved: '已批准',
|
approved: '已批准',
|
||||||
@@ -158,6 +154,8 @@ export const LOCALES = {
|
|||||||
unauthenticated: '未认证',
|
unauthenticated: '未认证',
|
||||||
authorized: '已授权',
|
authorized: '已授权',
|
||||||
unauthorized: '未授权',
|
unauthorized: '未授权',
|
||||||
|
|
||||||
|
// === 范围 / 角色 ===
|
||||||
public: '公开',
|
public: '公开',
|
||||||
private: '私有',
|
private: '私有',
|
||||||
protected: '受保护',
|
protected: '受保护',
|
||||||
@@ -181,6 +179,8 @@ export const LOCALES = {
|
|||||||
following: '关注中',
|
following: '关注中',
|
||||||
friend: '朋友',
|
friend: '朋友',
|
||||||
contact: '联系人',
|
contact: '联系人',
|
||||||
|
|
||||||
|
// === 组织 ===
|
||||||
group: '群组',
|
group: '群组',
|
||||||
team: '团队',
|
team: '团队',
|
||||||
organization: '组织',
|
organization: '组织',
|
||||||
@@ -190,8 +190,6 @@ export const LOCALES = {
|
|||||||
task: '任务',
|
task: '任务',
|
||||||
issue: '问题',
|
issue: '问题',
|
||||||
ticket: '工单',
|
ticket: '工单',
|
||||||
request: '请求',
|
|
||||||
response: '响应',
|
|
||||||
message: '消息',
|
message: '消息',
|
||||||
notification: '通知',
|
notification: '通知',
|
||||||
alert: '警报',
|
alert: '警报',
|
||||||
@@ -199,7 +197,6 @@ export const LOCALES = {
|
|||||||
event: '事件',
|
event: '事件',
|
||||||
activity: '活动',
|
activity: '活动',
|
||||||
log: '日志',
|
log: '日志',
|
||||||
report: '报告',
|
|
||||||
analytics: '分析',
|
analytics: '分析',
|
||||||
statistics: '统计',
|
statistics: '统计',
|
||||||
metrics: '指标',
|
metrics: '指标',
|
||||||
@@ -251,134 +248,10 @@ export const LOCALES = {
|
|||||||
which: '哪个',
|
which: '哪个',
|
||||||
whose: '谁的',
|
whose: '谁的',
|
||||||
whom: '谁',
|
whom: '谁',
|
||||||
myself: '我自己',
|
|
||||||
yourself: '你自己',
|
|
||||||
himself: '他自己',
|
|
||||||
herself: '她自己',
|
|
||||||
itself: '它自己',
|
|
||||||
ourselves: '我们自己',
|
|
||||||
yourselves: '你们自己',
|
|
||||||
themselves: '他们自己',
|
|
||||||
mine: '我的',
|
|
||||||
yours: '你的',
|
|
||||||
his: '他的',
|
|
||||||
hers: '她的',
|
|
||||||
its: '它的',
|
|
||||||
ours: '我们的',
|
|
||||||
yours: '你们的',
|
|
||||||
theirs: '他们的',
|
|
||||||
me: '我',
|
|
||||||
you: '你',
|
|
||||||
him: '他',
|
|
||||||
her: '她',
|
|
||||||
it: '它',
|
|
||||||
us: '我们',
|
|
||||||
them: '他们',
|
|
||||||
my: '我的',
|
|
||||||
your: '你的',
|
|
||||||
his: '他的',
|
|
||||||
her: '她的',
|
|
||||||
its: '它的',
|
|
||||||
our: '我们的',
|
|
||||||
your: '你们的',
|
|
||||||
their: '他们的',
|
|
||||||
i: '我',
|
|
||||||
you: '你',
|
|
||||||
he: '他',
|
|
||||||
she: '她',
|
|
||||||
it: '它',
|
|
||||||
we: '我们',
|
|
||||||
they: '他们',
|
|
||||||
am: '是',
|
|
||||||
is: '是',
|
|
||||||
are: '是',
|
|
||||||
was: '是',
|
|
||||||
were: '是',
|
|
||||||
be: '是',
|
|
||||||
been: '是',
|
|
||||||
being: '是',
|
|
||||||
have: '有',
|
|
||||||
has: '有',
|
|
||||||
had: '有',
|
|
||||||
having: '有',
|
|
||||||
do: '做',
|
|
||||||
does: '做',
|
|
||||||
did: '做',
|
|
||||||
doing: '做',
|
|
||||||
will: '会',
|
|
||||||
would: '会',
|
|
||||||
shall: '将',
|
|
||||||
should: '应该',
|
|
||||||
may: '可以',
|
|
||||||
might: '可能',
|
|
||||||
can: '能',
|
|
||||||
could: '能',
|
|
||||||
must: '必须',
|
|
||||||
need: '需要',
|
|
||||||
dare: '敢',
|
|
||||||
ought: '应该',
|
|
||||||
used: '过去常常',
|
|
||||||
to: '到',
|
|
||||||
of: '的',
|
|
||||||
in: '在',
|
|
||||||
for: '为了',
|
|
||||||
on: '在',
|
|
||||||
with: '和',
|
|
||||||
at: '在',
|
|
||||||
by: '通过',
|
|
||||||
from: '从',
|
|
||||||
into: '进入',
|
|
||||||
during: '在...期间',
|
|
||||||
before: '在...之前',
|
|
||||||
after: '在...之后',
|
|
||||||
above: '在...上面',
|
|
||||||
below: '在...下面',
|
|
||||||
between: '在...之间',
|
|
||||||
under: '在...下面',
|
|
||||||
over: '在...上面',
|
|
||||||
across: '穿过',
|
|
||||||
through: '通过',
|
|
||||||
into: '进入',
|
|
||||||
towards: '朝向',
|
|
||||||
upon: '在...上面',
|
|
||||||
about: '关于',
|
|
||||||
against: '反对',
|
|
||||||
among: '在...之中',
|
|
||||||
along: '沿着',
|
|
||||||
around: '周围',
|
|
||||||
beyond: '超出',
|
|
||||||
but: '但是',
|
|
||||||
despite: '尽管',
|
|
||||||
except: '除了',
|
|
||||||
inside: '里面',
|
|
||||||
outside: '外面',
|
|
||||||
since: '自从',
|
|
||||||
until: '直到',
|
|
||||||
unless: '除非',
|
|
||||||
whether: '是否',
|
|
||||||
while: '当...时候',
|
|
||||||
although: '虽然',
|
|
||||||
because: '因为',
|
|
||||||
if: '如果',
|
|
||||||
once: '一旦',
|
|
||||||
since: '自从',
|
|
||||||
so: '所以',
|
|
||||||
that: '那个',
|
|
||||||
though: '虽然',
|
|
||||||
till: '直到',
|
|
||||||
unless: '除非',
|
|
||||||
until: '直到',
|
|
||||||
when: '当...时候',
|
|
||||||
whenever: '每当',
|
|
||||||
where: '哪里',
|
|
||||||
wherever: '无论哪里',
|
|
||||||
whereas: '然而',
|
|
||||||
wherever: '无论哪里',
|
|
||||||
while: '当...时候',
|
|
||||||
why: '为什么',
|
|
||||||
},
|
},
|
||||||
|
|
||||||
'en-US': {
|
'en-US': {
|
||||||
|
// === Actions ===
|
||||||
close: 'Close',
|
close: 'Close',
|
||||||
loading: 'Loading...',
|
loading: 'Loading...',
|
||||||
success: 'Success',
|
success: 'Success',
|
||||||
@@ -459,6 +332,8 @@ export const LOCALES = {
|
|||||||
hide: 'Hide',
|
hide: 'Hide',
|
||||||
visible: 'Visible',
|
visible: 'Visible',
|
||||||
hidden: 'Hidden',
|
hidden: 'Hidden',
|
||||||
|
|
||||||
|
// === Status ===
|
||||||
enabled: 'Enabled',
|
enabled: 'Enabled',
|
||||||
disabled: 'Disabled',
|
disabled: 'Disabled',
|
||||||
active: 'Active',
|
active: 'Active',
|
||||||
@@ -467,7 +342,6 @@ export const LOCALES = {
|
|||||||
offline: 'Offline',
|
offline: 'Offline',
|
||||||
connected: 'Connected',
|
connected: 'Connected',
|
||||||
disconnected: 'Disconnected',
|
disconnected: 'Disconnected',
|
||||||
loading: 'Loading',
|
|
||||||
loaded: 'Loaded',
|
loaded: 'Loaded',
|
||||||
saving: 'Saving',
|
saving: 'Saving',
|
||||||
saved: 'Saved',
|
saved: 'Saved',
|
||||||
@@ -486,12 +360,9 @@ export const LOCALES = {
|
|||||||
receiving: 'Receiving',
|
receiving: 'Receiving',
|
||||||
received: 'Received',
|
received: 'Received',
|
||||||
connecting: 'Connecting',
|
connecting: 'Connecting',
|
||||||
error: 'Error',
|
|
||||||
warning: 'Warning',
|
// === Interaction ===
|
||||||
info: 'Info',
|
|
||||||
success: 'Success',
|
|
||||||
question: 'Question',
|
question: 'Question',
|
||||||
help: 'Help',
|
|
||||||
feedback: 'Feedback',
|
feedback: 'Feedback',
|
||||||
report: 'Report',
|
report: 'Report',
|
||||||
bug: 'Bug',
|
bug: 'Bug',
|
||||||
@@ -505,7 +376,6 @@ export const LOCALES = {
|
|||||||
complete: 'Complete',
|
complete: 'Complete',
|
||||||
incomplete: 'Incomplete',
|
incomplete: 'Incomplete',
|
||||||
pending: 'Pending',
|
pending: 'Pending',
|
||||||
processing: 'Processing',
|
|
||||||
failed: 'Failed',
|
failed: 'Failed',
|
||||||
cancelled: 'Cancelled',
|
cancelled: 'Cancelled',
|
||||||
timeout: 'Timeout',
|
timeout: 'Timeout',
|
||||||
@@ -514,8 +384,6 @@ export const LOCALES = {
|
|||||||
valid: 'Valid',
|
valid: 'Valid',
|
||||||
required: 'Required',
|
required: 'Required',
|
||||||
optional: 'Optional',
|
optional: 'Optional',
|
||||||
enabled: 'Enabled',
|
|
||||||
disabled: 'Disabled',
|
|
||||||
allowed: 'Allowed',
|
allowed: 'Allowed',
|
||||||
denied: 'Denied',
|
denied: 'Denied',
|
||||||
approved: 'Approved',
|
approved: 'Approved',
|
||||||
@@ -530,6 +398,8 @@ export const LOCALES = {
|
|||||||
unauthenticated: 'Unauthenticated',
|
unauthenticated: 'Unauthenticated',
|
||||||
authorized: 'Authorized',
|
authorized: 'Authorized',
|
||||||
unauthorized: 'Unauthorized',
|
unauthorized: 'Unauthorized',
|
||||||
|
|
||||||
|
// === Scope / Role ===
|
||||||
public: 'Public',
|
public: 'Public',
|
||||||
private: 'Private',
|
private: 'Private',
|
||||||
protected: 'Protected',
|
protected: 'Protected',
|
||||||
@@ -553,6 +423,8 @@ export const LOCALES = {
|
|||||||
following: 'Following',
|
following: 'Following',
|
||||||
friend: 'Friend',
|
friend: 'Friend',
|
||||||
contact: 'Contact',
|
contact: 'Contact',
|
||||||
|
|
||||||
|
// === Organization ===
|
||||||
group: 'Group',
|
group: 'Group',
|
||||||
team: 'Team',
|
team: 'Team',
|
||||||
organization: 'Organization',
|
organization: 'Organization',
|
||||||
@@ -562,8 +434,6 @@ export const LOCALES = {
|
|||||||
task: 'Task',
|
task: 'Task',
|
||||||
issue: 'Issue',
|
issue: 'Issue',
|
||||||
ticket: 'Ticket',
|
ticket: 'Ticket',
|
||||||
request: 'Request',
|
|
||||||
response: 'Response',
|
|
||||||
message: 'Message',
|
message: 'Message',
|
||||||
notification: 'Notification',
|
notification: 'Notification',
|
||||||
alert: 'Alert',
|
alert: 'Alert',
|
||||||
@@ -571,7 +441,6 @@ export const LOCALES = {
|
|||||||
event: 'Event',
|
event: 'Event',
|
||||||
activity: 'Activity',
|
activity: 'Activity',
|
||||||
log: 'Log',
|
log: 'Log',
|
||||||
report: 'Report',
|
|
||||||
analytics: 'Analytics',
|
analytics: 'Analytics',
|
||||||
statistics: 'Statistics',
|
statistics: 'Statistics',
|
||||||
metrics: 'Metrics',
|
metrics: 'Metrics',
|
||||||
@@ -623,130 +492,5 @@ export const LOCALES = {
|
|||||||
which: 'Which',
|
which: 'Which',
|
||||||
whose: 'Whose',
|
whose: 'Whose',
|
||||||
whom: 'Whom',
|
whom: 'Whom',
|
||||||
myself: 'Myself',
|
|
||||||
yourself: 'Yourself',
|
|
||||||
himself: 'Himself',
|
|
||||||
herself: 'Herself',
|
|
||||||
itself: 'Itself',
|
|
||||||
ourselves: 'Ourselves',
|
|
||||||
yourselves: 'Yourselves',
|
|
||||||
themselves: 'Themselves',
|
|
||||||
mine: 'Mine',
|
|
||||||
yours: 'Yours',
|
|
||||||
his: 'His',
|
|
||||||
hers: 'Hers',
|
|
||||||
its: 'Its',
|
|
||||||
ours: 'Ours',
|
|
||||||
yours: 'Yours',
|
|
||||||
theirs: 'Theirs',
|
|
||||||
me: 'Me',
|
|
||||||
you: 'You',
|
|
||||||
him: 'Him',
|
|
||||||
her: 'Her',
|
|
||||||
it: 'It',
|
|
||||||
us: 'Us',
|
|
||||||
them: 'Them',
|
|
||||||
my: 'My',
|
|
||||||
your: 'Your',
|
|
||||||
his: 'His',
|
|
||||||
her: 'Her',
|
|
||||||
its: 'Its',
|
|
||||||
our: 'Our',
|
|
||||||
your: 'Your',
|
|
||||||
their: 'Their',
|
|
||||||
i: 'I',
|
|
||||||
you: 'You',
|
|
||||||
he: 'He',
|
|
||||||
she: 'She',
|
|
||||||
it: 'It',
|
|
||||||
we: 'We',
|
|
||||||
they: 'They',
|
|
||||||
am: 'Am',
|
|
||||||
is: 'Is',
|
|
||||||
are: 'Are',
|
|
||||||
was: 'Was',
|
|
||||||
were: 'Were',
|
|
||||||
be: 'Be',
|
|
||||||
been: 'Been',
|
|
||||||
being: 'Being',
|
|
||||||
have: 'Have',
|
|
||||||
has: 'Has',
|
|
||||||
had: 'Had',
|
|
||||||
having: 'Having',
|
|
||||||
do: 'Do',
|
|
||||||
does: 'Does',
|
|
||||||
did: 'Did',
|
|
||||||
doing: 'Doing',
|
|
||||||
will: 'Will',
|
|
||||||
would: 'Would',
|
|
||||||
shall: 'Shall',
|
|
||||||
should: 'Should',
|
|
||||||
may: 'May',
|
|
||||||
might: 'Might',
|
|
||||||
can: 'Can',
|
|
||||||
could: 'Could',
|
|
||||||
must: 'Must',
|
|
||||||
need: 'Need',
|
|
||||||
dare: 'Dare',
|
|
||||||
ought: 'Ought',
|
|
||||||
used: 'Used',
|
|
||||||
to: 'To',
|
|
||||||
of: 'Of',
|
|
||||||
in: 'In',
|
|
||||||
for: 'For',
|
|
||||||
on: 'On',
|
|
||||||
with: 'With',
|
|
||||||
at: 'At',
|
|
||||||
by: 'By',
|
|
||||||
from: 'From',
|
|
||||||
into: 'Into',
|
|
||||||
during: 'During',
|
|
||||||
before: 'Before',
|
|
||||||
after: 'After',
|
|
||||||
above: 'Above',
|
|
||||||
below: 'Below',
|
|
||||||
between: 'Between',
|
|
||||||
under: 'Under',
|
|
||||||
over: 'Over',
|
|
||||||
across: 'Across',
|
|
||||||
through: 'Through',
|
|
||||||
into: 'Into',
|
|
||||||
towards: 'Towards',
|
|
||||||
upon: 'Upon',
|
|
||||||
about: 'About',
|
|
||||||
against: 'Against',
|
|
||||||
among: 'Among',
|
|
||||||
along: 'Along',
|
|
||||||
around: 'Around',
|
|
||||||
beyond: 'Beyond',
|
|
||||||
but: 'But',
|
|
||||||
despite: 'Despite',
|
|
||||||
except: 'Except',
|
|
||||||
inside: 'Inside',
|
|
||||||
outside: 'Outside',
|
|
||||||
since: 'Since',
|
|
||||||
until: 'Until',
|
|
||||||
unless: 'Unless',
|
|
||||||
whether: 'Whether',
|
|
||||||
while: 'While',
|
|
||||||
although: 'Although',
|
|
||||||
because: 'Because',
|
|
||||||
if: 'If',
|
|
||||||
once: 'Once',
|
|
||||||
since: 'Since',
|
|
||||||
so: 'So',
|
|
||||||
that: 'That',
|
|
||||||
though: 'Though',
|
|
||||||
till: 'Till',
|
|
||||||
unless: 'Unless',
|
|
||||||
until: 'Until',
|
|
||||||
when: 'When',
|
|
||||||
whenever: 'Whenever',
|
|
||||||
where: 'Where',
|
|
||||||
wherever: 'Wherever',
|
|
||||||
whereas: 'Whereas',
|
|
||||||
wherever: 'Wherever',
|
|
||||||
while: 'While',
|
|
||||||
why: 'Why',
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
+10
-6
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast Plugins - 插件系统
|
* MetonaToast Plugins - 插件系统
|
||||||
* @module plugins
|
* @module plugins
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
* @description 插件管理器 + 3 款预设插件 (keyboard / persistence / accessibility)
|
* @description 插件管理器 + 3 款预设插件 (keyboard / persistence / accessibility)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -21,15 +21,19 @@ class PluginManager {
|
|||||||
console.warn(`Plugin "${name}" is already registered`);
|
console.warn(`Plugin "${name}" is already registered`);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
if (!plugin || typeof plugin !== 'object' || (!plugin.name && !plugin.version)) {
|
if (!plugin || typeof plugin !== 'object' || !plugin.name) {
|
||||||
console.error(`Invalid plugin "${name}"`);
|
console.error(`Invalid plugin "${name}": must be an object with a "name" property`);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.plugins.set(name, { name, ...plugin, installed: false, enabled: true });
|
// 先存储再 install,确保 install 内通过 this 设置的实例属性保留在存储对象上
|
||||||
|
// 保留插件自带的 name(若有),否则使用注册 key 作为 name
|
||||||
|
const stored = { ...plugin, installed: false, enabled: true };
|
||||||
|
if (!stored.name) stored.name = name;
|
||||||
|
this.plugins.set(name, stored);
|
||||||
|
|
||||||
if (plugin.install) {
|
if (stored.install) {
|
||||||
try { plugin.install(this); this.plugins.get(name).installed = true; }
|
try { stored.install(this); stored.installed = true; }
|
||||||
catch (e) { console.error(`Failed to install plugin "${name}":`, e); }
|
catch (e) { console.error(`Failed to install plugin "${name}":`, e); }
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast Styles - 样式管理(精简版 v0.1.1)
|
* MetonaToast Styles - 样式管理(精简版 v0.1.2)
|
||||||
* @module styles
|
* @module styles
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
* @description 样式注入与主题管理,移除未使用的组件样式
|
* @description 样式注入与主题管理,移除未使用的组件样式
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+1
-81
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast Themes - 主题管理
|
* MetonaToast Themes - 主题管理
|
||||||
* @module themes
|
* @module themes
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
* @description 主题系统、自定义主题和主题切换
|
* @description 主题系统、自定义主题和主题切换
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -458,84 +458,4 @@ export const themeUtils = {
|
|||||||
loadTheme,
|
loadTheme,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 预设主题
|
|
||||||
*/
|
|
||||||
export const presetThemes = {
|
|
||||||
/**
|
|
||||||
* 浅色主题
|
|
||||||
*/
|
|
||||||
light: {
|
|
||||||
name: '浅色',
|
|
||||||
description: '明亮清晰的主题',
|
|
||||||
config: THEMES.light,
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 深色主题
|
|
||||||
*/
|
|
||||||
dark: {
|
|
||||||
name: '深色',
|
|
||||||
description: '护眼舒适的暗色主题',
|
|
||||||
config: THEMES.dark,
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自动主题
|
|
||||||
*/
|
|
||||||
auto: {
|
|
||||||
name: '自动',
|
|
||||||
description: '跟随系统主题设置',
|
|
||||||
config: 'auto',
|
|
||||||
},
|
|
||||||
|
|
||||||
warm: {
|
|
||||||
name: '暖色',
|
|
||||||
description: '温馨舒适的暖色主题',
|
|
||||||
config: THEMES.warm,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// 注册预设主题
|
|
||||||
Object.entries(presetThemes).forEach(([name, theme]) => {
|
|
||||||
if (name !== 'auto' && theme.config !== 'auto') {
|
|
||||||
THEMES[name] = theme.config;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建主题管理器
|
|
||||||
* @returns {Object} 主题管理器
|
|
||||||
*/
|
|
||||||
export const createThemeManager = () => {
|
|
||||||
return {
|
|
||||||
getSystemTheme,
|
|
||||||
resolveTheme,
|
|
||||||
getThemeConfig,
|
|
||||||
applyTheme,
|
|
||||||
getCurrentTheme,
|
|
||||||
getResolvedTheme,
|
|
||||||
switchTheme,
|
|
||||||
toggleTheme,
|
|
||||||
resetToAuto,
|
|
||||||
initTheme,
|
|
||||||
watchSystemTheme,
|
|
||||||
unwatchSystemTheme,
|
|
||||||
addThemeListener,
|
|
||||||
removeThemeListener,
|
|
||||||
clearThemeListeners,
|
|
||||||
registerTheme,
|
|
||||||
unregisterTheme,
|
|
||||||
getAllThemes,
|
|
||||||
getThemeNames,
|
|
||||||
hasTheme,
|
|
||||||
getThemePreview,
|
|
||||||
generateThemeCSS,
|
|
||||||
applyThemeCSS,
|
|
||||||
removeThemeCSS,
|
|
||||||
saveTheme,
|
|
||||||
loadTheme,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export { themeUtils as default };
|
export { themeUtils as default };
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast Utils - 精简工具函数
|
* MetonaToast Utils - 精简工具函数
|
||||||
* @module utils
|
* @module utils
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
* @description 仅保留核心模块实际使用的工具函数
|
* @description 仅保留核心模块实际使用的工具函数
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
+62
-4
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast 单元测试
|
* MetonaToast 单元测试
|
||||||
* @module tests
|
* @module tests
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import MeToast, { Toast, VERSION } from '../src/index.js';
|
import MeToast, { Toast, VERSION } from '../src/index.js';
|
||||||
@@ -121,8 +121,8 @@ describe('MetonaToast', () => {
|
|||||||
|
|
||||||
describe('版本信息', () => {
|
describe('版本信息', () => {
|
||||||
test('应该有正确的版本号', () => {
|
test('应该有正确的版本号', () => {
|
||||||
expect(VERSION).toBe('0.1.1');
|
expect(VERSION).toBe('0.1.2');
|
||||||
expect(MeToast.version).toBe('0.1.1');
|
expect(MeToast.version).toBe('0.1.2');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -566,6 +566,45 @@ describe('MetonaToast', () => {
|
|||||||
expect(toast.paused).toBe(false);
|
expect(toast.paused).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('暂停恢复应保持 remaining 时间连续性', () => {
|
||||||
|
const toast = MeToast.success({
|
||||||
|
message: '消息',
|
||||||
|
duration: 5000,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 模拟计时开始
|
||||||
|
toast.config.duration = 5000;
|
||||||
|
// 直接设置内部状态模拟已运行 2 秒
|
||||||
|
toast.startedAt = Date.now() - 2000;
|
||||||
|
toast.remaining = 3000;
|
||||||
|
toast.paused = false;
|
||||||
|
|
||||||
|
const remBefore = toast.remaining;
|
||||||
|
toast._pause();
|
||||||
|
expect(toast.paused).toBe(true);
|
||||||
|
expect(toast.remaining).toBeLessThanOrEqual(remBefore);
|
||||||
|
|
||||||
|
const pausedRemaining = toast.remaining;
|
||||||
|
toast._resume();
|
||||||
|
expect(toast.paused).toBe(false);
|
||||||
|
// resume 后 remaining 应保持与暂停时一致(允许微小误差)
|
||||||
|
expect(toast.remaining).toBeGreaterThanOrEqual(pausedRemaining - 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('update 类型变更应同步更新 DOM 类名', () => {
|
||||||
|
const toast = MeToast.info('test');
|
||||||
|
expect(toast.type).toBe('info');
|
||||||
|
toast.update({ type: 'error', message: 'changed' });
|
||||||
|
expect(toast.type).toBe('error');
|
||||||
|
// DOM 验证需要实际浏览器环境,此处验证状态变更
|
||||||
|
});
|
||||||
|
|
||||||
|
test('update 类型变更无 DOM 时不抛异常', () => {
|
||||||
|
const toast = new Toast({ message: 'test', type: 'info' });
|
||||||
|
expect(() => toast.update({ type: 'success', message: 'ok' })).not.toThrow();
|
||||||
|
expect(toast.type).toBe('success');
|
||||||
|
});
|
||||||
|
|
||||||
test('应该能够获取Toast配置', () => {
|
test('应该能够获取Toast配置', () => {
|
||||||
const toast = MeToast.success({
|
const toast = MeToast.success({
|
||||||
message: '消息',
|
message: '消息',
|
||||||
@@ -583,7 +622,7 @@ describe('MetonaToast', () => {
|
|||||||
MeToast.success('消息');
|
MeToast.success('消息');
|
||||||
|
|
||||||
const status = MeToast.getStatus();
|
const status = MeToast.getStatus();
|
||||||
expect(status.version).toBe('0.1.1');
|
expect(status.version).toBe('0.1.2');
|
||||||
expect(status.toasts).toBeGreaterThanOrEqual(0);
|
expect(status.toasts).toBeGreaterThanOrEqual(0);
|
||||||
expect(status.theme).toBeDefined();
|
expect(status.theme).toBeDefined();
|
||||||
expect(status.locale).toBeDefined();
|
expect(status.locale).toBeDefined();
|
||||||
@@ -1391,4 +1430,23 @@ describe('新增功能', () => {
|
|||||||
});
|
});
|
||||||
expect(t.config.render).toBeInstanceOf(Function);
|
expect(t.config.render).toBeInstanceOf(Function);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('onError 回调在钩子异常时触发', () => {
|
||||||
|
const errors = [];
|
||||||
|
MeToast.configure({ onError: (e) => errors.push(e) });
|
||||||
|
const badHandler = () => { throw new Error('test-error'); };
|
||||||
|
Toast.on('afterShow', badHandler);
|
||||||
|
const toast = MeToast.success('test');
|
||||||
|
Toast.trigger('afterShow', toast);
|
||||||
|
expect(errors.length).toBeGreaterThanOrEqual(1);
|
||||||
|
expect(errors[0].error.message).toBe('test-error');
|
||||||
|
Toast.off('afterShow', badHandler);
|
||||||
|
MeToast.configure({ onError: null });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('destroy 重复调用不抛异常', () => {
|
||||||
|
MeToast.success('test');
|
||||||
|
MeToast.destroy();
|
||||||
|
expect(() => MeToast.destroy()).not.toThrow();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Vendored
+3
-1
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* MetonaToast TypeScript 类型定义
|
* MetonaToast TypeScript 类型定义
|
||||||
* @version 0.1.1
|
* @version 0.1.2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 基础类型
|
// 基础类型
|
||||||
@@ -276,6 +276,8 @@ export interface ToastConfig {
|
|||||||
resetTimerOnUpdate?: boolean;
|
resetTimerOnUpdate?: boolean;
|
||||||
/** 后台发送系统通知 */
|
/** 后台发送系统通知 */
|
||||||
notifyWhenHidden?: boolean;
|
notifyWhenHidden?: boolean;
|
||||||
|
/** 全局错误回调 */
|
||||||
|
onError?: (errorInfo: { hook?: string; source?: string; error: Error; toast?: ToastInstance }) => void;
|
||||||
/** 分组名称 */
|
/** 分组名称 */
|
||||||
group?: string;
|
group?: string;
|
||||||
/** 语言 */
|
/** 语言 */
|
||||||
|
|||||||
Reference in New Issue
Block a user