"use strict"; (function (global) { let activeTooltipElement = null; function ensureTooltipPopover() { let pop = document.getElementById("toolTipPopover"); if (!pop) { pop = document.createElement("div"); pop.id = "toolTipPopover"; pop.className = "tool-tip-popover hidden"; document.body.appendChild(pop); } return pop; } function resolveTip(el) { if (!el) return ""; if (typeof el.__tarinaiTipProvider === "function") return String(el.__tarinaiTipProvider() || ""); return String(el.dataset?.tip || ""); } function showTooltip(el) { if (!el || !document.documentElement.contains(el)) return; const tip = resolveTip(el); if (!tip) return; const pop = ensureTooltipPopover(); activeTooltipElement = el; pop.textContent = tip; pop.classList.remove("hidden"); const rect = el.getBoundingClientRect(); const popW = pop.offsetWidth || 220; const popH = pop.offsetHeight || 36; const preferLeft = rect.left - popW - 12; const rightSide = rect.right + 12; const left = preferLeft >= 8 ? preferLeft : rightSide; pop.style.left = `${clamp(left, 8, Math.max(8, window.innerWidth - popW - 8))}px`; pop.style.top = `${clamp(rect.top + rect.height / 2 - popH / 2, 8, Math.max(8, window.innerHeight - popH - 8))}px`; } function hideTooltip() { activeTooltipElement = null; ensureTooltipPopover().classList.add("hidden"); } function refreshTooltip(el = null) { const target = el || activeTooltipElement; if (!target) return; // Do not let unrelated UI refreshes steal an already-visible tooltip. // Ground UI updates run during stats refresh; without this guard, hovering a // tool can suddenly turn into the current ground description. if (el && activeTooltipElement && el !== activeTooltipElement) return; if (!document.documentElement.contains(target)) { hideTooltip(); return; } const pop = ensureTooltipPopover(); if (pop.classList.contains("hidden")) return; showTooltip(target); } function bindTooltip(el, tip = "") { if (!el) return; if (typeof tip === "function") el.__tarinaiTipProvider = tip; else if (tip) el.dataset.tip = String(tip); // Native browser title tooltips can linger and overlap the custom popover. el.removeAttribute?.("title"); if (el.dataset.tipBound === "1") return; el.dataset.tipBound = "1"; el.addEventListener("mouseenter", () => showTooltip(el)); el.addEventListener("focus", () => showTooltip(el)); el.addEventListener("mouseleave", hideTooltip); el.addEventListener("blur", hideTooltip); el.addEventListener("pointerdown", () => { if (activeTooltipElement === el) hideTooltip(); }); } function applyToolPaletteTooltips() { const tips = global.TEXT_CATALOG?.toolTips || {}; const root = global.ui?.toolPalette || document; for (const btn of root.querySelectorAll?.(".tool[data-tool]") || []) { const tip = tips[btn.dataset.tool]; if (tip) bindTooltip(btn, tip); } } global.TarinaiTooltips = Object.freeze({ ensure: ensureTooltipPopover, bind: bindTooltip, show: showTooltip, hide: hideTooltip, refresh: refreshTooltip, active: () => activeTooltipElement, applyToolPalette: applyToolPaletteTooltips, }); global.bindTooltip = bindTooltip; })(window);