iter(g300): 修正 toast 悬停暂停从未生效
This commit is contained in:
@@ -4,6 +4,7 @@ import type { ToastProps } from './types.js';
|
||||
let host: HTMLElement | null = null; // 全局右上角堆叠容器:首条消息出现时懒创建
|
||||
let seq = 0; // 自增序号:为每条 toast 生成唯一 id,辅助无障碍定位
|
||||
const MAX_STACK = 4; // 同屏最多条数:超出即挤掉最早一条,避免刷屏淹页面
|
||||
const PAUSE_FLOOR = 400; // 恢复时的最短剩余毫秒:悬停前已近归零也不至于松手即消失
|
||||
|
||||
/*** 确保堆叠容器存在:fixed 挂在 body 末尾,后续消息依次向上堆叠 ***/
|
||||
function ensureHost(): HTMLElement {
|
||||
@@ -43,10 +44,23 @@ export function showToast(props: ToastProps): HTMLElement {
|
||||
stack.appendChild(item);
|
||||
requestAnimationFrame(() => item.classList.add('ua-open')); // 下一帧入场,保证过渡生效
|
||||
const arm = (ms: number): void => { startedAt = Date.now(); timer = window.setTimeout(() => dismiss(item), ms); }; // 重新武装倒计时
|
||||
/*** 暂停倒计时:扣掉本段已走时长,清空句柄(重复进入不会二次扣减) ***/
|
||||
const pause = (): void => {
|
||||
if (!timer) return; // 已暂停 / 常驻(duration 为 0)时无计时器可停
|
||||
window.clearTimeout(timer);
|
||||
timer = 0;
|
||||
remain = Math.max(PAUSE_FLOOR, remain - (Date.now() - startedAt));
|
||||
};
|
||||
/*** 恢复倒计时:按剩余时长重新武装 ***/
|
||||
const resume = (): void => { if (!timer && remain > 0) arm(remain); };
|
||||
if (duration > 0) {
|
||||
arm(duration);
|
||||
item.addEventListener('pointerenter', () => { window.clearTimeout(timer); remain -= Date.now() - startedAt; }); // 悬停暂停:记下剩余时长
|
||||
item.addEventListener('pointerleave', () => arm(remain)); // 移出后按剩余时长继续
|
||||
item.addEventListener('pointerenter', pause); // 悬停停留阅读:倒计时暂停
|
||||
item.addEventListener('pointerleave', resume); // 移出后按剩余时长继续
|
||||
item.addEventListener('focusin', pause); // 键盘 Tab 进关闭 / 操作按钮时同样暂停
|
||||
item.addEventListener('focusout', (e) => {
|
||||
if (!item.contains(e.relatedTarget as Node | null)) resume(); // 焦点还在卡片内部(按钮间切换)时不恢复
|
||||
});
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user