/** * Which frame the pointer is over, computed from geometry rather than hit testing. * * The canvas camera layer turns off hit testing unless the select tool is active, * so a canvas tool can drag across frame content. That also means a frame never * sees a real pointer event in those modes — and hover is exactly when preparing * the next frame pays off. The canvas surface still owns the pointer, so the frame * under it is resolved from the camera transform and the frame boxes instead. */ export interface FrameBox { frameId: string; x: number; y: number; width: number; height: number; } export interface CanvasCamera { panX: number; panY: number; zoom: number; } export interface ClientRectLike { left: number; top: number; } /** Converts a client point into canvas coordinates. Mirrors the marquee math in the canvas surface. */ export declare function canvasPointFromClient(client: { clientX: number; clientY: number; }, rect: ClientRectLike, camera: CanvasCamera): { x: number; y: number; } | null; /** * Returns the frame containing a canvas point, or null. * * Later frames win, matching paint order: a frame drawn on top of another is the * one the designer is pointing at. */ export declare function frameAtCanvasPoint(frames: readonly FrameBox[], point: { x: number; y: number; } | null): string | null; export type FrameHoverTransition = { action: 'idle'; } | { action: 'restart'; frameId: string; } | { action: 'clear'; }; /** * Decides what a pointer move does to the pending dwell. * * Leaving a frame forgets it, which is what makes returning to it start over. If * the frame were remembered, a pointer that left before the dwell elapsed and came * back would look like it had never moved, and that frame would never be prepared. */ export declare function resolveFrameHoverTransition(previousFrameId: string | null, frameId: string | null): FrameHoverTransition; /** * Reports whether the canvas surface has to resolve hover itself. * * With the select tool the frames receive real pointer events, so the frame's own * hover path already noted the intent; resolving it again from the surface would * note the same frame twice. */ export declare function canvasOwnsFrameHover(editMode: boolean, tool: string): boolean;