// retoor import { OptimisticAction } from "./OptimisticAction.js"; export class ReactionBar extends OptimisticAction { constructor() { super(); document.addEventListener("click", (event) => this.onClick(event)); } async onClick(event) { const addButton = event.target.closest(".reaction-add-btn"); if (addButton) { event.preventDefault(); this.togglePalette(addButton); return; } const trigger = event.target.closest("[data-reaction-emoji]"); if (trigger && !trigger.disabled) { event.preventDefault(); await this.react(trigger); return; } this.closeAllPalettes(); } togglePalette(addButton) { const palette = addButton.parentElement.querySelector(".reaction-palette"); const isOpen = palette.hidden === false; this.closeAllPalettes(); palette.hidden = isOpen; if (!palette.hidden) { this.clampToViewport(palette); this.ensureInView(palette); } } clampToViewport(palette) { const margin = 8; palette.style.left = ""; const rect = palette.getBoundingClientRect(); const overflowRight = rect.right - (window.innerWidth - margin); if (overflowRight > 0) { palette.style.left = `${-overflowRight}px`; } const adjusted = palette.getBoundingClientRect(); if (adjusted.left < margin) { const current = parseFloat(palette.style.left || "0"); palette.style.left = `${current + (margin - adjusted.left)}px`; } } ensureInView(palette) { const margin = 8; const rect = palette.getBoundingClientRect(); const extra = rect.height * 0.3; if (rect.top < margin) { window.scrollBy({ top: rect.top - margin - extra, behavior: "smooth" }); } else if (rect.bottom > window.innerHeight - margin) { window.scrollBy({ top: rect.bottom - (window.innerHeight - margin) + extra, behavior: "smooth" }); } } closeAllPalettes() { document.querySelectorAll(".reaction-palette").forEach((palette) => { palette.hidden = true; }); } async react(trigger) { const bar = trigger.closest(".reaction-bar"); if (!bar) { return; } const type = bar.dataset.reactionType; const uid = bar.dataset.reactionUid; const emoji = trigger.dataset.reactionEmoji; await this.submit(`/reactions/${type}/${uid}`, { emoji }, null, (result) => this.render(bar, result)); this.closeAllPalettes(); } render(bar, result) { const counts = result.counts || {}; const mine = new Set(result.mine || []); bar.querySelectorAll(".reaction-list .reaction-chip").forEach((chip) => { const emoji = chip.dataset.reactionEmoji; const count = counts[emoji] || 0; chip.querySelector(".reaction-count").textContent = count; chip.hidden = count === 0 && !mine.has(emoji); chip.classList.toggle("reacted", mine.has(emoji)); }); } }