/** * Headless model for HUD tooltips and popovers — the shared description seam games have been * hand-rolling with a bare DOM `title=` attribute. {@link actionTooltip} turns a * {@link ResolvedAction} into structured {@link TooltipContent} (title, cost, cooldown, blocking * notes), and {@link placePopover} is the pure, SSR-safe positioning math the React tooltip uses to * flip and clamp against the viewport. Both are rendering-agnostic. */ import type { ActionCooldown, ActionCost, ResolvedAction } from "./actionModel.js"; /** Structured tooltip content — a renderer lays these fields out; the model owns what is shown. */ export interface TooltipContent { title: string; subtitle?: string; body?: string; /** Hotkey label to echo (e.g. `"Q"`). */ hotkey?: string; costs?: readonly ActionCost[]; cooldown?: ActionCooldown | null; /** Blocking reasons rendered as a warning footer (why the action is unavailable). */ notes?: readonly string[]; } /** * Build {@link TooltipContent} from a {@link ResolvedAction}: title from the label, the group as a * subtitle, the description as the body, and the blocking reasons as warning notes. The single place * an action's tooltip copy is assembled, so every renderer shows the same thing. */ export declare function actionTooltip(action: ResolvedAction): TooltipContent; /** Which side of its anchor a popover opens toward. */ export type PopoverSide = "top" | "bottom" | "left" | "right"; /** A positioned rectangle (viewport/anchor space, top-left origin, pixels). */ export interface UiRect { x: number; y: number; width: number; height: number; } /** A width/height pair (pixels). */ export interface UiSize { width: number; height: number; } /** The resolved popover position — the side it actually opened on and its clamped top-left. */ export interface PopoverPlacement { side: PopoverSide; left: number; top: number; } /** Options for {@link placePopover}. */ export interface PopoverOptions { /** Side to try first (default `"top"`). Flips to the opposite when it would overflow. */ preferred?: PopoverSide; /** Gap between the anchor and the popover, in pixels (default 8). */ gap?: number; /** Minimum inset from the viewport edges, in pixels (default 8). */ margin?: number; } /** * Position a popover/tooltip of `content` size against its `anchor` rectangle inside `viewport`: * open on the `preferred` side, flip to the opposite when that side lacks room and the opposite has * more, then clamp the top-left so the box stays fully on screen (respecting `margin`). Pure and * deterministic — no DOM reads — so it is SSR-safe and unit-testable, and the React tooltip is a thin * shell over it. */ export declare function placePopover(anchor: UiRect, content: UiSize, viewport: UiSize, options?: PopoverOptions): PopoverPlacement;