"use strict"; class TarinaiEventBus { constructor({ historyLimit = 180 } = {}) { this.handlers = new Map(); this.history = []; this.historyLimit = historyLimit; } on(type, handler) { if (!type || typeof handler !== "function") return () => {}; let list = this.handlers.get(type); if (!list) { list = new Set(); this.handlers.set(type, list); } list.add(handler); return () => this.off(type, handler); } off(type, handler) { const list = this.handlers.get(type); if (!list) return; list.delete(handler); if (!list.size) this.handlers.delete(type); } emit(type, detail = {}) { if (!type) return null; const event = { type, detail: detail || {}, at: performance?.now?.() ?? Date.now() }; this.history.unshift(event); if (this.history.length > this.historyLimit) this.history.length = this.historyLimit; const direct = this.handlers.get(type); if (direct) for (const handler of [...direct]) this.safeCall(handler, event); const wildcard = this.handlers.get("*"); if (wildcard) for (const handler of [...wildcard]) this.safeCall(handler, event); return event; } safeCall(handler, event) { try { handler(event); } catch (err) { console.error("event handler failed", event.type, err); } } recent(filter = null, limit = 40) { const list = filter ? this.history.filter(ev => ev.type === filter) : this.history; return list.slice(0, limit); } } window.TarinaiEventBus = TarinaiEventBus; window.TarinaiEvents = window.TarinaiEvents || new TarinaiEventBus();