import { useCallback, useState } from 'react' import type { CardInfo } from '../api' // State for the floating card-text preview (components/CardPreview.tsx): // shown while hovering or keyboard-focusing a card name, only on devices // with a real pointer -- touch users tap through to Scryfall instead. export interface PreviewState { card: CardInfo x: number y: number } export const PREVIEW_WIDTH = 300 // Estimate used only to keep the panel on screen; real height varies with text. const PREVIEW_HEIGHT = 240 const OFFSET = 18 function place(x: number, y: number): { x: number; y: number } { const vw = window.innerWidth const vh = window.innerHeight const left = x + OFFSET + PREVIEW_WIDTH > vw ? x - OFFSET - PREVIEW_WIDTH : x + OFFSET const top = Math.min(Math.max(8, y - PREVIEW_HEIGHT / 2), vh - PREVIEW_HEIGHT - 8) return { x: Math.max(8, left), y: top } } const canHover = () => window.matchMedia('(hover: hover) and (pointer: fine)').matches export function usePreview() { const [state, setState] = useState(null) const show = useCallback((card: CardInfo, e: React.MouseEvent) => { if (canHover()) setState({ card, ...place(e.clientX, e.clientY) }) }, []) const move = useCallback((e: React.MouseEvent) => { setState((s) => (s ? { ...s, ...place(e.clientX, e.clientY) } : s)) }, []) const showAt = useCallback((card: CardInfo, el: HTMLElement) => { if (!canHover()) return const r = el.getBoundingClientRect() setState({ card, ...place(r.right, r.top + r.height / 2) }) }, []) const hide = useCallback(() => setState(null), []) return { state, show, move, showAt, hide } }