import type { ComputedLayout } from 'textura'; import type { App, FrameTimings, Renderer, UIElement, SelectionRange, TextNodeInfo, AccessibilityNode } from '@geometra/core'; export interface CanvasRendererOptions { /** Canvas element to render into. */ canvas: HTMLCanvasElement; /** Device pixel ratio for crisp rendering. Default: window.devicePixelRatio. */ dpr?: number; /** Background color for the canvas. Default: '#ffffff'. */ background?: string; /** Highlight color for text selection. Default: 'rgba(59, 130, 246, 0.4)'. */ selectionColor?: string; /** Text color for selected text. Default: auto-computed from selectionColor for contrast. */ selectedTextColor?: string; /** Called when an async image finishes loading. Use to trigger re-render. */ onImageLoaded?: () => void; /** Max number of decoded images to keep in memory. Default: 256. */ imageCacheMaxEntries?: number; /** Placeholder color while an image is loading. Default: '#27272a'. */ imagePlaceholderColor?: string; /** Fallback fill color when image loading fails. Default: '#3f1d1d'. */ imageErrorColor?: string; /** TTL in ms for decoded images. 0 disables expiry. Default: 0. */ imageCacheTTLms?: number; /** Max retries after image load failure. Default: 2. */ imageRetryCount?: number; /** Base delay for exponential backoff retries in ms. Default: 500. */ imageRetryBaseDelayMs?: number; /** Custom placeholder painter for loading/error states. */ imagePlaceholderRenderer?: (ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, state: 'loading' | 'error', src: string) => void; /** Factory for creating image objects (useful for tests/custom loaders). */ createImage?: () => HTMLImageElement; /** Stroke every layout rect (flex debugging). Default false. */ debugLayoutBounds?: boolean; /** Draw a ring around the keyboard-focused box. Default true. */ showFocusRing?: boolean; /** Focus ring stroke color. Default: rgba(59, 130, 246, 0.95). */ focusRingColor?: string; /** Outset from the focused box in CSS pixels. Default 2. */ focusRingPadding?: number; /** Skip debug/focus overlays during active drag interactions. Default true. */ optimizeOverlaysDuringInteraction?: boolean; /** * Draw a lightweight inspector HUD (node count, tree depth, root size, focus summary). * Negligible cost when disabled. Default false. */ layoutInspector?: boolean; } export interface AccessibilityMirrorOptions { /** Label for the hidden accessibility region. */ rootLabel?: string; } export interface CanvasInputForwardingOptions { /** Optional target for keyboard/composition events. Defaults to document. */ keyboardTarget?: Document | HTMLElement; } export declare class CanvasRenderer implements Renderer { private ctx; private canvas; private dpr; private background; private selectionColor; private selectedTextColor; private onImageLoaded?; private imageCacheMaxEntries; private imagePlaceholderColor; private imageErrorColor; private imageCacheTTLms; private imageRetryCount; private imageRetryBaseDelayMs; private imagePlaceholderRenderer?; private createImage; private debugLayoutBounds; private showFocusRing; private focusRingColor; private focusRingPadding; private optimizeOverlaysDuringInteraction; private layoutInspector; private interactionActive; /** Cache text wrapping + per-char metrics to avoid recomputing every frame. */ private textLineCache; /** Cache child paint order by z-index per box element. */ private paintOrderCache; /** Cached loaded images (LRU by lastUsedAt). */ private imageCache; private pendingImages; private failedImages; private retryTimers; /** Text nodes collected during the last render (for selection hit-testing). */ textNodes: TextNodeInfo[]; /** Text nodes sorted by vertical position for faster hit prefilter. */ textNodesByY: TextNodeInfo[]; /** Current text selection range, or null if nothing is selected. */ selection: SelectionRange | null; /** Highlighted find matches. */ findHighlights: SelectionRange[]; /** Index of the currently active find match (-1 = none). */ currentFindIndex: number; /** The last rendered tree + layout (for cursor queries). */ lastTree: UIElement | null; lastLayout: ComputedLayout | null; /** * When `layoutInspector` is enabled, optional pointer in layout coordinates * to show `hitPathAtPoint` in the HUD. Set each frame from pointer move (or clear). * Non-finite values and non-numbers are ignored so the HUD omits the hit line (aligned with core hit-test guards). */ inspectorProbe: { x: number; y: number; } | null; /** Increments every `render()`; shown in the layout inspector HUD. */ renderFrame: number; /** Wall time (ms) for the last completed `render()` call, including paint and overlays. */ lastRenderWallMs: number; /** Last `computeLayout` wall time (ms) reported by `createApp` via `setFrameTimings`. */ lastLayoutWallMs: number; private textNodeIndex; constructor(options: CanvasRendererOptions); /** * Same clamping as `createApp` after Yoga: non-finite or negative `layoutMs` become `0` so the * inspector HUD and telemetry never observe NaN/negative layout times. */ setFrameTimings(timings: FrameTimings): void; render(layout: ComputedLayout, tree: UIElement): void; private computeTextNodeLines; private zIndexOf; private getChildrenByZAsc; private paintNode; private paintBox; private paintImage; /** Warm image cache before first paint. */ preloadImages(urls: string[]): void; clearImageCache(): void; getImageCacheStats(): { cached: number; pending: number; failed: number; maxEntries: number; }; private paintImagePlaceholder; private startImageLoad; private enforceImageCacheLimit; private paintText; private getLineSelectionRanges; private paintSelectionHighlight; private paintFindHighlights; private wrapText; private roundRect; private paintLayoutDebug; private countInspectorNodes; private maxInspectorDepth; private paintLayoutInspectorHud; private paintFocusRingForTarget; /** Effective corner radii for the focus ring outline (slightly larger than the box when padded). */ private focusRingBorderRadius; private strokeFocusRingOutline; getSelectedText(): string; setInteractionActive(active: boolean): void; /** Build an accessibility tree for the currently rendered frame. */ getAccessibilityTree(): AccessibilityNode | null; destroy(): void; } /** * Enable text selection and cursor styles on a canvas rendered by a CanvasRenderer. * Returns a cleanup function. */ export declare function enableSelection(canvas: HTMLCanvasElement, renderer: CanvasRenderer, onSelectionChange?: () => void): () => void; /** * Enable Cmd/Ctrl+F find overlay for canvas-rendered text. * Returns a cleanup function. */ export declare function enableFind(canvas: HTMLCanvasElement, renderer: CanvasRenderer): () => void; /** * Mirror canvas semantics into a hidden DOM subtree for assistive tech. * The mirror auto-syncs after every canvas render. */ export declare function enableAccessibilityMirror(host: HTMLElement, renderer: CanvasRenderer, options?: AccessibilityMirrorOptions): () => void; /** * Forward browser pointer/keyboard/composition events into a Geometra app. * Returns a cleanup function. */ export declare function enableInputForwarding(canvas: HTMLCanvasElement, getApp: () => App | null, options?: CanvasInputForwardingOptions): () => void; //# sourceMappingURL=renderer.d.ts.map