import { GaugeType } from "../types/GaugeComponentProps"; import { Dimensions } from "../types/Dimensions"; import { Labels } from "../types/Labels"; /** * Coordinate System Manager for Gauge Component * * This module centralizes all coordinate, dimension, and viewBox calculations * to ensure consistent positioning and optimal space utilization. * * KEY INSIGHT: Padding should be calculated based on ACTUAL gauge configuration, * not worst-case assumptions. This maximizes the usable space for the gauge. */ export interface ViewBox { x: number; y: number; width: number; height: number; toString(): string; } export interface GaugeLayout { viewBox: ViewBox; outerRadius: number; innerRadius: number; gaugeCenter: { x: number; y: number; }; doughnutTransform: { x: number; y: number; }; } /** * Configuration options that affect padding calculations */ export interface PaddingConfig { hasOuterTicks: boolean; hasInnerTicks: boolean; hasTickLabels: boolean; tickLabelFontSize: number; hasValueLabel: boolean; valueLabelFontSize: number; pointerLength: number; } /** * Extract padding configuration from gauge props */ export declare const extractPaddingConfig: (labels?: Labels, pointerLength?: number) => PaddingConfig; /** * Calculates optimal outer radius given available space and gauge type * This is the core function that determines how much space the gauge will use * * CRITICAL: The resulting viewBox must fit within parentWidth x parentHeight */ export declare const calculateOptimalRadius: (parentWidth: number, parentHeight: number, gaugeType: GaugeType, marginPercent?: number) => number; /** * Calculates the viewBox dimensions based on gauge type and radius * ViewBox defines the coordinate system for the SVG */ export declare const calculateViewBox: (outerRadius: number, gaugeType: GaugeType) => ViewBox; /** * Calculates the center point of the gauge within the viewBox * This is where the doughnut element should be positioned */ export declare const calculateGaugeCenter: (viewBox: ViewBox, outerRadius: number, gaugeType: GaugeType) => { x: number; y: number; }; /** * Calculates complete layout information for the gauge * This is the main function used by the rendering code */ export declare const calculateGaugeLayout: (parentWidth: number, parentHeight: number, gaugeType: GaugeType, arcWidth: number, marginPercent?: number) => GaugeLayout; /** * NEW: Calculates optimized layout using dynamic padding based on actual config * This maximizes gauge size by only reserving space that's actually needed */ export declare const calculateOptimizedLayout: (parentWidth: number, parentHeight: number, gaugeType: GaugeType, arcWidth: number, paddingConfig: PaddingConfig, marginPercent?: number) => GaugeLayout; /** * Updates the dimensions object with new layout calculations * This maintains backward compatibility with existing code */ export declare const updateDimensionsFromLayout: (dimensions: Dimensions, layout: GaugeLayout) => void; /** * Validates that a gauge won't cause infinite resizing * Returns true if the layout is stable * * Compares radius, viewBox dimensions, and center position to detect oscillation */ export declare const isLayoutStable: (previousLayout: GaugeLayout | null, currentLayout: GaugeLayout, tolerance?: number) => boolean; /** * TWO-PASS RENDERING: Calculate optimized layout from measured bounds * * After the first render, we measure the actual bounding box of the element. * This tells us exactly how much space the gauge content uses. * We then recalculate the viewBox to fit the content with minimal padding. * * The measured bounds are relative to the element's transform origin (gauge center). * So bounds.x and bounds.y can be negative (content extends left/up from center). */ export declare const calculateLayoutFromMeasuredBounds: (parentWidth: number, parentHeight: number, measuredBounds: { width: number; height: number; x: number; y: number; }, gaugeType: GaugeType, arcWidth: number, currentLayout: GaugeLayout) => GaugeLayout; /** * TWO-PASS RENDERING: Optimized approach using actual measured bounds * * Pass 1: Render with generous initial padding to ensure all content is visible * for accurate measurement. This pass is hidden from the user. * Pass 2: Recalculate viewBox to maximize gauge size while fitting content * * This approach: * 1. Uses generous padding for first pass (hidden) to capture all content * 2. Renders all elements (arcs, labels, pointer) * 3. Measures the actual bounding box of the rendered content * 4. Adjusts the viewBox to tightly fit the content with proper margins */ export declare const calculateTightLayout: (parentWidth: number, parentHeight: number, gaugeType: GaugeType, arcWidth: number, marginPercent?: number) => GaugeLayout;