import { ref } from 'vue'; import type { SlipItem } from '../stores/betSlip'; const visible = ref(false); const anchorX = ref(0); const anchorY = ref(0); const pendingItem = ref(null); const activeCardRootId = ref(null); const placement = ref<'top' | 'bottom'>('bottom'); let closeTimer: number | undefined = undefined; export function useDesktopBetPopover() { function openAt(event: MouseEvent, item: SlipItem) { cancelClose(); const el = (event.currentTarget || event.target) as HTMLElement; const btn = el?.closest?.('button') || el; const rect = btn?.getBoundingClientRect?.(); if (!rect) return; const popW = 190; const popH = 170; const pad = 12; // increased pad to leave space for the arrow pointer // Calculate center X of the button const btnCenterX = rect.left + rect.width / 2; let x = btnCenterX - popW / 2; // Default: place below button (center bottom) let y = rect.bottom + pad; placement.value = 'bottom'; if (typeof window !== 'undefined') { const spaceBelow = window.innerHeight - rect.bottom; if (spaceBelow < popH + pad) { // Not enough space below, place above button (center top) y = rect.top - popH - pad; placement.value = 'top'; } // Keep within viewport boundaries x = Math.max(pad, Math.min(x, window.innerWidth - popW - pad)); y = Math.max(pad, Math.min(y, window.innerHeight - popH - pad)); } anchorX.value = x; anchorY.value = y; pendingItem.value = item; const root = el?.closest?.('[data-bet-card-root]') as HTMLElement | null; activeCardRootId.value = root?.dataset.betCardRoot ?? null; visible.value = true; } function close() { visible.value = false; pendingItem.value = null; activeCardRootId.value = null; if (closeTimer !== undefined) { window.clearTimeout(closeTimer); closeTimer = undefined; } } function scheduleClose(delay = 200) { if (closeTimer !== undefined) { window.clearTimeout(closeTimer); } closeTimer = window.setTimeout(() => { visible.value = false; pendingItem.value = null; activeCardRootId.value = null; closeTimer = undefined; }, delay); } function cancelClose() { if (closeTimer !== undefined) { window.clearTimeout(closeTimer); closeTimer = undefined; } } function isActiveForCard(cardRootId: string | null | undefined) { if (!cardRootId || !visible.value || !pendingItem.value) return false; return activeCardRootId.value === cardRootId; } return { visible, anchorX, anchorY, pendingItem, activeCardRootId, placement, openAt, close, scheduleClose, cancelClose, isActiveForCard, }; }