"use strict"; (function (global) { let activeTooltipElement = null; let hideTimer = 0; let longPressTimer = 0; 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, options = {}) { if (!el || !document.documentElement.contains(el)) return; const tip = resolveTip(el); if (!tip) return; if (hideTimer) { clearTimeout(hideTimer); hideTimer = 0; } 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`; if (options.autoHide || document.body.classList.contains("touch-mobile-ui")) { hideTimer = setTimeout(hideTooltip, Number(options.delay || 1800)); } } function hideTooltip() { activeTooltipElement = null; if (hideTimer) { clearTimeout(hideTimer); hideTimer = 0; } if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = 0; } 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", () => { if (!document.body.classList.contains("touch-mobile-ui")) showTooltip(el); }); el.addEventListener("focus", () => { if (!document.body.classList.contains("touch-mobile-ui")) showTooltip(el); }); el.addEventListener("mouseleave", hideTooltip); el.addEventListener("blur", hideTooltip); el.addEventListener("pointerdown", () => { if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = 0; } if (activeTooltipElement === el || document.body.classList.contains("touch-mobile-ui")) hideTooltip(); }); el.addEventListener("touchstart", () => { if (!document.body.classList.contains("touch-mobile-ui")) return; if (longPressTimer) clearTimeout(longPressTimer); longPressTimer = setTimeout(() => { longPressTimer = 0; el.dataset.suppressNextClick = "1"; setTimeout(() => { if (el.dataset.suppressNextClick === "1") el.dataset.suppressNextClick = ""; }, 900); showTooltip(el, { autoHide: true, delay: 2600 }); }, 520); }, { passive: true }); el.addEventListener("touchmove", () => { if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = 0; } }, { passive: true }); el.addEventListener("touchend", () => { if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = 0; } }, { passive: true }); el.addEventListener("touchcancel", () => { if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = 0; } }, { passive: true }); } 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); } } document.addEventListener("pointerdown", (e) => { if (!activeTooltipElement) return; if (activeTooltipElement.contains?.(e.target)) return; hideTooltip(); }, { capture: true, passive: true }); document.addEventListener("touchstart", (e) => { if (!activeTooltipElement) return; if (activeTooltipElement.contains?.(e.target)) return; hideTooltip(); }, { capture: true, passive: true }); window.addEventListener("scroll", hideTooltip, { passive: true }); window.addEventListener("resize", hideTooltip, { passive: true }); document.addEventListener("visibilitychange", () => { if (document.hidden) hideTooltip(); }); global.TarinaiTooltips = Object.freeze({ bind: bindTooltip, hide: hideTooltip, refresh: refreshTooltip, applyToolPalette: applyToolPaletteTooltips, }); })(window);