- 包声明 type:module 时 .js 产物被 Node 按 ESM 解析:Node 16/18 下 require 报 ERR_REQUIRE_ESM,Node 20+ 拿到 namespace 对象(success/version 等属性 undefined) - dist/metona-toast.cjs.js → .cjs,dist/react.cjs.js → .cjs - 主包 CJS footer 将 default 提升为 module.exports:require() 直接返回 MeToast(兼容 .default / .MeToast / .Met / .Toast / .VERSION 所有用法) - 版本 0.5.1(0.5.0 已发布带问题产物) - 真实消费者验证:CJS/ESM/React 子包四路加载全部正常
506 lines
35 KiB
HTML
506 lines
35 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||
<title>API 文档 — MetonaToast</title>
|
||
<style>
|
||
:root {
|
||
--bg: #070b14; --surface: rgba(255,255,255,0.03); --border: rgba(255,255,255,0.08);
|
||
--text: #e8ecf4; --muted: #8b94a7; --accent: #a5b4fc; --accent2: #c7d2fe;
|
||
--grad: linear-gradient(135deg, #818cf8, #c084fc, #f472b6);
|
||
--radius: 12px;
|
||
}
|
||
* { margin:0; padding:0; box-sizing:border-box; }
|
||
html { scroll-behavior:smooth; }
|
||
body {
|
||
font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif;
|
||
background:var(--bg); color:var(--text); line-height:1.75; display:flex; min-height:100vh;
|
||
background-image:
|
||
radial-gradient(ellipse 70% 40% at 80% -10%, rgba(99,102,241,0.12), transparent),
|
||
radial-gradient(ellipse 50% 40% at 0% 20%, rgba(236,72,153,0.05), transparent);
|
||
}
|
||
code {
|
||
background:rgba(99,102,241,0.15); color:#a5b4fc; padding:1px 6px;
|
||
border-radius:5px; font-size:.88em; white-space:nowrap;
|
||
}
|
||
a { color:var(--accent); text-decoration:none; }
|
||
a:hover { color:var(--accent2); }
|
||
|
||
/* ===== 侧边栏 ===== */
|
||
.sidebar {
|
||
width:264px; min-width:264px; background:rgba(10,15,26,.8);
|
||
border-right:1px solid var(--border); padding:22px 0;
|
||
position:sticky; top:0; height:100vh; overflow-y:auto;
|
||
backdrop-filter:blur(14px);
|
||
}
|
||
.sidebar::-webkit-scrollbar { width:5px; }
|
||
.sidebar::-webkit-scrollbar-thumb { background:rgba(255,255,255,.12); border-radius:3px; }
|
||
.sidebar-logo { font-size:16px; font-weight:800; padding:0 24px; margin-bottom:4px; }
|
||
.grad-text { background:var(--grad); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; color:transparent; }
|
||
.sidebar .back { display:block; font-size:12.5px; padding:6px 24px; color:var(--muted); }
|
||
.sidebar .back:hover { color:var(--accent2); }
|
||
.sidebar a.snav {
|
||
display:block; padding:6.5px 24px; font-size:13px; color:var(--muted);
|
||
transition:.15s; border-left:2px solid transparent;
|
||
}
|
||
.sidebar a.snav:hover { color:var(--accent2); }
|
||
.sidebar a.snav.active { color:var(--accent2); border-left-color:#a855f7; background:rgba(139,92,246,.08); }
|
||
.sidebar .section {
|
||
font-size:11px; text-transform:uppercase; letter-spacing:1.2px;
|
||
padding:18px 24px 6px; color:var(--muted); font-weight:700; opacity:.75;
|
||
}
|
||
|
||
/* ===== 主内容 ===== */
|
||
.main { flex:1; padding:44px 52px; max-width:980px; min-width:0; }
|
||
.main h1 { font-size:32px; font-weight:800; margin-bottom:6px; letter-spacing:-.5px; }
|
||
.main .h1-desc { color:var(--muted); font-size:14px; margin-bottom:8px; }
|
||
.main h2 {
|
||
font-size:22px; font-weight:700; margin:52px 0 12px; padding-top:22px;
|
||
border-top:1px solid var(--border); scroll-margin-top:24px;
|
||
}
|
||
.main h2::before { content:'#'; margin-right:8px; background:var(--grad); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; }
|
||
.main h3 { font-size:16.5px; font-weight:700; margin:26px 0 10px; color:var(--accent2); }
|
||
.main p { margin:8px 0; color:var(--muted); font-size:14px; }
|
||
.main p code { font-size:.9em; }
|
||
.main table { width:100%; border-collapse:collapse; margin:14px 0 22px; font-size:13px; }
|
||
.main th, .main td { text-align:left; padding:9px 14px; border-bottom:1px solid var(--border); vertical-align:top; }
|
||
.main th { color:var(--muted); font-weight:600; font-size:11px; text-transform:uppercase; letter-spacing:.8px; }
|
||
.main td:first-child { color:var(--accent); font-family:monospace; font-size:12px; white-space:nowrap; }
|
||
.main td:nth-child(3) { font-family:monospace; font-size:11.5px; color:var(--muted); }
|
||
.badge {
|
||
display:inline-block; padding:1px 8px; border-radius:4px; font-size:10px;
|
||
font-weight:700; margin-left:6px; vertical-align:middle;
|
||
}
|
||
.badge-new { background:rgba(16,185,129,.18); color:#34d399; border:1px solid rgba(16,185,129,.3); }
|
||
.badge-v5 { background:rgba(168,85,247,.2); color:#d8b4fe; border:1px solid rgba(168,85,247,.4); }
|
||
.hint { font-size:12.5px; color:var(--muted); margin-top:2px; }
|
||
.return-box {
|
||
background:rgba(16,185,129,.06); border:1px solid rgba(16,185,129,.2);
|
||
border-radius:10px; padding:14px 18px; margin:14px 0;
|
||
}
|
||
.return-box h4 { font-size:11.5px; color:#34d399; margin-bottom:8px; text-transform:uppercase; letter-spacing:.8px; }
|
||
|
||
.terminal {
|
||
background:#0a0f1c; border:1px solid var(--border); border-radius:10px;
|
||
overflow:hidden; margin:12px 0 20px;
|
||
}
|
||
.terminal-bar { display:flex; align-items:center; gap:7px; padding:9px 14px; background:rgba(255,255,255,0.03); border-bottom:1px solid var(--border); }
|
||
.terminal-bar .t-dot { width:10px; height:10px; border-radius:50%; }
|
||
.terminal-bar .t-dot:nth-child(1){ background:#ff5f57; } .terminal-bar .t-dot:nth-child(2){ background:#febc2e; } .terminal-bar .t-dot:nth-child(3){ background:#28c840; }
|
||
.terminal-bar .t-title { margin-left:10px; font-size:11px; color:var(--muted); }
|
||
.terminal pre { padding:16px 18px; overflow-x:auto; font:12.5px/1.75 'SF Mono','Cascadia Code','Fira Code',Consolas,monospace; color:#cbd5e1; }
|
||
.terminal pre .kw { color:#c084fc; } .terminal pre .fn { color:#60a5fa; } .terminal pre .s { color:#34d399; } .terminal pre .cm { color:#475569; }
|
||
|
||
@media (max-width:860px) {
|
||
body { flex-direction:column; }
|
||
.sidebar { width:100%; min-width:0; height:auto; position:static; border-right:none; border-bottom:1px solid var(--border); padding:12px 16px; }
|
||
.sidebar .section, .sidebar .back { padding:4px 8px; }
|
||
.sidebar a.snav { display:inline-block; padding:4px 10px; border-left:none; font-size:12.5px; }
|
||
.sidebar a.snav.active { border-left:none; border-radius:6px; }
|
||
.main { padding:26px 20px; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<nav class="sidebar">
|
||
<div class="sidebar-logo"><span class="grad-text">MetonaToast 文档</span></div>
|
||
<a class="back" href="index.html">← 返回首页</a>
|
||
<a class="back" href="demo.html">🎮 在线演示</a>
|
||
<div class="section">基础通知</div>
|
||
<a class="snav" href="#show">show()</a>
|
||
<a class="snav" href="#success">success()</a>
|
||
<a class="snav" href="#error">error()</a>
|
||
<a class="snav" href="#warning">warning()</a>
|
||
<a class="snav" href="#info">info()</a>
|
||
<a class="snav" href="#loading">loading()</a>
|
||
<div class="section">高级功能</div>
|
||
<a class="snav" href="#promise">promise()</a>
|
||
<a class="snav" href="#confirm">confirm()</a>
|
||
<a class="snav" href="#prompt">prompt()</a>
|
||
<a class="snav" href="#progress">progress()</a>
|
||
<a class="snav" href="#countdown">countdown()</a>
|
||
<a class="snav" href="#queue">queue()</a>
|
||
<a class="snav" href="#stack">stack()</a>
|
||
<a class="snav" href="#action">action()</a>
|
||
<div class="section">管理方法</div>
|
||
<a class="snav" href="#group">group()</a>
|
||
<a class="snav" href="#dismiss">dismiss()</a>
|
||
<a class="snav" href="#clear">clear()</a>
|
||
<a class="snav" href="#updatePosition">updatePosition()</a>
|
||
<a class="snav" href="#remove">remove() / removeToast()</a>
|
||
<a class="snav" href="#configure">configure()</a>
|
||
<a class="snav" href="#use">use()</a>
|
||
<a class="snav" href="#destroy">destroy()</a>
|
||
<div class="section">扩展</div>
|
||
<a class="snav" href="#hooks">钩子系统</a>
|
||
<a class="snav" href="#react">React 适配器</a>
|
||
<a class="snav" href="#config">全部配置项</a>
|
||
<a class="snav" href="#callbacks">回调函数</a>
|
||
<a class="snav" href="#animations">动画列表</a>
|
||
<a class="snav" href="#themes">主题参考</a>
|
||
</nav>
|
||
|
||
<main class="main">
|
||
|
||
<h1>API 文档</h1>
|
||
<p class="h1-desc">MetonaToast v0.5.1 完整 API 参考。所有基础通知方法支持字符串与对象两种调用形式,均可传入任何<a href="#config">配置项</a>作为可选参数。</p>
|
||
|
||
<!-- ===== 基础通知 ===== -->
|
||
<h2 id="show">show(message, opts?)</h2>
|
||
<p>显示默认类型 Toast,无特定颜色与图标。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">show.js</span></div>
|
||
<pre><span class="cm">// 字符串形式</span>
|
||
MeToast.<span class="fn">show</span>(<span class="s">'默认消息'</span>);
|
||
MeToast.<span class="fn">show</span>(<span class="s">'自定义'</span>, { <span class="fn">duration</span>: <span class="num">2000</span>, <span class="fn">position</span>: <span class="s">'bottom-center'</span> });
|
||
<span class="cm">// 对象形式</span>
|
||
MeToast.<span class="fn">show</span>({ <span class="fn">title</span>: <span class="s">'标题'</span>, <span class="fn">message</span>: <span class="s">'内容'</span>, <span class="fn">duration</span>: <span class="num">3000</span> });</pre></div>
|
||
|
||
<h2 id="success">success(message, opts?)</h2>
|
||
<p>绿色对勾图标 <code>#10b981</code>,type = success。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">success.js</span></div>
|
||
<pre>MeToast.<span class="fn">success</span>(<span class="s">'保存成功!'</span>);
|
||
MeToast.<span class="fn">success</span>({ <span class="fn">title</span>: <span class="s">'已保存'</span>, <span class="fn">message</span>: <span class="s">'数据已同步'</span> });
|
||
Met.<span class="fn">success</span>(<span class="s">'Met 与 MeToast 等价'</span>);</pre></div>
|
||
|
||
<h2 id="error">error(message, opts?)</h2>
|
||
<p>红色叉号图标 <code>#ef4444</code>,type = error。aria-live = assertive。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">error.js</span></div>
|
||
<pre>MeToast.<span class="fn">error</span>(<span class="s">'网络错误,请重试'</span>);
|
||
MeToast.<span class="fn">error</span>({ <span class="fn">title</span>: <span class="s">'提交失败'</span>, <span class="fn">message</span>: <span class="s">'服务器不可达'</span> });</pre></div>
|
||
|
||
<h2 id="warning">warning(message, opts?)</h2>
|
||
<p>黄色三角图标 <code>#f59e0b</code>,type = warning。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">warning.js</span></div>
|
||
<pre>MeToast.<span class="fn">warning</span>(<span class="s">'请注意检查输入内容'</span>);</pre></div>
|
||
|
||
<h2 id="info">info(message, opts?)</h2>
|
||
<p>蓝色圆形图标 <code>#3b82f6</code>,type = info。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">info.js</span></div>
|
||
<pre>MeToast.<span class="fn">info</span>(<span class="s">'系统将于 22:00 维护'</span>);</pre></div>
|
||
|
||
<h2 id="loading">loading(message, opts?)</h2>
|
||
<p>type = loading,duration 强制 0(不自动关闭)。返回 LoadingControl。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">loading.js</span></div>
|
||
<pre><span class="kw">const</span> loading = MeToast.<span class="fn">loading</span>(<span class="s">'正在提交...'</span>);
|
||
<span class="fn">setTimeout</span>(() => loading.<span class="fn">success</span>(<span class="s">'提交成功!'</span>), <span class="num">2000</span>);</pre></div>
|
||
<div class="return-box">
|
||
<h4>LoadingControl(链式转换 id 稳定)</h4>
|
||
<table>
|
||
<tr><th>方法</th><th>说明</th></tr>
|
||
<tr><td>success/error/info/warning</td><td>原地更新为对应类型(同一实例,id 不变),duration 自动恢复默认值</td></tr>
|
||
<tr><td>update(partial)</td><td>原地更新内容,不改变类型</td></tr>
|
||
<tr><td>dismiss()</td><td>直接关闭,不转换</td></tr>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- ===== 高级功能 ===== -->
|
||
<h2 id="promise">promise(promise, opts)</h2>
|
||
<p>监听 Promise 生命周期,自动 loading → resolve/reject 切换 success/error,返回原 Promise。</p>
|
||
<table>
|
||
<tr><th>参数</th><th>类型</th><th>默认</th><th>说明</th></tr>
|
||
<tr><td>promise</td><td>Promise</td><td>—</td><td>要监听的 Promise。非 Promise 打印错误并返回 rejected Promise</td></tr>
|
||
<tr><td>opts.loading / success / error</td><td>string</td><td>加载中... / 操作成功 / 操作失败</td><td>各阶段文本</td></tr>
|
||
</table>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">promise.js</span></div>
|
||
<pre><span class="kw">try</span> {
|
||
<span class="kw">await</span> MeToast.<span class="fn">promise</span>(<span class="fn">fetch</span>(<span class="s">'/api/data'</span>), {
|
||
<span class="fn">loading</span>: <span class="s">'加载中...'</span>, <span class="fn">success</span>: <span class="s">'完成!'</span>, <span class="fn">error</span>: <span class="s">'失败'</span>,
|
||
});
|
||
} <span class="kw">catch</span> (e) { <span class="cm">/* reject 会继续抛出 */</span> }</pre></div>
|
||
|
||
<h2 id="confirm">confirm(message, opts?)</h2>
|
||
<p>确认对话框,返回 <code>Promise<boolean></code>,内置 10 秒安全超时自动 resolve(false)。</p>
|
||
<table>
|
||
<tr><th>参数</th><th>默认</th><th>说明</th></tr>
|
||
<tr><td>confirmText / confirmColor</td><td>确认 / #10b981</td><td>确认按钮文字与颜色</td></tr>
|
||
<tr><td>cancelText / cancelColor</td><td>取消 / #6b7280</td><td>取消按钮文字与颜色</td></tr>
|
||
<tr><td>type</td><td>warning</td><td>Toast 类型</td></tr>
|
||
</table>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">confirm.js</span></div>
|
||
<pre><span class="kw">const</span> ok = <span class="kw">await</span> MeToast.<span class="fn">confirm</span>(<span class="s">'确定删除?'</span>, { <span class="fn">confirmText</span>: <span class="s">'删除'</span>, <span class="fn">confirmColor</span>: <span class="s">'#ef4444'</span> });
|
||
<span class="kw">if</span> (ok) MeToast.<span class="fn">success</span>(<span class="s">'已删除'</span>);</pre></div>
|
||
|
||
<h2 id="prompt">prompt(message, opts?)</h2>
|
||
<p>输入对话框,返回 <code>Promise<string|null></code>。Enter / 提交返回输入值,取消返回 null,10 秒超时。</p>
|
||
<table>
|
||
<tr><th>参数</th><th>默认</th><th>说明</th></tr>
|
||
<tr><td>placeholder / defaultValue</td><td>""</td><td>输入框占位与默认值</td></tr>
|
||
<tr><td>inputType</td><td>text</td><td>input 的 type(password/email/number 等)</td></tr>
|
||
<tr><td>submitText / submitColor</td><td>确认 / #3b82f6</td><td>提交按钮</td></tr>
|
||
<tr><td>cancelText / cancelColor</td><td>取消 / #6b7280</td><td>取消按钮</td></tr>
|
||
</table>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">prompt.js</span></div>
|
||
<pre><span class="kw">const</span> name = <span class="kw">await</span> MeToast.<span class="fn">prompt</span>(<span class="s">'请输入姓名'</span>, { <span class="fn">placeholder</span>: <span class="s">'请输入...'</span> });
|
||
<span class="kw">if</span> (name) MeToast.<span class="fn">info</span>(<span class="s">'你好,'</span> + name);</pre></div>
|
||
|
||
<h2 id="progress">progress(message, opts?)</h2>
|
||
<p>进度条通知,不自动关闭。返回 ProgressControl。</p>
|
||
<table>
|
||
<tr><th>方法</th><th>说明</th></tr>
|
||
<tr><td>setProgress(percent)</td><td>设置进度 0~100,自动 clamp</td></tr>
|
||
<tr><td>complete(message?)</td><td>跳 100%,300ms 后转 success,1s 后自动关闭</td></tr>
|
||
<tr><td>error(message?)</td><td>转 error,2s 后自动关闭</td></tr>
|
||
<tr><td>dismiss()</td><td>直接关闭</td></tr>
|
||
</table>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">progress.js</span></div>
|
||
<pre><span class="kw">const</span> p = MeToast.<span class="fn">progress</span>(<span class="s">'上传中...'</span>, { <span class="fn">progressColor</span>: <span class="s">'#10b981'</span> });
|
||
p.<span class="fn">setProgress</span>(<span class="num">45</span>);
|
||
p.<span class="fn">complete</span>(<span class="s">'上传完成!'</span>);</pre></div>
|
||
|
||
<h2 id="countdown">countdown(message, seconds, opts?)</h2>
|
||
<p>倒计时 Toast,<code>{seconds}</code> 占位符每秒自动替换。</p>
|
||
<table>
|
||
<tr><th>参数</th><th>默认</th><th>说明</th></tr>
|
||
<tr><td>seconds</td><td>10</td><td>倒计时秒数,最小 1</td></tr>
|
||
<tr><td>opts.onComplete</td><td>—</td><td>归零回调</td></tr>
|
||
</table>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">countdown.js</span></div>
|
||
<pre>MeToast.<span class="fn">countdown</span>(<span class="s">'{seconds} 秒后执行'</span>, <span class="num">5</span>, { <span class="fn">onComplete</span>: () => MeToast.<span class="fn">success</span>(<span class="s">'已执行'</span>) });
|
||
<span class="cm">// 返回 { cancel(), pause(), resume() }</span></pre></div>
|
||
|
||
<h2 id="queue">queue(messages, opts?)</h2>
|
||
<p>顺序逐个显示消息队列,返回 thenable + cancel。支持 await。</p>
|
||
<table>
|
||
<tr><th>参数</th><th>默认</th><th>说明</th></tr>
|
||
<tr><td>opts.delay</td><td>1000</td><td>每条关闭后到下一条的间隔(ms)</td></tr>
|
||
<tr><td>opts.duration</td><td>3000</td><td>每条显示时长,可被消息级 duration 覆盖</td></tr>
|
||
</table>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">queue.js</span></div>
|
||
<pre><span class="kw">const</span> q = MeToast.<span class="fn">queue</span>([<span class="s">'步骤一'</span>, <span class="s">'步骤二'</span>, <span class="s">'步骤三'</span>], { <span class="fn">delay</span>: <span class="num">800</span>, <span class="fn">duration</span>: <span class="num">2000</span> });
|
||
q.<span class="fn">cancel</span>(); <span class="cm">// 中途取消</span>
|
||
<span class="kw">await</span> q; <span class="cm">// 等待完成</span></pre></div>
|
||
|
||
<h2 id="stack">stack(messages, opts?)</h2>
|
||
<p>同时错峰显示多条消息。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">stack.js</span></div>
|
||
<pre>MeToast.<span class="fn">stack</span>([<span class="s">'消息1'</span>, <span class="s">'消息2'</span>, { <span class="fn">message</span>: <span class="s">'警告'</span>, <span class="fn">type</span>: <span class="s">'warning'</span> }], { <span class="fn">stagger</span>: <span class="num">150</span> });</pre></div>
|
||
|
||
<h2 id="action">action(message, actions, opts?)</h2>
|
||
<p>内嵌操作按钮。默认 duration=0 不自动关闭。点击按钮不会误触 closeOnClick(已隔离冒泡)。</p>
|
||
<table>
|
||
<tr><th>ActionButton</th><th>默认</th><th>说明</th></tr>
|
||
<tr><td>text</td><td>—(必填)</td><td>按钮文字</td></tr>
|
||
<tr><td>onClick</td><td>—(必填)</td><td>点击回调,参数为当前 toast</td></tr>
|
||
<tr><td>color / style</td><td>#6366f1</td><td>背景色 / 内联样式(style.background 优先)</td></tr>
|
||
<tr><td>close</td><td>true</td><td>点击后是否关闭。false 可多次点击</td></tr>
|
||
</table>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">action.js</span></div>
|
||
<pre>MeToast.<span class="fn">action</span>(<span class="s">'文件已删除'</span>, [
|
||
{ <span class="fn">text</span>: <span class="s">'撤销'</span>, <span class="fn">onClick</span>: () => <span class="fn">restore</span>(), <span class="fn">color</span>: <span class="s">'#3b82f6'</span> },
|
||
{ <span class="fn">text</span>: <span class="s">'查看'</span>, <span class="fn">onClick</span>: () => <span class="fn">open</span>(), <span class="fn">color</span>: <span class="s">'#10b981'</span>, <span class="fn">close</span>: <span class="kw">false</span> },
|
||
]);</pre></div>
|
||
|
||
<!-- ===== 管理方法 ===== -->
|
||
<h2 id="group">group(name)</h2>
|
||
<p>创建分组,返回 GroupAPI。所有方法自动注入 <code>group: name</code>。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">group.js</span></div>
|
||
<pre><span class="kw">const</span> orders = MeToast.<span class="fn">group</span>(<span class="s">'orders'</span>);
|
||
orders.<span class="fn">success</span>(<span class="s">'订单已创建'</span>);
|
||
orders.<span class="fn">count</span>(); <span class="cm">// 该组数量</span>
|
||
orders.<span class="fn">dismiss</span>(); <span class="cm">// 关闭整组</span>
|
||
MeToast.<span class="fn">dismissGroup</span>(<span class="s">'orders'</span>);</pre></div>
|
||
|
||
<h2 id="dismiss">dismiss(id?)</h2>
|
||
<p>关闭 Toast。无参数关闭全部,传入 id 关闭指定。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">dismiss.js</span></div>
|
||
<pre>MeToast.<span class="fn">dismiss</span>(); <span class="cm">// 全部</span>
|
||
MeToast.<span class="fn">dismiss</span>(toast.id); <span class="cm">// 指定</span></pre></div>
|
||
|
||
<h2 id="clear">clear(position?)</h2>
|
||
<p>按位置清除。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">clear.js</span></div>
|
||
<pre>MeToast.<span class="fn">clear</span>(); <span class="cm">// 全部</span>
|
||
MeToast.<span class="fn">clear</span>(<span class="s">'bottom-right'</span>); <span class="cm">// 仅右下角</span></pre></div>
|
||
|
||
<h2 id="updatePosition">updatePosition(position) <span class="badge badge-v5">v0.3</span></h2>
|
||
<p>运行时将 Toast 移动到新位置容器,立即生效。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">position.js</span></div>
|
||
<pre><span class="kw">const</span> t = MeToast.<span class="fn">info</span>(<span class="s">'可移动的 Toast'</span>);
|
||
t.<span class="fn">updatePosition</span>(<span class="s">'bottom-left'</span>);</pre></div>
|
||
|
||
<h2 id="remove">remove() / removeToast(id) <span class="badge badge-new">立即移除</span></h2>
|
||
<p>立即从 DOM 和内存移除,<b>不触发离场动画</b>。适用于无动画快速清除。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">remove.js</span></div>
|
||
<pre>t.<span class="fn">remove</span>(); <span class="cm">// 实例方法</span>
|
||
MeToast.<span class="fn">removeToast</span>(t.id); <span class="cm">// 按 id(等价)</span></pre></div>
|
||
|
||
<h2 id="configure">configure(opts)</h2>
|
||
<p>全局配置,影响后续所有 Toast。theme/locale 变化触发副作用。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">configure.js</span></div>
|
||
<pre>MeToast.<span class="fn">configure</span>({
|
||
<span class="fn">position</span>: <span class="s">'top-right'</span>, <span class="fn">duration</span>: <span class="num">4000</span>, <span class="fn">theme</span>: <span class="s">'dark'</span>,
|
||
<span class="fn">animation</span>: <span class="s">'slide'</span>, <span class="fn">locale</span>: <span class="s">'zh-CN'</span>,
|
||
});</pre></div>
|
||
|
||
<h2 id="use">use(plugin)</h2>
|
||
<p>安装插件:字符串预设名或插件对象。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">use.js</span></div>
|
||
<pre>MeToast.<span class="fn">use</span>(<span class="s">'keyboard'</span>); <span class="cm">// ESC 关闭所有</span>
|
||
MeToast.<span class="fn">use</span>(<span class="s">'persistence'</span>); <span class="cm">// 配置持久化 localStorage</span>
|
||
MeToast.<span class="fn">use</span>(<span class="s">'accessibility'</span>); <span class="cm">// 屏幕阅读器朗读</span>
|
||
MeToast.<span class="fn">use</span>(<span class="s">'dedupe'</span>); <span class="cm">// 相同 type+message 自动去重</span></pre></div>
|
||
<p class="hint">dedupe:检测已有相同 toast,更新它并阻止重复弹出(beforeShow 钩子实现,支持 uninstall 卸载钩子)。</p>
|
||
|
||
<h2 id="destroy">destroy()</h2>
|
||
<p>完全销毁:关闭所有 Toast、移除全部 DOM 容器与注入样式、清空内存缓存与钩子。支持重复调用,<code>init()</code> 可恢复。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">destroy.js</span></div>
|
||
<pre>MeToast.<span class="fn">destroy</span>();
|
||
MeToast.<span class="fn">init</span>({ <span class="fn">config</span>: { <span class="fn">duration</span>: <span class="num">3000</span> } }); <span class="cm">// 恢复</span></pre></div>
|
||
|
||
<!-- ===== 钩子系统 ===== -->
|
||
<h2 id="hooks">钩子系统 <span class="badge badge-v5">v0.3</span></h2>
|
||
<p><code>Toast.on(name, handler)</code> 注册钩子并返回取消函数。<code>beforeShow</code> / <code>beforeClose</code> / <code>beforeUpdate</code> 的 handler 返回 <code>false</code> 可拦截对应操作。</p>
|
||
<table>
|
||
<tr><th>钩子</th><th>触发时机</th><th>拦截</th></tr>
|
||
<tr><td>beforeInit / afterInit</td><td>init() 前后</td><td>—</td></tr>
|
||
<tr><td>beforeDestroy / afterDestroy</td><td>destroy() 前后</td><td>—</td></tr>
|
||
<tr><td>beforeShow / afterShow</td><td>显示前后</td><td>✅ 返回 false 阻止</td></tr>
|
||
<tr><td>beforeClose / afterClose</td><td>关闭前后</td><td>✅ 返回 false 阻止</td></tr>
|
||
<tr><td>beforeUpdate / afterUpdate</td><td>update() 前后</td><td>✅ 返回 false 阻止</td></tr>
|
||
<tr><td>configChange</td><td>configure / updateConfig / resetConfig</td><td>—</td></tr>
|
||
<tr><td>themeChange / localeChange</td><td>主题 / 语言切换</td><td>—</td></tr>
|
||
<tr><td>click / hover</td><td>点击 / 悬停进出</td><td>—</td></tr>
|
||
<tr><td>dragStart / dragEnd</td><td>拖拽开始 / 结束</td><td>—</td></tr>
|
||
<tr><td>animationStart / animationEnd</td><td>入场动画开始 / 结束</td><td>—</td></tr>
|
||
<tr><td>progressStart / progressEnd</td><td>倒计时开始 / 归零</td><td>—</td></tr>
|
||
</table>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">hooks.js</span></div>
|
||
<pre><span class="kw">import</span> MeToast, { <span class="fn">Toast</span> } <span class="kw">from</span> <span class="s">'@metona-team/metona-toast'</span>;
|
||
|
||
<span class="cm">// 拦截:非允许时段禁止错误提示</span>
|
||
<span class="kw">const</span> off = <span class="fn">Toast</span>.<span class="fn">on</span>(<span class="s">'beforeShow'</span>, (toast) => {
|
||
<span class="kw">if</span> (toast.type === <span class="s">'error'</span> && !isAllowed) <span class="kw">return</span> <span class="kw">false</span>;
|
||
});
|
||
<span class="cm">// ...</span>
|
||
off(); <span class="cm">// 取消注册</span></pre></div>
|
||
|
||
<!-- ===== React ===== -->
|
||
<h2 id="react">React 适配器 <span class="badge badge-v5">v0.4</span></h2>
|
||
<p>主包保持零依赖。通过子路径 <code>@metona-team/metona-toast/react</code> 导入,<code>react</code> 为 optional peerDependency。</p>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">react.tsx</span></div>
|
||
<pre><span class="kw">import</span> { <span class="fn">useToast</span>, <span class="fn">Toast</span> } <span class="kw">from</span> <span class="s">'@metona-team/metona-toast/react'</span>;
|
||
|
||
<span class="kw">function</span> <span class="fn">SubmitButton</span>() {
|
||
<span class="kw">const</span> toast = <span class="fn">useToast</span>(); <span class="cm">// 组件卸载自动清理本组件创建的 Toast</span>
|
||
<span class="kw">const</span> submit = <span class="kw">async</span> () => {
|
||
<span class="kw">const</span> loading = toast.<span class="fn">loading</span>(<span class="s">'正在提交...'</span>);
|
||
<span class="kw">try</span> { <span class="kw">await</span> api(); loading.<span class="fn">success</span>(<span class="s">'完成!'</span>); }
|
||
<span class="kw">catch</span> (e) { loading.<span class="fn">error</span>(<span class="s">'失败'</span>); }
|
||
};
|
||
<span class="kw">return</span> <button onClick={submit}>提交</button>;
|
||
}
|
||
|
||
<span class="cm">// 声明式 Toast:props 变化更新,卸载自动移除(autoClose 默认 true)</span>
|
||
<span class="kw">function</span> <span class="fn">SaveIndicator</span>({ saving }) {
|
||
<span class="kw">return</span> saving ? <<span class="fn">Toast</span> type=<span class="s">"info"</span> message=<span class="s">"正在保存..."</span> /> : null;
|
||
}</pre></div>
|
||
|
||
<!-- ===== 配置参考 ===== -->
|
||
<h2 id="config">全部配置项</h2>
|
||
<p>可用于 <code>configure()</code>、<code>init()</code> 或单个 Toast 方法的 opts。</p>
|
||
<table>
|
||
<tr><th>配置项</th><th>类型</th><th>默认值</th><th>说明</th></tr>
|
||
<tr><td>position</td><td>string</td><td>'top-right'</td><td>6 个位置之一(RTL 自动翻转)</td></tr>
|
||
<tr><td>duration</td><td>number</td><td>4000</td><td>显示时长(ms),0 = 不自动关闭</td></tr>
|
||
<tr><td>max</td><td>number</td><td>6</td><td>同位置最多条数,超出真正关闭最早的</td></tr>
|
||
<tr><td>gap</td><td>number</td><td>12</td><td>Toast 间距(px)</td></tr>
|
||
<tr><td>offset</td><td>number</td><td>24</td><td>容器距屏幕边缘(px)</td></tr>
|
||
<tr><td>pauseOnHover</td><td>boolean</td><td>true</td><td>悬停暂停倒计时</td></tr>
|
||
<tr><td>closeOnClick</td><td>boolean</td><td>true</td><td>点击关闭</td></tr>
|
||
<tr><td>draggable</td><td>boolean</td><td>true</td><td>允许拖拽关闭</td></tr>
|
||
<tr><td>dragThreshold</td><td>number</td><td>120</td><td>拖拽关闭阈值(px)</td></tr>
|
||
<tr><td>showProgress</td><td>boolean</td><td>true</td><td>显示倒计时进度条</td></tr>
|
||
<tr><td>progressDirection</td><td>string</td><td>'horizontal'</td><td>horizontal / vertical</td></tr>
|
||
<tr><td>icon</td><td>boolean</td><td>true</td><td>显示类型图标</td></tr>
|
||
<tr><td>closeButton</td><td>boolean</td><td>true</td><td>显示关闭 × 按钮</td></tr>
|
||
<tr><td>theme</td><td>string</td><td>'auto'</td><td>light / dark / auto / warm / 自定义名</td></tr>
|
||
<tr><td>animation</td><td>string</td><td>'slide'</td><td>11 种内置或自定义动画名</td></tr>
|
||
<tr><td>zIndex</td><td>number</td><td>9999</td><td>容器 z-index</td></tr>
|
||
<tr><td>width</td><td>number|string</td><td>360</td><td>宽度,数字表示 px</td></tr>
|
||
<tr><td>className</td><td>string</td><td>''</td><td>附加 CSS 类名</td></tr>
|
||
<tr><td>style</td><td>object</td><td>{}</td><td>附加内联样式</td></tr>
|
||
<tr><td>locale</td><td>string</td><td>'zh-CN'</td><td>语言代码</td></tr>
|
||
<tr><td>resetTimerOnUpdate</td><td>boolean</td><td>false</td><td>update() 时重置倒计时</td></tr>
|
||
<tr><td>notifyWhenHidden</td><td>boolean</td><td>false</td><td>页面不可见时发系统通知</td></tr>
|
||
<tr><td>render</td><td>function</td><td>—</td><td>自定义渲染函数,完全接管 DOM</td></tr>
|
||
<tr><td>onBeforeShow</td><td>function</td><td>—</td><td>返回 false 阻止显示</td></tr>
|
||
<tr><td>onError</td><td>function</td><td>—</td><td>钩子/定时器异常全局回调</td></tr>
|
||
</table>
|
||
|
||
<h2 id="callbacks">回调函数</h2>
|
||
<table>
|
||
<tr><th>回调</th><th>签名</th><th>触发时机</th></tr>
|
||
<tr><td>onBeforeShow</td><td>(toast) => boolean | void</td><td>DOM 创建前,返回 false 阻止显示</td></tr>
|
||
<tr><td>onShow</td><td>(toast) => void</td><td>创建并播放入场动画后</td></tr>
|
||
<tr><td>onClose</td><td>(toast) => void</td><td>DOM 移除后(离场完成)</td></tr>
|
||
<tr><td>onClick</td><td>(toast) => void</td><td>点击时(closeOnClick=true 时还会关闭)</td></tr>
|
||
<tr><td>onUpdate</td><td>(toast) => void</td><td>update() 后</td></tr>
|
||
<tr><td>onError</td><td>({ hook, source, error, toast }) => void</td><td>钩子/定时器异常时</td></tr>
|
||
</table>
|
||
|
||
<h2 id="animations">动画列表</h2>
|
||
<p>未注册的动画名自动 fallback 到 slide。</p>
|
||
<table>
|
||
<tr><th>名称</th><th>效果</th><th>时长</th></tr>
|
||
<tr><td>slide</td><td>从右侧滑入 + 回弹</td><td>400ms</td></tr>
|
||
<tr><td>fade</td><td>纯淡入 + blur→清晰</td><td>500ms</td></tr>
|
||
<tr><td>scale</td><td>弹性放大 (0.55→1.07→1)</td><td>450ms</td></tr>
|
||
<tr><td>bounce</td><td>从天而降四段弹跳</td><td>650ms</td></tr>
|
||
<tr><td>flip</td><td>3D 翻转入场 + 回摆</td><td>500ms</td></tr>
|
||
<tr><td>rotate</td><td>旋转摇摆进入</td><td>500ms</td></tr>
|
||
<tr><td>zoom</td><td>从中心爆发式弹出</td><td>500ms</td></tr>
|
||
<tr><td>slideUp / slideDown</td><td>从下方 / 上方弹入</td><td>400ms</td></tr>
|
||
<tr><td>slideLeft / slideRight</td><td>从左侧 / 右侧滑入</td><td>400ms</td></tr>
|
||
</table>
|
||
|
||
<h2 id="themes">主题参考</h2>
|
||
<div class="terminal"><div class="terminal-bar"><span class="t-dot"></span><span class="t-dot"></span><span class="t-dot"></span><span class="t-title">theme.js</span></div>
|
||
<pre><span class="cm">// 内置主题:light · dark · auto(跟随系统)· warm</span>
|
||
MeToast.themes.<span class="fn">registerTheme</span>(<span class="s">'ocean'</span>, {
|
||
<span class="fn">bg</span>: <span class="s">'rgba(240,249,255,0.96)'</span>,
|
||
<span class="fn">text</span>: <span class="s">'#0c4a6e'</span>,
|
||
<span class="fn">border</span>: <span class="s">'rgba(14,165,233,0.2)'</span>,
|
||
<span class="fn">shadow</span>: <span class="s">'0 10px 36px -10px rgba(14,165,233,0.18)'</span>,
|
||
<span class="fn">hoverShadow</span>: <span class="s">'0 14px 48px -10px rgba(14,165,233,0.22)'</span>,
|
||
<span class="fn">progressBg</span>: <span class="s">'rgba(14,165,233,0.1)'</span>,
|
||
<span class="fn">closeHoverBg</span>: <span class="s">'rgba(14,165,233,0.1)'</span>,
|
||
});
|
||
MeToast.themes.<span class="fn">switchTheme</span>(<span class="s">'ocean'</span>);</pre></div>
|
||
|
||
</main>
|
||
|
||
<script src="../dist/metona-toast.js"></script>
|
||
<script>
|
||
MeToast.configure({ position: 'top-right', duration: 4000, theme: 'dark', animation: 'slide' });
|
||
|
||
// 侧边栏滚动高亮
|
||
const links = document.querySelectorAll('.sidebar a.snav');
|
||
const sections = [];
|
||
links.forEach(l => {
|
||
const id = l.getAttribute('href').slice(1);
|
||
const el = document.getElementById(id);
|
||
if (el) sections.push({ id, el, link: l });
|
||
});
|
||
const spy = new IntersectionObserver(entries => {
|
||
entries.forEach(e => {
|
||
if (e.isIntersecting) {
|
||
links.forEach(l => l.classList.remove('active'));
|
||
const hit = sections.find(s => s.el === e.target);
|
||
if (hit) hit.link.classList.add('active');
|
||
}
|
||
});
|
||
}, { rootMargin: '-15% 0px -70% 0px' });
|
||
sections.forEach(s => spy.observe(s.el));
|
||
|
||
// 点击关闭高亮
|
||
links.forEach(l => l.addEventListener('click', () => {
|
||
links.forEach(x => x.classList.remove('active'));
|
||
l.classList.add('active');
|
||
}));
|
||
</script>
|
||
</body>
|
||
</html>
|