velo-plot 1.15.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ChartCore-BimVvUEg.js → ChartCore-BhQ4j7f5.js} +2213 -1489
- package/dist/ChartCore-BhQ4j7f5.js.map +1 -0
- package/dist/SciPlot-GJvw7GJo.js +463 -0
- package/dist/SciPlot-GJvw7GJo.js.map +1 -0
- package/dist/assets/downsample.worker-C70QJ04y.js +2 -0
- package/dist/assets/downsample.worker-C70QJ04y.js.map +1 -0
- package/dist/assets/indicator.worker-bv0zC4EX.js +2 -0
- package/dist/assets/indicator.worker-bv0zC4EX.js.map +1 -0
- package/dist/axisFormat-SPX-CD5s.js +200 -0
- package/dist/axisFormat-SPX-CD5s.js.map +1 -0
- package/dist/core/InteractionManager.d.ts +1 -0
- package/dist/core/OverlayRenderer.d.ts +13 -0
- package/dist/core/chart/ChartAlerts.d.ts +42 -0
- package/dist/core/chart/ChartCore.d.ts +24 -1
- package/dist/core/chart/ChartRenderLoop.d.ts +9 -2
- package/dist/core/chart/ChartRenderer.d.ts +8 -2
- package/dist/core/chart/candlestickMarkers.d.ts +23 -0
- package/dist/core/chart/heikinAshi.d.ts +10 -0
- package/dist/core/chart/positionLines.d.ts +12 -0
- package/dist/core/chart/series/types.d.ts +2 -2
- package/dist/core/chart/types.d.ts +9 -0
- package/dist/core/format/axisFormat.d.ts +2 -1
- package/dist/core/indicator/addIndicator.d.ts +36 -0
- package/dist/core/indicator/index.d.ts +2 -0
- package/dist/core/indicator/indicatorPresets.d.ts +45 -0
- package/dist/core/series/Series.d.ts +3 -0
- package/dist/core/stacked/types.d.ts +8 -0
- package/dist/core/time/TimeScale.d.ts +31 -0
- package/dist/core/time/applyTimeScale.d.ts +10 -0
- package/dist/createStackedChart-DJSmqerD.js +706 -0
- package/dist/createStackedChart-DJSmqerD.js.map +1 -0
- package/dist/gpu/adapter/gpuRenderer.d.ts +21 -0
- package/dist/gpu/backends/webgpu/WebGPUBackend.d.ts +2 -1
- package/dist/gpuRenderer-BpaMYz-k.js +1848 -0
- package/dist/gpuRenderer-BpaMYz-k.js.map +1 -0
- package/dist/{index-DjeWClO9.js → index-CWipqOLP.js} +2 -2
- package/dist/{index-DjeWClO9.js.map → index-CWipqOLP.js.map} +1 -1
- package/dist/index-D7dTq6VB.js +503 -0
- package/dist/index-D7dTq6VB.js.map +1 -0
- package/dist/{index-Ce2JgkH_.js → index-DoYxf1cV.js} +86 -43
- package/dist/{index-Ce2JgkH_.js.map → index-DoYxf1cV.js.map} +1 -1
- package/dist/{index.core-C_-CFftD.js → index.core-fpZ1dYN0.js} +3 -3
- package/dist/{index.core-C_-CFftD.js.map → index.core-fpZ1dYN0.js.map} +1 -1
- package/dist/index.d.ts +17 -4
- package/dist/indicators--eJGmVox.js +302 -0
- package/dist/indicators--eJGmVox.js.map +1 -0
- package/dist/mockDatafeed-Cdg5hKEo.js +511 -0
- package/dist/mockDatafeed-Cdg5hKEo.js.map +1 -0
- package/dist/plugins/analysis.js +530 -807
- package/dist/plugins/analysis.js.map +1 -1
- package/dist/plugins/caching.js +26 -21
- package/dist/plugins/caching.js.map +1 -1
- package/dist/plugins/drawing-tools/index.d.ts +29 -0
- package/dist/plugins/drawing-tools/measure.d.ts +21 -0
- package/dist/plugins/drawing-tools/snapToCandle.d.ts +21 -0
- package/dist/plugins/gpu.js +202 -1895
- package/dist/plugins/gpu.js.map +1 -1
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/keyboard/index.d.ts +1 -7
- package/dist/plugins/keyboard.js +1 -1
- package/dist/plugins/lazy-load/types.d.ts +7 -0
- package/dist/plugins/lazy-load.js +131 -108
- package/dist/plugins/lazy-load.js.map +1 -1
- package/dist/plugins/replay/index.d.ts +19 -0
- package/dist/plugins/tools.js +1 -1
- package/dist/plugins/virtualization/types.d.ts +12 -0
- package/dist/plugins/virtualization.js +1 -1
- package/dist/pool-15HMCNv8.js +88 -0
- package/dist/pool-15HMCNv8.js.map +1 -0
- package/dist/react.js +5 -5
- package/dist/renderer/CandlestickRenderer.d.ts +1 -1
- package/dist/renderer/ChartSeriesRenderer.d.ts +6 -0
- package/dist/renderer/GpuChartRenderer.d.ts +23 -0
- package/dist/renderer/index.d.ts +3 -0
- package/dist/renderer/spike/WebGLGridSpike.d.ts +40 -0
- package/dist/testing/baselines/v1.15.0.json.d.ts +51 -0
- package/dist/testing/gridSpikeBenchmark.d.ts +49 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/rendererBenchmark.d.ts +13 -0
- package/dist/testing/stage1BrowserBench.d.ts +42 -0
- package/dist/trading/datafeed.d.ts +48 -0
- package/dist/trading/index.d.ts +29 -0
- package/dist/trading/mockDatafeed.d.ts +9 -0
- package/dist/trading/ohlcvGenerator.d.ts +25 -0
- package/dist/trading.d.ts +1 -0
- package/dist/trading.js +95 -0
- package/dist/trading.js.map +1 -0
- package/dist/types.d.ts +22 -2
- package/dist/velo-plot.full.js +1088 -776
- package/dist/velo-plot.full.js.map +1 -1
- package/dist/velo-plot.js +15 -15
- package/dist/workers/downsample.d.ts +38 -0
- package/dist/workers/downsampleAsync.d.ts +6 -0
- package/dist/workers/indicator.worker.d.ts +32 -0
- package/dist/workers/indicatorsAsync.d.ts +26 -0
- package/dist/workers/pool.d.ts +36 -0
- package/package.json +23 -1
- package/dist/ChartCore-BimVvUEg.js.map +0 -1
- package/dist/axisFormat-B7o_uIEA.js +0 -127
- package/dist/axisFormat-B7o_uIEA.js.map +0 -1
- package/dist/createStackedChart-CjsKcOvX.js +0 -1088
- package/dist/createStackedChart-CjsKcOvX.js.map +0 -1
- package/dist/index-ChgIdk3N.js +0 -229
- package/dist/index-ChgIdk3N.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-DjeWClO9.js","sources":["../src/plugins/tools/delta-tool/index.ts","../src/plugins/tools/peak-tool/index.ts","../src/plugins/tools/tooltip/themes.ts","../src/plugins/tools/tooltip/TooltipPositioner.ts","../src/plugins/tools/tooltip/TooltipRenderer.ts","../src/plugins/tools/tooltip/format.ts","../src/plugins/tools/tooltip/templates/DefaultTemplate.ts","../src/plugins/tools/tooltip/templates/MinimalTemplate.ts","../src/plugins/tools/tooltip/templates/CrosshairTemplate.ts","../src/plugins/tools/tooltip/templates/HeatmapTemplate.ts","../src/plugins/tools/tooltip/templates/ScientificTemplate.ts","../src/plugins/tools/tooltip/templates/AnnotationTemplate.ts","../src/plugins/tools/tooltip/templates/RangeTemplate.ts","../src/plugins/tools/tooltip/templates/index.ts","../src/plugins/tools/tooltip/TooltipManager.ts","../src/plugins/tools/index.ts"],"sourcesContent":["/**\n * Sci Plot - Delta Tool Module\n * \n * Provides interactive measurement tool for measuring distances,\n * differences, and slopes between two data points on the chart.\n * \n * Features:\n * - Click to select first point (snaps to nearest data point)\n * - Click to select second point \n * - Highlight points on hover\n * - Show delta measurements between points\n * \n * @module delta-tool\n */\n\nimport type { DeltaMeasurement, Bounds } from '../../../types';\nimport type { AnimationEngine } from '../../../core/animation';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface DeltaToolOptions {\n /** Line color for measurement (default: '#ff6b6b') */\n lineColor?: string;\n /** Line width in pixels (default: 2) */\n lineWidth?: number;\n /** Show labels at measurement points (default: true) */\n showLabels?: boolean;\n /** Label font size (default: 12) */\n labelFontSize?: number;\n /** Label background color (default: 'rgba(0,0,0,0.8)') */\n labelBackground?: string;\n /** Label text color (default: '#ffffff') */\n labelColor?: string;\n /** Show delta values inline (default: true) */\n showDelta?: boolean;\n /** Number precision for values (default: 4) */\n precision?: number;\n /** Show slope value (default: true) */\n showSlope?: boolean;\n /** Show distance value (default: true) */\n showDistance?: boolean;\n /** Custom CSS class for overlay elements */\n className?: string;\n /** Point highlight size when hovering (default: 10) */\n highlightSize?: number;\n /** Point highlight color (default: '#00f2ff') */\n highlightColor?: string;\n /** Snap radius in pixels for detecting nearby points (default: 20) */\n snapRadius?: number;\n}\n\n/** Data point with series information */\nexport interface DataPoint {\n x: number;\n y: number;\n seriesId: string;\n yAxisId?: string;\n index: number;\n pixelX: number;\n pixelY: number;\n}\n\nexport interface DeltaToolState {\n /** Whether the tool is enabled */\n enabled: boolean;\n /** Selection state: 'idle' | 'waitingSecond' | 'complete' */\n selectionState: 'idle' | 'waitingSecond' | 'complete';\n /** First selected point */\n point1: DataPoint | null;\n /** Second selected point */\n point2: DataPoint | null;\n /** Currently hovered point (for highlighting) */\n hoveredPoint: DataPoint | null;\n /** Last completed measurement */\n lastMeasurement: DeltaMeasurement | null;\n}\n\nexport interface SeriesData {\n id: string;\n x: Float32Array | Float64Array | number[];\n y: Float32Array | Float64Array | number[];\n yAxisId?: string;\n}\n\nexport interface DeltaToolContext {\n container: HTMLElement;\n getPlotArea: () => { x: number; y: number; width: number; height: number };\n getViewBounds: () => Bounds;\n getYBounds?: (yAxisId?: string) => { yMin: number; yMax: number };\n requestRender: () => void;\n getSeries?: () => SeriesData[];\n onMeasure?: (measurement: DeltaMeasurement) => void;\n animationEngine?: AnimationEngine;\n}\n\n// ============================================\n// Delta Tool Implementation\n// ============================================\n\nexport class DeltaTool {\n private ctx: DeltaToolContext;\n private options: Required<DeltaToolOptions>;\n private state: DeltaToolState = {\n enabled: false,\n selectionState: 'idle',\n point1: null,\n point2: null,\n hoveredPoint: null,\n lastMeasurement: null,\n };\n\n private overlayCanvas: HTMLCanvasElement | null = null;\n private overlayCtx: CanvasRenderingContext2D | null = null;\n\n // Label dragging\n private labelOffset: { x: number; y: number } = { x: 15, y: 0 };\n private isDraggingLabel = false;\n private labelBounds: { x: number; y: number; width: number; height: number } | null = null;\n private dragStart: { x: number; y: number } = { x: 0, y: 0 };\n private crosshairPosition: { x: number; y: number } | null = null;\n\n // Bound handlers\n private boundMouseMove: (e: MouseEvent) => void;\n private boundClick: (e: MouseEvent) => void;\n private boundKeyDown: (e: KeyboardEvent) => void;\n private boundMouseDown: (e: MouseEvent) => void;\n private boundMouseUp: (e: MouseEvent) => void;\n private boundResize: () => void;\n\n constructor(context: DeltaToolContext, options?: DeltaToolOptions) {\n this.ctx = context;\n this.options = {\n lineColor: '#ff6b6b',\n lineWidth: 2,\n showLabels: true,\n labelFontSize: 12,\n labelBackground: 'rgba(0, 0, 0, 0.85)',\n labelColor: '#ffffff',\n showDelta: true,\n precision: 4,\n showSlope: true,\n showDistance: true,\n className: 'velo-plot-delta-tool',\n highlightSize: 12,\n highlightColor: '#00f2ff',\n snapRadius: 30,\n ...options,\n };\n\n this.boundMouseMove = this.handleMouseMove.bind(this);\n this.boundClick = this.handleClick.bind(this);\n this.boundKeyDown = this.handleKeyDown.bind(this);\n this.boundMouseDown = this.handleLabelMouseDown.bind(this);\n this.boundMouseUp = this.handleLabelMouseUp.bind(this);\n this.boundResize = this.resizeOverlay.bind(this);\n }\n\n /**\n * Enable the delta measurement tool\n */\n enable(): void {\n if (this.state.enabled) return;\n\n this.state.enabled = true;\n this.state.selectionState = 'idle';\n this.createOverlay();\n this.attachListeners();\n this.ctx.container.style.cursor = 'crosshair';\n \n }\n\n /**\n * Disable the delta measurement tool\n */\n disable(): void {\n if (!this.state.enabled) return;\n\n this.state.enabled = false;\n this.state.selectionState = 'idle';\n this.state.point1 = null;\n this.state.point2 = null;\n this.state.hoveredPoint = null;\n\n this.detachListeners();\n this.destroyOverlay();\n this.ctx.container.style.cursor = '';\n }\n\n /**\n * Toggle the tool on/off\n */\n toggle(): void {\n if (this.state.enabled) {\n this.disable();\n } else {\n this.enable();\n }\n }\n\n /**\n * Check if tool is enabled\n */\n isEnabled(): boolean {\n return this.state.enabled;\n }\n\n /**\n * Get the current state\n */\n getState(): DeltaToolState {\n return { ...this.state };\n }\n\n /**\n * Get the last completed measurement\n */\n getMeasurement(): DeltaMeasurement | null {\n return this.state.lastMeasurement;\n }\n\n /**\n * Clear the current measurement\n */\n clear(): void {\n this.state.point1 = null;\n this.state.point2 = null;\n this.state.selectionState = 'idle';\n this.state.lastMeasurement = null;\n this.labelBounds = null;\n this.labelOffset = { x: 15, y: 0 };\n this.renderOverlay();\n }\n\n /**\n * Destroy the tool and cleanup\n */\n destroy(): void {\n this.disable();\n this.state.lastMeasurement = null;\n }\n\n /**\n * Recalculate measurements (useful if data changes)\n */\n public recalculate(): void {\n if (!this.state.point1 || !this.state.point2) return;\n\n // Refresh data points from series\n const seriesList = this.ctx.getSeries ? this.ctx.getSeries() : [];\n\n const updatePoint = (p: DataPoint) => {\n const s = seriesList.find(ser => ser.id === p.seriesId);\n if (s && p.index < s.x.length) {\n p.x = s.x[p.index];\n p.y = s.y[p.index];\n p.yAxisId = s.yAxisId;\n\n // Update pixel coordinates\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(s.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n return true;\n }\n return false;\n };\n\n const p1Valid = updatePoint(this.state.point1);\n const p2Valid = updatePoint(this.state.point2);\n\n if (p1Valid && p2Valid) {\n this.state.lastMeasurement = this.calculateMeasurement();\n if (this.ctx.onMeasure) {\n this.ctx.onMeasure(this.state.lastMeasurement);\n }\n } else {\n this.clear();\n }\n\n this.renderOverlay();\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private createOverlay(): void {\n if (this.overlayCanvas) return;\n\n this.overlayCanvas = document.createElement('canvas');\n this.overlayCanvas.className = this.options.className;\n this.overlayCanvas.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 1000;\n `;\n\n this.resizeOverlay();\n this.overlayCtx = this.overlayCanvas.getContext('2d');\n this.ctx.container.appendChild(this.overlayCanvas);\n }\n\n private resizeOverlay(): void {\n if (!this.overlayCanvas) return;\n const rect = this.ctx.container.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n this.overlayCanvas.width = rect.width * dpr;\n this.overlayCanvas.height = rect.height * dpr;\n if (this.overlayCtx) {\n this.overlayCtx.setTransform(1, 0, 0, 1, 0, 0);\n this.overlayCtx.scale(dpr, dpr);\n }\n }\n\n private destroyOverlay(): void {\n if (this.overlayCanvas && this.overlayCanvas.parentNode) {\n this.overlayCanvas.parentNode.removeChild(this.overlayCanvas);\n }\n this.overlayCanvas = null;\n this.overlayCtx = null;\n }\n\n private attachListeners(): void {\n // Use capture phase to get events before InteractionManager\n this.ctx.container.addEventListener('mousemove', this.boundMouseMove, true);\n this.ctx.container.addEventListener('mousedown', this.boundClick, true);\n this.ctx.container.addEventListener('mousedown', this.boundMouseDown, true);\n this.ctx.container.addEventListener('mouseup', this.boundMouseUp, true);\n window.addEventListener('resize', this.boundResize);\n document.addEventListener('keydown', this.boundKeyDown);\n }\n\n private detachListeners(): void {\n this.ctx.container.removeEventListener('mousemove', this.boundMouseMove, true);\n this.ctx.container.removeEventListener('mousedown', this.boundClick, true);\n this.ctx.container.removeEventListener('mousedown', this.boundMouseDown, true);\n this.ctx.container.removeEventListener('mouseup', this.boundMouseUp, true);\n window.removeEventListener('resize', this.boundResize);\n document.removeEventListener('keydown', this.boundKeyDown);\n }\n\n private handleMouseMove(e: MouseEvent): void {\n if (!this.state.enabled) return;\n\n const rect = this.ctx.container.getBoundingClientRect();\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n // Handle label dragging\n if (this.isDraggingLabel) {\n this.labelOffset.x += pixelX - this.dragStart.x;\n this.labelOffset.y += pixelY - this.dragStart.y;\n this.dragStart = { x: pixelX, y: pixelY };\n this.renderOverlay();\n return;\n }\n\n // Update cursor if over label\n if (this.labelBounds &&\n pixelX >= this.labelBounds.x && pixelX <= this.labelBounds.x + this.labelBounds.width &&\n pixelY >= this.labelBounds.y && pixelY <= this.labelBounds.y + this.labelBounds.height) {\n this.ctx.container.style.cursor = 'move';\n } else {\n this.ctx.container.style.cursor = 'crosshair';\n }\n\n // Check if inside plot area\n if (\n pixelX < plotArea.x ||\n pixelX > plotArea.x + plotArea.width ||\n pixelY < plotArea.y ||\n pixelY > plotArea.y + plotArea.height\n ) {\n this.state.hoveredPoint = null;\n this.crosshairPosition = null;\n this.renderOverlay();\n return;\n }\n\n // Store current mouse position for crosshair\n this.crosshairPosition = { x: pixelX, y: pixelY };\n\n // Find nearest data point\n const nearestPoint = this.findNearestPoint(pixelX, pixelY, plotArea, bounds);\n this.state.hoveredPoint = nearestPoint;\n this.renderOverlay();\n }\n\n private handleLabelMouseDown(e: MouseEvent): void {\n if (!this.state.enabled || !this.labelBounds) return;\n\n const rect = this.ctx.container.getBoundingClientRect();\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n if (pixelX >= this.labelBounds.x && pixelX <= this.labelBounds.x + this.labelBounds.width &&\n pixelY >= this.labelBounds.y && pixelY <= this.labelBounds.y + this.labelBounds.height) {\n this.isDraggingLabel = true;\n this.dragStart = { x: pixelX, y: pixelY };\n e.stopPropagation();\n e.preventDefault();\n }\n }\n\n private handleLabelMouseUp(): void {\n this.isDraggingLabel = false;\n }\n\n private async handleClick(e: MouseEvent): Promise<void> {\n if (!this.state.enabled) return;\n\n // If chart is animating, wait for it to settle to get accurate coordinates\n if (this.ctx.animationEngine?.isAnimating()) {\n await this.ctx.animationEngine.waitForIdle();\n }\n\n // Stop propagation to prevent InteractionManager from handling this\n e.stopPropagation();\n e.preventDefault();\n\n const rect = this.ctx.container.getBoundingClientRect();\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n // Check if inside plot area\n if (\n pixelX < plotArea.x ||\n pixelX > plotArea.x + plotArea.width ||\n pixelY < plotArea.y ||\n pixelY > plotArea.y + plotArea.height\n ) {\n return;\n }\n\n // Find nearest data point\n const nearestPoint = this.findNearestPoint(pixelX, pixelY, plotArea, bounds);\n\n if (!nearestPoint) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n if (this.state.selectionState === 'idle' || this.state.selectionState === 'complete') {\n // Select first point\n this.state.point1 = nearestPoint;\n this.state.point2 = null;\n this.state.selectionState = 'waitingSecond';\n this.state.lastMeasurement = null;\n } else if (this.state.selectionState === 'waitingSecond') {\n // Select second point\n this.state.point2 = nearestPoint;\n this.state.selectionState = 'complete';\n\n // Calculate measurement\n const measurement = this.calculateMeasurement();\n this.state.lastMeasurement = measurement;\n\n if (this.ctx.onMeasure) {\n this.ctx.onMeasure(measurement);\n }\n }\n\n this.renderOverlay();\n }\n\n private handleKeyDown(e: KeyboardEvent): void {\n if (e.key === 'Escape' && this.state.enabled) {\n this.clear();\n }\n }\n\n private findNearestPoint(\n pixelX: number,\n pixelY: number,\n plotArea: { x: number; y: number; width: number; height: number },\n bounds: Bounds\n ): DataPoint | null {\n if (!this.ctx.getSeries) return null;\n\n const series = this.ctx.getSeries();\n let nearestPoint: DataPoint | null = null;\n let minDistance = this.options.snapRadius;\n\n for (const s of series) {\n const xData = s.x;\n const yData = s.y;\n const len = Math.min(xData.length, yData.length);\n\n // Get Y bounds for this series (may be different if using secondary Y axis)\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(s.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n\n for (let i = 0; i < len; i++) {\n const dataX = xData[i];\n const dataY = yData[i];\n\n // Convert data to pixel coordinates\n const px = plotArea.x + ((dataX - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n const py = plotArea.y + (1 - (dataY - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n\n // Skip if outside visible range\n if (px < plotArea.x || px > plotArea.x + plotArea.width) continue;\n if (py < plotArea.y || py > plotArea.y + plotArea.height) continue;\n\n const distance = Math.sqrt((pixelX - px) ** 2 + (pixelY - py) ** 2);\n\n if (distance < minDistance) {\n minDistance = distance;\n nearestPoint = {\n x: dataX,\n y: dataY,\n seriesId: s.id,\n yAxisId: s.yAxisId,\n index: i,\n pixelX: px,\n pixelY: py,\n };\n }\n }\n }\n\n return nearestPoint;\n }\n\n private calculateMeasurement(): DeltaMeasurement {\n const p1 = this.state.point1!;\n const p2 = this.state.point2!;\n\n const deltaX = p2.x - p1.x;\n const deltaY = p2.y - p1.y;\n const slope = deltaX !== 0 ? deltaY / deltaX : Infinity;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n\n return {\n x1: p1.x,\n y1: p1.y,\n x2: p2.x,\n y2: p2.y,\n deltaX,\n deltaY,\n slope,\n distance,\n pixelX1: p1.pixelX,\n pixelY1: p1.pixelY,\n pixelX2: p2.pixelX,\n pixelY2: p2.pixelY,\n };\n }\n\n public renderOverlay(): void {\n if (!this.overlayCtx || !this.overlayCanvas) return;\n\n // Resize if needed\n this.resizeOverlay();\n\n const rect = this.ctx.container.getBoundingClientRect();\n this.overlayCtx.clearRect(0, 0, rect.width, rect.height);\n\n const opts = this.options;\n const ctx = this.overlayCtx;\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n // Update pixel coordinates of selected points to follow zoom/pan\n if (this.state.point1) {\n const p = this.state.point1;\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(p.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n }\n if (this.state.point2) {\n const p = this.state.point2;\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(p.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n }\n\n // Draw crosshair lines (dotted lines from cursor to axes)\n if (this.crosshairPosition && this.state.selectionState !== 'complete') {\n const cx = this.crosshairPosition.x;\n const cy = this.crosshairPosition.y;\n\n ctx.save();\n ctx.setLineDash([4, 4]);\n ctx.strokeStyle = 'rgba(150, 150, 150, 0.7)';\n ctx.lineWidth = 1;\n\n // Vertical line (to X axis)\n ctx.beginPath();\n ctx.moveTo(cx, plotArea.y);\n ctx.lineTo(cx, plotArea.y + plotArea.height);\n ctx.stroke();\n\n // Horizontal line (to Y axis)\n ctx.beginPath();\n ctx.moveTo(plotArea.x, cy);\n ctx.lineTo(plotArea.x + plotArea.width, cy);\n ctx.stroke();\n\n ctx.restore();\n }\n\n // Draw hovered point highlight (pulsing effect)\n if (this.state.hoveredPoint && this.state.selectionState !== 'complete') {\n const hp = this.state.hoveredPoint;\n\n // Outer glow\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, opts.highlightSize + 4, 0, Math.PI * 2);\n ctx.fillStyle = opts.highlightColor + '30';\n ctx.fill();\n\n // Main highlight\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.strokeStyle = opts.highlightColor;\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Center dot\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, 4, 0, Math.PI * 2);\n ctx.fillStyle = opts.highlightColor;\n ctx.fill();\n\n // Show coordinates tooltip\n this.drawPointTooltip(ctx, hp, 'Hover');\n }\n\n // Draw selected point 1\n if (this.state.point1) {\n const p1 = this.state.point1;\n\n // Selected point marker\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.fillStyle = opts.lineColor;\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, opts.highlightSize - 3, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, 3, 0, Math.PI * 2);\n ctx.fillStyle = opts.lineColor;\n ctx.fill();\n\n // Label for point 1\n this.drawPointLabel(ctx, p1.pixelX, p1.pixelY - opts.highlightSize - 8, 'P1', opts.lineColor);\n }\n\n // Draw selected point 2\n if (this.state.point2) {\n const p2 = this.state.point2;\n\n // Selected point marker\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.fillStyle = '#4ade80';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, opts.highlightSize - 3, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, 3, 0, Math.PI * 2);\n ctx.fillStyle = '#4ade80';\n ctx.fill();\n\n // Label for point 2\n this.drawPointLabel(ctx, p2.pixelX, p2.pixelY - opts.highlightSize - 8, 'P2', '#4ade80');\n }\n\n // Draw measurement line between points\n if (this.state.point1 && this.state.point2) {\n const p1 = this.state.point1;\n const p2 = this.state.point2;\n\n // Dashed line connecting points\n ctx.beginPath();\n ctx.moveTo(p1.pixelX, p1.pixelY);\n ctx.lineTo(p2.pixelX, p2.pixelY);\n ctx.strokeStyle = opts.lineColor;\n ctx.lineWidth = opts.lineWidth;\n ctx.setLineDash([6, 4]);\n ctx.stroke();\n ctx.setLineDash([]);\n\n // Delta lines (horizontal and vertical)\n ctx.beginPath();\n ctx.moveTo(p1.pixelX, p1.pixelY);\n ctx.lineTo(p2.pixelX, p1.pixelY);\n ctx.lineTo(p2.pixelX, p2.pixelY);\n ctx.strokeStyle = 'rgba(255, 107, 107, 0.4)';\n ctx.lineWidth = 1;\n ctx.setLineDash([3, 3]);\n ctx.stroke();\n ctx.setLineDash([]);\n\n // Draw measurement label\n if (opts.showLabels && this.state.lastMeasurement) {\n this.drawMeasurementLabel(ctx, p1, p2, this.state.lastMeasurement);\n }\n }\n\n // Draw status indicator\n this.drawStatusIndicator(ctx);\n }\n\n private drawPointTooltip(\n ctx: CanvasRenderingContext2D,\n point: DataPoint,\n label: string\n ): void {\n const opts = this.options;\n const text = `${label}: (${this.formatValue(point.x)}, ${this.formatValue(point.y)})`;\n\n ctx.font = `${opts.labelFontSize}px system-ui, sans-serif`;\n const metrics = ctx.measureText(text);\n const padding = 6;\n const boxWidth = metrics.width + padding * 2;\n const boxHeight = opts.labelFontSize + padding * 2;\n\n let boxX = point.pixelX + 15;\n let boxY = point.pixelY - boxHeight / 2;\n\n // Keep within container\n const rect = this.ctx.container.getBoundingClientRect();\n if (boxX + boxWidth > rect.width) boxX = point.pixelX - boxWidth - 15;\n if (boxY < 0) boxY = 5;\n if (boxY + boxHeight > rect.height) boxY = rect.height - boxHeight - 5;\n\n // Background\n ctx.fillStyle = opts.labelBackground;\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 4);\n ctx.fill();\n\n // Text\n ctx.fillStyle = opts.labelColor;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(text, boxX + padding, boxY + boxHeight / 2);\n }\n\n private drawPointLabel(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n label: string,\n color: string\n ): void {\n const opts = this.options;\n ctx.font = `bold ${opts.labelFontSize}px system-ui, sans-serif`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'bottom';\n\n // Background pill\n const metrics = ctx.measureText(label);\n const padding = 4;\n const pillWidth = metrics.width + padding * 2;\n const pillHeight = opts.labelFontSize + padding;\n\n ctx.fillStyle = color;\n this.roundRect(ctx, x - pillWidth / 2, y - pillHeight, pillWidth, pillHeight, 3);\n ctx.fill();\n\n // Text\n ctx.fillStyle = '#ffffff';\n ctx.fillText(label, x, y - 2);\n }\n\n private drawMeasurementLabel(\n ctx: CanvasRenderingContext2D,\n p1: DataPoint,\n p2: DataPoint,\n m: DeltaMeasurement\n ): void {\n const opts = this.options;\n const midX = (p1.pixelX + p2.pixelX) / 2;\n const midY = (p1.pixelY + p2.pixelY) / 2;\n\n const lines: string[] = [];\n\n if (opts.showDelta) {\n lines.push(`ΔX: ${this.formatValue(m.deltaX)}`);\n lines.push(`ΔY: ${this.formatValue(m.deltaY)}`);\n }\n\n if (opts.showSlope && isFinite(m.slope)) {\n lines.push(`Slope: ${this.formatValue(m.slope)}`);\n }\n\n if (opts.showDistance) {\n lines.push(`Distance: ${this.formatValue(m.distance)}`);\n }\n\n const lineHeight = opts.labelFontSize + 4;\n const padding = 10;\n const boxWidth = 170;\n const boxHeight = lines.length * lineHeight + padding * 2;\n\n // Position box using offset from midpoint\n let boxX = midX + this.labelOffset.x;\n let boxY = midY + this.labelOffset.y;\n\n // Keep within bounds\n const container = this.ctx.container.getBoundingClientRect();\n if (boxX < 0) boxX = 0;\n if (boxX + boxWidth > container.width) boxX = container.width - boxWidth;\n if (boxY < 0) boxY = 0;\n if (boxY + boxHeight > container.height) boxY = container.height - boxHeight;\n\n // Store bounds for hit testing\n this.labelBounds = { x: boxX, y: boxY, width: boxWidth, height: boxHeight };\n\n // Draw box with border\n ctx.fillStyle = opts.labelBackground;\n ctx.strokeStyle = opts.lineColor;\n ctx.lineWidth = 2;\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 8);\n ctx.fill();\n ctx.stroke();\n\n // Draw text\n ctx.fillStyle = opts.labelColor;\n ctx.font = `${opts.labelFontSize}px system-ui, sans-serif`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n\n lines.forEach((line, i) => {\n ctx.fillText(line, boxX + padding, boxY + padding + i * lineHeight);\n });\n }\n\n private drawStatusIndicator(\n ctx: CanvasRenderingContext2D\n ): void {\n const opts = this.options;\n const plotArea = this.ctx.getPlotArea();\n\n let statusText = '';\n let statusColor = '#666';\n\n if (this.state.selectionState === 'idle') {\n statusText = '📏 Click a point to start measuring';\n statusColor = opts.highlightColor;\n } else if (this.state.selectionState === 'waitingSecond') {\n statusText = '📏 Click second point to complete';\n statusColor = '#f59e0b';\n } else if (this.state.selectionState === 'complete') {\n statusText = '📏 Measurement complete (ESC to clear)';\n statusColor = '#4ade80';\n }\n\n if (!statusText) return;\n\n ctx.font = `12px system-ui, sans-serif`;\n const metrics = ctx.measureText(statusText);\n const padding = 8;\n const boxWidth = metrics.width + padding * 2;\n const boxHeight = 24;\n const boxX = plotArea.x + 10;\n const boxY = plotArea.y + 10;\n\n // Background\n ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 4);\n ctx.fill();\n\n // Status dot\n ctx.beginPath();\n ctx.arc(boxX + 16, boxY + boxHeight / 2, 4, 0, Math.PI * 2);\n ctx.fillStyle = statusColor;\n ctx.fill();\n\n // Text\n ctx.fillStyle = '#fff';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(statusText, boxX + 26, boxY + boxHeight / 2);\n }\n\n private roundRect(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n r: number\n ): void {\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + w - r, y);\n ctx.quadraticCurveTo(x + w, y, x + w, y + r);\n ctx.lineTo(x + w, y + h - r);\n ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\n ctx.lineTo(x + r, y + h);\n ctx.quadraticCurveTo(x, y + h, x, y + h - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n }\n\n private formatValue(val: number): string {\n const abs = Math.abs(val);\n if (abs === 0) return '0';\n if (abs >= 1e6 || abs < 0.001) {\n return val.toExponential(this.options.precision - 1);\n }\n return val.toPrecision(this.options.precision);\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\n/**\n * Create a delta tool for a chart context\n */\nexport function createDeltaTool(\n context: DeltaToolContext,\n options?: DeltaToolOptions\n): DeltaTool {\n return new DeltaTool(context, options);\n}\n","/**\n * Sci Plot - Peak Tool Module\n * \n * Provides interactive measurement tool for measuring distances,\n * differences, and slopes between two data points on the chart.\n * \n * Features:\n * - Click to select first point (snaps to nearest data point)\n * - Click to select second point \n * - Highlight points on hover\n * - Show peak measurements between points\n * \n * @module peak-tool\n */\n\nimport type { PeakMeasurement, Bounds } from '../../../types';\nimport type { AnimationEngine } from '../../../core/animation';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface PeakToolOptions {\n /** Line color for measurement (default: '#ff6b6b') */\n lineColor?: string;\n /** Line width in pixels (default: 2) */\n lineWidth?: number;\n /** Show labels at measurement points (default: true) */\n showLabels?: boolean;\n /** Label font size (default: 12) */\n labelFontSize?: number;\n /** Label background color (default: 'rgba(0,0,0,0.8)') */\n labelBackground?: string;\n /** Label text color (default: '#ffffff') */\n labelColor?: string;\n /** Show peak values inline (default: true) */\n showPeak?: boolean;\n /** Number precision for values (default: 4) */\n precision?: number;\n /** Custom CSS class for overlay elements */\n className?: string;\n /** Number of points to use for baseline regression (default: 10) */\n baselineWindow?: number;\n /** Area fill color (default: 'rgba(255, 107, 107, 0.3)') */\n areaFill?: string;\n /** Point highlight size when hovering (default: 10) */\n highlightSize?: number;\n /** Point highlight color (default: '#00f2ff') */\n highlightColor?: string;\n /** Snap radius in pixels for detecting nearby points (default: 20) */\n snapRadius?: number;\n}\n\n/** Data point with series information */\nexport interface DataPoint {\n x: number;\n y: number;\n seriesId: string;\n yAxisId?: string;\n index: number;\n pixelX: number;\n pixelY: number;\n}\n\nexport interface PeakToolState {\n /** Whether the tool is enabled */\n enabled: boolean;\n /** Selection state: 'idle' | 'waitingSecond' | 'complete' */\n selectionState: 'idle' | 'waitingSecond' | 'complete';\n /** First selected point */\n point1: DataPoint | null;\n /** Second selected point */\n point2: DataPoint | null;\n /** Currently hovered point (for highlighting) */\n hoveredPoint: DataPoint | null;\n /** Last completed measurement */\n lastMeasurement: PeakMeasurement | null;\n}\n\nexport interface SeriesData {\n id: string;\n x: Float32Array | Float64Array | number[];\n y: Float32Array | Float64Array | number[];\n yAxisId?: string;\n}\n\nexport interface PeakToolContext {\n container: HTMLElement;\n getPlotArea: () => { x: number; y: number; width: number; height: number };\n getViewBounds: () => Bounds;\n getYBounds?: (yAxisId?: string) => { yMin: number; yMax: number };\n requestRender: () => void;\n getSeries?: () => SeriesData[];\n onMeasure?: (measurement: PeakMeasurement) => void;\n animationEngine?: AnimationEngine;\n}\n\n// ============================================\n// Peak Tool Implementation\n// ============================================\n\nexport class PeakTool {\n private ctx: PeakToolContext;\n private options: Required<PeakToolOptions>;\n private state: PeakToolState = {\n enabled: false,\n selectionState: 'idle',\n point1: null,\n point2: null,\n hoveredPoint: null,\n lastMeasurement: null,\n };\n\n private overlayCanvas: HTMLCanvasElement | null = null;\n private overlayCtx: CanvasRenderingContext2D | null = null;\n\n // Label dragging\n private labelOffset: { x: number; y: number } = { x: 15, y: 0 };\n private isDraggingLabel = false;\n private labelBounds: { x: number; y: number; width: number; height: number } | null = null;\n private dragStart: { x: number; y: number } = { x: 0, y: 0 };\n private crosshairPosition: { x: number; y: number } | null = null;\n\n // Bound handlers\n private boundMouseMove: (e: MouseEvent) => void;\n private boundClick: (e: MouseEvent) => void;\n private boundKeyDown: (e: KeyboardEvent) => void;\n private boundMouseDown: (e: MouseEvent) => void;\n private boundMouseUp: (e: MouseEvent) => void;\n private boundResize: () => void;\n\n constructor(context: PeakToolContext, options?: PeakToolOptions) {\n this.ctx = context;\n this.options = {\n lineColor: '#ff6b6b',\n lineWidth: 2,\n showLabels: true,\n labelFontSize: 12,\n labelBackground: 'rgba(0, 0, 0, 0.85)',\n labelColor: '#ffffff',\n showPeak: true,\n precision: 4,\n className: 'velo-plot-peak-tool',\n highlightSize: 12,\n highlightColor: '#00f2ff',\n snapRadius: 30,\n baselineWindow: 10,\n areaFill: 'rgba(255, 107, 107, 0.3)',\n ...options,\n };\n\n this.boundMouseMove = this.handleMouseMove.bind(this);\n this.boundClick = this.handleClick.bind(this);\n this.boundKeyDown = this.handleKeyDown.bind(this);\n this.boundMouseDown = this.handleLabelMouseDown.bind(this);\n this.boundMouseUp = this.handleLabelMouseUp.bind(this);\n this.boundResize = this.resizeOverlay.bind(this);\n }\n\n /**\n * Enable the peak measurement tool\n */\n enable(): void {\n if (this.state.enabled) return;\n\n this.state.enabled = true;\n this.state.selectionState = 'idle';\n this.createOverlay();\n this.attachListeners();\n this.ctx.container.style.cursor = 'crosshair';\n }\n\n /**\n * Disable the peak measurement tool\n */\n disable(): void {\n if (!this.state.enabled) return;\n\n this.state.enabled = false;\n this.state.selectionState = 'idle';\n this.state.point1 = null;\n this.state.point2 = null;\n this.state.hoveredPoint = null;\n\n this.detachListeners();\n this.destroyOverlay();\n this.ctx.container.style.cursor = '';\n }\n\n /**\n * Toggle the tool on/off\n */\n toggle(): void {\n if (this.state.enabled) {\n this.disable();\n } else {\n this.enable();\n }\n }\n\n /**\n * Check if tool is enabled\n */\n isEnabled(): boolean {\n return this.state.enabled;\n }\n\n /**\n * Get the current state\n */\n getState(): PeakToolState {\n return { ...this.state };\n }\n\n /**\n * Get the last completed measurement\n */\n getMeasurement(): PeakMeasurement | null {\n return this.state.lastMeasurement;\n }\n\n /**\n * Clear the current measurement\n */\n clear(): void {\n this.state.point1 = null;\n this.state.point2 = null;\n this.state.selectionState = 'idle';\n this.state.lastMeasurement = null;\n this.labelBounds = null;\n this.labelOffset = { x: 15, y: 0 };\n this.renderOverlay();\n }\n\n /**\n * Destroy the tool and cleanup\n */\n destroy(): void {\n this.disable();\n this.state.lastMeasurement = null;\n }\n\n /**\n * Recalculate measurements (useful if data changes)\n */\n public recalculate(): void {\n if (!this.state.point1 || !this.state.point2) return;\n\n // Refresh data points from series\n const seriesList = this.ctx.getSeries ? this.ctx.getSeries() : [];\n\n const updatePoint = (p: DataPoint) => {\n const s = seriesList.find(ser => ser.id === p.seriesId);\n if (s && p.index < s.x.length) {\n p.x = s.x[p.index];\n p.y = s.y[p.index];\n p.yAxisId = s.yAxisId;\n\n // Update pixel coordinates\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(s.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n return true;\n }\n return false;\n };\n\n const p1Valid = updatePoint(this.state.point1);\n const p2Valid = updatePoint(this.state.point2);\n\n if (p1Valid && p2Valid) {\n this.state.lastMeasurement = this.calculateMeasurement();\n if (this.ctx.onMeasure) {\n this.ctx.onMeasure(this.state.lastMeasurement);\n }\n } else {\n this.clear();\n }\n\n this.renderOverlay();\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private createOverlay(): void {\n if (this.overlayCanvas) return;\n\n this.overlayCanvas = document.createElement('canvas');\n this.overlayCanvas.className = this.options.className;\n this.overlayCanvas.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 1000;\n `;\n\n this.resizeOverlay();\n this.overlayCtx = this.overlayCanvas.getContext('2d');\n this.ctx.container.appendChild(this.overlayCanvas);\n }\n\n private resizeOverlay(): void {\n if (!this.overlayCanvas) return;\n const rect = this.ctx.container.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n this.overlayCanvas.width = rect.width * dpr;\n this.overlayCanvas.height = rect.height * dpr;\n if (this.overlayCtx) {\n this.overlayCtx.setTransform(1, 0, 0, 1, 0, 0);\n this.overlayCtx.scale(dpr, dpr);\n }\n }\n\n private destroyOverlay(): void {\n if (this.overlayCanvas && this.overlayCanvas.parentNode) {\n this.overlayCanvas.parentNode.removeChild(this.overlayCanvas);\n }\n this.overlayCanvas = null;\n this.overlayCtx = null;\n }\n\n private attachListeners(): void {\n // Use capture phase to get events before InteractionManager\n this.ctx.container.addEventListener('mousemove', this.boundMouseMove, true);\n this.ctx.container.addEventListener('mousedown', this.boundClick, true);\n this.ctx.container.addEventListener('mousedown', this.boundMouseDown, true);\n this.ctx.container.addEventListener('mouseup', this.boundMouseUp, true);\n window.addEventListener('resize', this.boundResize);\n document.addEventListener('keydown', this.boundKeyDown);\n }\n\n private detachListeners(): void {\n this.ctx.container.removeEventListener('mousemove', this.boundMouseMove, true);\n this.ctx.container.removeEventListener('mousedown', this.boundClick, true);\n this.ctx.container.removeEventListener('mousedown', this.boundMouseDown, true);\n this.ctx.container.removeEventListener('mouseup', this.boundMouseUp, true);\n window.removeEventListener('resize', this.boundResize);\n document.removeEventListener('keydown', this.boundKeyDown);\n }\n\n private handleMouseMove(e: MouseEvent): void {\n if (!this.state.enabled) return;\n\n const rect = this.ctx.container.getBoundingClientRect();\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n // Handle label dragging\n if (this.isDraggingLabel) {\n this.labelOffset.x += pixelX - this.dragStart.x;\n this.labelOffset.y += pixelY - this.dragStart.y;\n this.dragStart = { x: pixelX, y: pixelY };\n this.renderOverlay();\n return;\n }\n\n // Update cursor if over label\n if (this.labelBounds &&\n pixelX >= this.labelBounds.x && pixelX <= this.labelBounds.x + this.labelBounds.width &&\n pixelY >= this.labelBounds.y && pixelY <= this.labelBounds.y + this.labelBounds.height) {\n this.ctx.container.style.cursor = 'move';\n } else {\n this.ctx.container.style.cursor = 'crosshair';\n }\n\n // Check if inside plot area\n if (\n pixelX < plotArea.x ||\n pixelX > plotArea.x + plotArea.width ||\n pixelY < plotArea.y ||\n pixelY > plotArea.y + plotArea.height\n ) {\n this.state.hoveredPoint = null;\n this.crosshairPosition = null;\n this.renderOverlay();\n return;\n }\n\n // Store current mouse position for crosshair\n this.crosshairPosition = { x: pixelX, y: pixelY };\n\n // Find nearest data point\n // When waiting for second point, only show points from the same series\n const seriesFilter = this.state.selectionState === 'waitingSecond' && this.state.point1\n ? this.state.point1.seriesId\n : undefined;\n const nearestPoint = this.findNearestPoint(pixelX, pixelY, plotArea, bounds, seriesFilter);\n this.state.hoveredPoint = nearestPoint;\n this.renderOverlay();\n }\n\n private handleLabelMouseDown(e: MouseEvent): void {\n if (!this.state.enabled || !this.labelBounds) return;\n\n const rect = this.ctx.container.getBoundingClientRect();\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n if (pixelX >= this.labelBounds.x && pixelX <= this.labelBounds.x + this.labelBounds.width &&\n pixelY >= this.labelBounds.y && pixelY <= this.labelBounds.y + this.labelBounds.height) {\n this.isDraggingLabel = true;\n this.dragStart = { x: pixelX, y: pixelY };\n e.stopPropagation();\n e.preventDefault();\n }\n }\n\n private handleLabelMouseUp(): void {\n this.isDraggingLabel = false;\n }\n\n private async handleClick(e: MouseEvent): Promise<void> {\n if (!this.state.enabled) return;\n\n // If chart is animating, wait for it to settle to get accurate coordinates\n if (this.ctx.animationEngine?.isAnimating()) {\n await this.ctx.animationEngine.waitForIdle();\n }\n\n // Stop propagation to prevent InteractionManager from handling this\n e.stopPropagation();\n e.preventDefault();\n\n const rect = this.ctx.container.getBoundingClientRect();\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n // Check if inside plot area\n if (\n pixelX < plotArea.x ||\n pixelX > plotArea.x + plotArea.width ||\n pixelY < plotArea.y ||\n pixelY > plotArea.y + plotArea.height\n ) {\n return;\n }\n\n // Find nearest data point\n // When waiting for second point, only look for points from the same series\n const seriesFilter = this.state.selectionState === 'waitingSecond' && this.state.point1\n ? this.state.point1.seriesId\n : undefined;\n const nearestPoint = this.findNearestPoint(pixelX, pixelY, plotArea, bounds, seriesFilter);\n\n if (!nearestPoint) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n if (this.state.selectionState === 'idle' || this.state.selectionState === 'complete') {\n // Select first point\n this.state.point1 = nearestPoint;\n this.state.point2 = null;\n this.state.selectionState = 'waitingSecond';\n this.state.lastMeasurement = null;\n } else if (this.state.selectionState === 'waitingSecond') {\n // For peak integration, both points MUST be on the same series\n if (this.state.point1 && nearestPoint.seriesId !== this.state.point1.seriesId) {\n // Ignore - user clicked on a different series\n return;\n }\n\n // Select second point\n this.state.point2 = nearestPoint;\n this.state.selectionState = 'complete';\n\n // Calculate measurement\n const measurement = this.calculateMeasurement();\n this.state.lastMeasurement = measurement;\n\n if (this.ctx.onMeasure) {\n this.ctx.onMeasure(measurement);\n }\n }\n\n this.renderOverlay();\n }\n\n private handleKeyDown(e: KeyboardEvent): void {\n if (e.key === 'Escape' && this.state.enabled) {\n this.clear();\n }\n }\n\n private findNearestPoint(\n pixelX: number,\n pixelY: number,\n plotArea: { x: number; y: number; width: number; height: number },\n bounds: Bounds,\n seriesIdFilter?: string\n ): DataPoint | null {\n if (!this.ctx.getSeries) return null;\n\n const series = this.ctx.getSeries();\n let nearestPoint: DataPoint | null = null;\n let minDistance = this.options.snapRadius;\n\n for (const s of series) {\n // If filtering by series ID, skip other series\n if (seriesIdFilter && s.id !== seriesIdFilter) continue;\n\n const xData = s.x;\n const yData = s.y;\n const len = Math.min(xData.length, yData.length);\n\n // Get Y bounds for this series (may be different if using secondary Y axis)\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(s.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n\n for (let i = 0; i < len; i++) {\n const dataX = xData[i];\n const dataY = yData[i];\n\n // Convert data to pixel coordinates\n const px = plotArea.x + ((dataX - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n const py = plotArea.y + (1 - (dataY - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n\n // Skip if outside visible range\n if (px < plotArea.x || px > plotArea.x + plotArea.width) continue;\n if (py < plotArea.y || py > plotArea.y + plotArea.height) continue;\n\n const distance = Math.sqrt((pixelX - px) ** 2 + (pixelY - py) ** 2);\n\n if (distance < minDistance) {\n minDistance = distance;\n nearestPoint = {\n x: dataX,\n y: dataY,\n seriesId: s.id,\n yAxisId: s.yAxisId,\n index: i,\n pixelX: px,\n pixelY: py,\n };\n }\n }\n }\n\n return nearestPoint;\n }\n\n private calculateMeasurement(): PeakMeasurement {\n const p1 = this.state.point1!;\n const p2 = this.state.point2!;\n const seriesList = this.ctx.getSeries ? this.ctx.getSeries() : [];\n const series = seriesList.find(s => s.id === p1.seriesId);\n\n if (!series) {\n return {\n x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y,\n area: 0, integral: 0, baselineSlope: 0, baselineIntercept: 0,\n peakHeight: 0, peakX: 0, peakY: 0,\n pixelX1: p1.pixelX, pixelY1: p1.pixelY, pixelX2: p2.pixelX, pixelY2: p2.pixelY\n };\n }\n\n const xData = series.x;\n const yData = series.y;\n const idx1 = Math.min(p1.index, p2.index);\n const idx2 = Math.max(p1.index, p2.index);\n\n // Baseline detection using linear regression on windows around p1 and p2 (noise segments)\n const win = this.options.baselineWindow;\n const baselinePointsX: number[] = [];\n const baselinePointsY: number[] = [];\n\n // Window around idx1\n for (let i = Math.max(0, idx1 - Math.floor(win / 2)); i <= Math.min(xData.length - 1, idx1 + Math.floor(win / 2)); i++) {\n baselinePointsX.push(xData[i]);\n baselinePointsY.push(yData[i]);\n }\n // Window around idx2\n for (let i = Math.max(0, idx2 - Math.floor(win / 2)); i <= Math.min(xData.length - 1, idx2 + Math.floor(win / 2)); i++) {\n baselinePointsX.push(xData[i]);\n baselinePointsY.push(yData[i]);\n }\n\n // Linear regression: y = mx + b\n const n = baselinePointsX.length;\n let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0;\n for (let i = 0; i < n; i++) {\n sumX += baselinePointsX[i];\n sumY += baselinePointsY[i];\n sumXY += baselinePointsX[i] * baselinePointsY[i];\n sumXX += baselinePointsX[i] * baselinePointsX[i];\n }\n const baselineSlope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);\n const baselineIntercept = (sumY - baselineSlope * sumX) / n;\n\n // Numerical integration (trapezoidal rule)\n let area = 0;\n let integral = 0;\n let peakHeight = -Infinity;\n let peakX = 0;\n let peakY = 0;\n\n for (let i = idx1; i < idx2; i++) {\n const x_a = xData[i];\n const y_a = yData[i];\n const x_b = xData[i + 1];\n const y_b = yData[i + 1];\n\n const dx = x_b - x_a;\n const avgY = (y_a + y_b) / 2;\n\n integral += avgY * dx;\n\n // Baseline value at these points\n const bl_a = baselineSlope * x_a + baselineIntercept;\n const bl_b = baselineSlope * x_b + baselineIntercept;\n const avgBL = (bl_a + bl_b) / 2;\n\n area += (avgY - avgBL) * dx;\n\n // Find maximum elevation above baseline\n const h_a = y_a - bl_a;\n if (h_a > peakHeight) {\n peakHeight = h_a;\n peakX = x_a;\n peakY = y_a;\n }\n }\n\n return {\n x1: p1.x, y1: p1.y,\n x2: p2.x, y2: p2.y,\n area, integral, baselineSlope, baselineIntercept,\n peakHeight, peakX, peakY,\n pixelX1: p1.pixelX, pixelY1: p1.pixelY,\n pixelX2: p2.pixelX, pixelY2: p2.pixelY\n };\n }\n\n public renderOverlay(): void {\n if (!this.overlayCtx || !this.overlayCanvas) return;\n\n // Resize if needed\n this.resizeOverlay();\n\n const rect = this.ctx.container.getBoundingClientRect();\n this.overlayCtx.clearRect(0, 0, rect.width, rect.height);\n\n const opts = this.options;\n const ctx = this.overlayCtx;\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n // Update pixel coordinates of selected points to follow zoom/pan\n if (this.state.point1) {\n const p = this.state.point1;\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(p.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n }\n if (this.state.point2) {\n const p = this.state.point2;\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(p.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n }\n\n // Draw crosshair lines (dotted lines from cursor to axes)\n if (this.crosshairPosition && this.state.selectionState !== 'complete') {\n const cx = this.crosshairPosition.x;\n const cy = this.crosshairPosition.y;\n\n ctx.save();\n ctx.setLineDash([4, 4]);\n ctx.strokeStyle = 'rgba(150, 150, 150, 0.7)';\n ctx.lineWidth = 1;\n\n // Vertical line (to X axis)\n ctx.beginPath();\n ctx.moveTo(cx, plotArea.y);\n ctx.lineTo(cx, plotArea.y + plotArea.height);\n ctx.stroke();\n\n // Horizontal line (to Y axis)\n ctx.beginPath();\n ctx.moveTo(plotArea.x, cy);\n ctx.lineTo(plotArea.x + plotArea.width, cy);\n ctx.stroke();\n\n ctx.restore();\n }\n\n // Draw hovered point highlight (pulsing effect)\n if (this.state.hoveredPoint && this.state.selectionState !== 'complete') {\n const hp = this.state.hoveredPoint;\n\n // Outer glow\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, opts.highlightSize + 4, 0, Math.PI * 2);\n ctx.fillStyle = opts.highlightColor + '30';\n ctx.fill();\n\n // Main highlight\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.strokeStyle = opts.highlightColor;\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Center dot\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, 4, 0, Math.PI * 2);\n ctx.fillStyle = opts.highlightColor;\n ctx.fill();\n\n // Show coordinates tooltip\n this.drawPointTooltip(ctx, hp, 'Hover');\n }\n\n // Draw selected point 1\n if (this.state.point1) {\n const p1 = this.state.point1;\n\n // Selected point marker\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.fillStyle = opts.lineColor;\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, opts.highlightSize - 3, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, 3, 0, Math.PI * 2);\n ctx.fillStyle = opts.lineColor;\n ctx.fill();\n\n // Label for point 1\n this.drawPointLabel(ctx, p1.pixelX, p1.pixelY - opts.highlightSize - 8, 'P1', opts.lineColor);\n }\n\n // Draw selected point 2\n if (this.state.point2) {\n const p2 = this.state.point2;\n\n // Selected point marker\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.fillStyle = '#4ade80';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, opts.highlightSize - 3, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, 3, 0, Math.PI * 2);\n ctx.fillStyle = '#4ade80';\n ctx.fill();\n\n // Label for point 2\n this.drawPointLabel(ctx, p2.pixelX, p2.pixelY - opts.highlightSize - 8, 'P2', '#4ade80');\n }\n\n // Draw baseline and area\n if (this.state.point1 && this.state.point2 && this.state.lastMeasurement) {\n const p1 = this.state.point1;\n const p2 = this.state.point2;\n const m = this.state.lastMeasurement;\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n // Draw area fill\n const seriesList = this.ctx.getSeries ? this.ctx.getSeries() : [];\n const series = seriesList.find(s => s.id === p1.seriesId);\n if (series) {\n const xData = series.x;\n const yData = series.y;\n const idx1 = Math.min(p1.index, p2.index);\n const idx2 = Math.max(p1.index, p2.index);\n\n // Get correct Y bounds for this series\n const seriesYBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(series.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n\n ctx.beginPath();\n // Start from first point on baseline\n ctx.moveTo(p1.pixelX, p1.pixelY);\n\n // Trace the peak curve\n for (let i = idx1; i <= idx2; i++) {\n const px = plotArea.x + ((xData[i] - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n const py = plotArea.y + (1 - (yData[i] - seriesYBounds.yMin) / (seriesYBounds.yMax - seriesYBounds.yMin)) * plotArea.height;\n ctx.lineTo(px, py);\n }\n\n // Close back along baseline\n ctx.lineTo(p2.pixelX, p2.pixelY);\n ctx.closePath();\n\n ctx.fillStyle = opts.areaFill;\n ctx.fill();\n }\n\n // Draw baseline (straight line from regression)\n ctx.beginPath();\n ctx.moveTo(p1.pixelX, p1.pixelY);\n ctx.lineTo(p2.pixelX, p2.pixelY);\n ctx.strokeStyle = opts.lineColor;\n ctx.lineWidth = 1;\n ctx.stroke();\n\n // Peak height indicator - use correct Y bounds\n const peakYBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(p1.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n const peakPX = plotArea.x + ((m.peakX - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n const peakPY = plotArea.y + (1 - (m.peakY - peakYBounds.yMin) / (peakYBounds.yMax - peakYBounds.yMin)) * plotArea.height;\n const baselineAtPeak = m.baselineSlope * m.peakX + m.baselineIntercept;\n const basePY = plotArea.y + (1 - (baselineAtPeak - peakYBounds.yMin) / (peakYBounds.yMax - peakYBounds.yMin)) * plotArea.height;\n\n ctx.beginPath();\n ctx.moveTo(peakPX, peakPY);\n ctx.lineTo(peakPX, basePY);\n ctx.strokeStyle = opts.lineColor;\n ctx.setLineDash([2, 2]);\n ctx.stroke();\n ctx.setLineDash([]);\n\n // Draw measurement label\n if (opts.showLabels) {\n this.drawMeasurementLabel(ctx, p1, p2, m);\n }\n }\n\n // Draw status indicator\n this.drawStatusIndicator(ctx);\n }\n\n private drawPointTooltip(\n ctx: CanvasRenderingContext2D,\n point: DataPoint,\n label: string\n ): void {\n const opts = this.options;\n const text = `${label}: (${this.formatValue(point.x)}, ${this.formatValue(point.y)})`;\n\n ctx.font = `${opts.labelFontSize}px system-ui, sans-serif`;\n const metrics = ctx.measureText(text);\n const padding = 6;\n const boxWidth = metrics.width + padding * 2;\n const boxHeight = opts.labelFontSize + padding * 2;\n\n let boxX = point.pixelX + 15;\n let boxY = point.pixelY - boxHeight / 2;\n\n // Keep within container\n const rect = this.ctx.container.getBoundingClientRect();\n if (boxX + boxWidth > rect.width) boxX = point.pixelX - boxWidth - 15;\n if (boxY < 0) boxY = 5;\n if (boxY + boxHeight > rect.height) boxY = rect.height - boxHeight - 5;\n\n // Background\n ctx.fillStyle = opts.labelBackground;\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 4);\n ctx.fill();\n\n // Text\n ctx.fillStyle = opts.labelColor;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(text, boxX + padding, boxY + boxHeight / 2);\n }\n\n private drawPointLabel(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n label: string,\n color: string\n ): void {\n const opts = this.options;\n ctx.font = `bold ${opts.labelFontSize}px system-ui, sans-serif`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'bottom';\n\n // Background pill\n const metrics = ctx.measureText(label);\n const padding = 4;\n const pillWidth = metrics.width + padding * 2;\n const pillHeight = opts.labelFontSize + padding;\n\n ctx.fillStyle = color;\n this.roundRect(ctx, x - pillWidth / 2, y - pillHeight, pillWidth, pillHeight, 3);\n ctx.fill();\n\n // Text\n ctx.fillStyle = '#ffffff';\n ctx.fillText(label, x, y - 2);\n }\n\n private drawMeasurementLabel(\n ctx: CanvasRenderingContext2D,\n p1: DataPoint,\n p2: DataPoint,\n m: PeakMeasurement\n ): void {\n const opts = this.options;\n const midX = (p1.pixelX + p2.pixelX) / 2;\n const midY = (p1.pixelY + p2.pixelY) / 2;\n\n const lines: string[] = [];\n if (opts.showPeak) {\n lines.push(`Peak Area: ${this.formatValue(m.area)}`);\n lines.push(`Peak Height: ${this.formatValue(m.peakHeight)}`);\n lines.push(`Integral: ${this.formatValue(m.integral)}`);\n }\n\n const lineHeight = opts.labelFontSize + 4;\n const padding = 10;\n const boxWidth = 170;\n const boxHeight = lines.length * lineHeight + padding * 2;\n\n // Position box using offset from midpoint\n let boxX = midX + this.labelOffset.x;\n let boxY = midY + this.labelOffset.y;\n\n // Keep within bounds\n const container = this.ctx.container.getBoundingClientRect();\n if (boxX < 0) boxX = 0;\n if (boxX + boxWidth > container.width) boxX = container.width - boxWidth;\n if (boxY < 0) boxY = 0;\n if (boxY + boxHeight > container.height) boxY = container.height - boxHeight;\n\n // Store bounds for hit testing\n this.labelBounds = { x: boxX, y: boxY, width: boxWidth, height: boxHeight };\n\n // Draw box with border\n ctx.fillStyle = opts.labelBackground;\n ctx.strokeStyle = opts.lineColor;\n ctx.lineWidth = 2;\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 8);\n ctx.fill();\n ctx.stroke();\n\n // Draw text\n ctx.fillStyle = opts.labelColor;\n ctx.font = `${opts.labelFontSize}px system-ui, sans-serif`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n\n lines.forEach((line, i) => {\n ctx.fillText(line, boxX + padding, boxY + padding + i * lineHeight);\n });\n }\n\n private drawStatusIndicator(\n ctx: CanvasRenderingContext2D\n ): void {\n const opts = this.options;\n const plotArea = this.ctx.getPlotArea();\n\n let statusText = '';\n let statusColor = '#666';\n\n if (this.state.selectionState === 'idle') {\n statusText = '📏 Click a point to start measuring';\n statusColor = opts.highlightColor;\n } else if (this.state.selectionState === 'waitingSecond') {\n statusText = '📏 Click second point to complete';\n statusColor = '#f59e0b';\n } else if (this.state.selectionState === 'complete') {\n statusText = '📏 Measurement complete (ESC to clear)';\n statusColor = '#4ade80';\n }\n\n if (!statusText) return;\n\n ctx.font = `12px system-ui, sans-serif`;\n const metrics = ctx.measureText(statusText);\n const padding = 8;\n const boxWidth = metrics.width + padding * 2;\n const boxHeight = 24;\n const boxX = plotArea.x + 10;\n const boxY = plotArea.y + 10;\n\n // Background\n ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 4);\n ctx.fill();\n\n // Status dot\n ctx.beginPath();\n ctx.arc(boxX + 16, boxY + boxHeight / 2, 4, 0, Math.PI * 2);\n ctx.fillStyle = statusColor;\n ctx.fill();\n\n // Text\n ctx.fillStyle = '#fff';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(statusText, boxX + 26, boxY + boxHeight / 2);\n }\n\n private roundRect(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n r: number\n ): void {\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + w - r, y);\n ctx.quadraticCurveTo(x + w, y, x + w, y + r);\n ctx.lineTo(x + w, y + h - r);\n ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\n ctx.lineTo(x + r, y + h);\n ctx.quadraticCurveTo(x, y + h, x, y + h - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n }\n\n private formatValue(val: number): string {\n const abs = Math.abs(val);\n if (abs === 0) return '0';\n if (abs >= 1e6 || abs < 0.001) {\n return val.toExponential(this.options.precision - 1);\n }\n return val.toPrecision(this.options.precision);\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\n/**\n * Create a peak tool for a chart context\n */\nexport function createPeakTool(\n context: PeakToolContext,\n options?: PeakToolOptions\n): PeakTool {\n return new PeakTool(context, options);\n}\n","/**\n * Tooltip Themes - Predefined visual styles for tooltips\n * \n * This module provides beautiful, high-quality tooltip themes that\n * integrate seamlessly with the chart theme system.\n * \n * @module tooltip/themes\n */\n\nimport type { TooltipTheme } from './types';\n\n// ============================================\n// Base Defaults\n// ============================================\n\nconst DEFAULT_PADDING = {\n top: 10,\n right: 12,\n bottom: 10,\n left: 12\n};\n\n// ============================================\n// Dark Theme\n// ============================================\n\n/**\n * Dark Theme - Elegant dark tooltip with subtle glow\n */\nexport const TOOLTIP_DARK_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(15, 18, 25, 0.95)',\n backgroundGradient: 'rgba(25, 30, 40, 0.90)',\n borderColor: 'rgba(255, 255, 255, 0.12)',\n borderWidth: 1,\n borderRadius: 8,\n backdropBlur: 12,\n shadow: {\n color: 'rgba(0, 0, 0, 0.4)',\n offsetX: 0,\n offsetY: 4,\n blur: 16\n },\n \n // Typography\n fontFamily: 'Inter, system-ui, -apple-system, BlinkMacSystemFont, sans-serif',\n textColor: '#ffffff',\n textSecondaryColor: 'rgba(255, 255, 255, 0.6)',\n titleFontSize: 12,\n titleFontWeight: 600,\n contentFontSize: 11,\n lineHeight: 1.4,\n \n // Spacing\n padding: DEFAULT_PADDING,\n itemGap: 4,\n headerGap: 8,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 8,\n showHeaderSeparator: true,\n separatorColor: 'rgba(255, 255, 255, 0.1)',\n showArrow: true,\n arrowSize: 6\n};\n\n// ============================================\n// Light Theme\n// ============================================\n\n/**\n * Light Theme - Clean and professional for light backgrounds\n */\nexport const TOOLTIP_LIGHT_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(255, 255, 255, 0.98)',\n borderColor: 'rgba(0, 0, 0, 0.12)',\n borderWidth: 1,\n borderRadius: 8,\n backdropBlur: 8,\n shadow: {\n color: 'rgba(0, 0, 0, 0.12)',\n offsetX: 0,\n offsetY: 4,\n blur: 12\n },\n \n // Typography\n fontFamily: 'Inter, system-ui, -apple-system, BlinkMacSystemFont, sans-serif',\n textColor: '#1a1a1a',\n textSecondaryColor: 'rgba(0, 0, 0, 0.55)',\n titleFontSize: 12,\n titleFontWeight: 600,\n contentFontSize: 11,\n lineHeight: 1.4,\n \n // Spacing\n padding: DEFAULT_PADDING,\n itemGap: 4,\n headerGap: 8,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 8,\n showHeaderSeparator: true,\n separatorColor: 'rgba(0, 0, 0, 0.08)',\n showArrow: true,\n arrowSize: 6\n};\n\n// ============================================\n// Glassmorphism Theme\n// ============================================\n\n/**\n * Glassmorphism Theme - Modern frosted glass effect\n */\nexport const TOOLTIP_GLASS_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(255, 255, 255, 0.08)',\n backgroundGradient: 'rgba(255, 255, 255, 0.04)',\n borderColor: 'rgba(255, 255, 255, 0.2)',\n borderWidth: 1,\n borderRadius: 12,\n backdropBlur: 20,\n shadow: {\n color: 'rgba(0, 0, 0, 0.3)',\n offsetX: 0,\n offsetY: 8,\n blur: 32\n },\n \n // Typography\n fontFamily: 'Inter, system-ui, sans-serif',\n textColor: 'rgba(255, 255, 255, 0.95)',\n textSecondaryColor: 'rgba(255, 255, 255, 0.6)',\n titleFontSize: 12,\n titleFontWeight: 600,\n contentFontSize: 11,\n lineHeight: 1.5,\n \n // Spacing\n padding: { top: 12, right: 14, bottom: 12, left: 14 },\n itemGap: 5,\n headerGap: 10,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 8,\n showHeaderSeparator: true,\n separatorColor: 'rgba(255, 255, 255, 0.15)',\n showArrow: true,\n arrowSize: 7\n};\n\n// ============================================\n// Midnight Theme\n// ============================================\n\n/**\n * Midnight Theme - Deep blue tones for night mode\n */\nexport const TOOLTIP_MIDNIGHT_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(10, 15, 30, 0.95)',\n backgroundGradient: 'rgba(20, 25, 50, 0.90)',\n borderColor: 'rgba(100, 120, 255, 0.25)',\n borderWidth: 1,\n borderRadius: 8,\n backdropBlur: 15,\n shadow: {\n color: 'rgba(50, 70, 150, 0.25)',\n offsetX: 0,\n offsetY: 4,\n blur: 20\n },\n \n // Typography\n fontFamily: 'Inter, system-ui, sans-serif',\n textColor: '#e0e8ff',\n textSecondaryColor: 'rgba(180, 190, 255, 0.6)',\n titleFontSize: 12,\n titleFontWeight: 600,\n contentFontSize: 11,\n lineHeight: 1.4,\n \n // Spacing\n padding: DEFAULT_PADDING,\n itemGap: 4,\n headerGap: 8,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 8,\n showHeaderSeparator: true,\n separatorColor: 'rgba(100, 120, 255, 0.15)',\n showArrow: true,\n arrowSize: 6\n};\n\n// ============================================\n// Electrochemistry Theme\n// ============================================\n\n/**\n * Electrochemistry Theme - Professional blue tones for scientific data\n */\nexport const TOOLTIP_ELECTROCHEM_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(8, 20, 40, 0.96)',\n backgroundGradient: 'rgba(15, 35, 60, 0.92)',\n borderColor: 'rgba(30, 136, 229, 0.35)',\n borderWidth: 1,\n borderRadius: 6,\n backdropBlur: 10,\n shadow: {\n color: 'rgba(30, 136, 229, 0.2)',\n offsetX: 0,\n offsetY: 4,\n blur: 16\n },\n \n // Typography\n fontFamily: '\"JetBrains Mono\", \"Fira Code\", monospace',\n textColor: '#bbdefb',\n textSecondaryColor: 'rgba(144, 202, 249, 0.7)',\n titleFontSize: 11,\n titleFontWeight: 600,\n contentFontSize: 11,\n lineHeight: 1.5,\n \n // Spacing\n padding: { top: 8, right: 10, bottom: 8, left: 10 },\n itemGap: 3,\n headerGap: 6,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 6,\n showHeaderSeparator: true,\n separatorColor: 'rgba(30, 136, 229, 0.2)',\n showArrow: true,\n arrowSize: 5\n};\n\n// ============================================\n// Neon Theme\n// ============================================\n\n/**\n * Neon Theme - Vibrant glowing effect for futuristic UIs\n */\nexport const TOOLTIP_NEON_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(0, 0, 0, 0.92)',\n borderColor: '#00ffff',\n borderWidth: 1,\n borderRadius: 4,\n backdropBlur: 0,\n shadow: {\n color: 'rgba(0, 255, 255, 0.35)',\n offsetX: 0,\n offsetY: 0,\n blur: 20\n },\n \n // Typography\n fontFamily: '\"Orbitron\", \"Exo 2\", sans-serif',\n textColor: '#00ffff',\n textSecondaryColor: 'rgba(0, 255, 255, 0.6)',\n titleFontSize: 11,\n titleFontWeight: 700,\n contentFontSize: 10,\n lineHeight: 1.4,\n \n // Spacing\n padding: { top: 8, right: 12, bottom: 8, left: 12 },\n itemGap: 4,\n headerGap: 6,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 6,\n showHeaderSeparator: true,\n separatorColor: 'rgba(0, 255, 255, 0.3)',\n showArrow: false,\n arrowSize: 0\n};\n\n// ============================================\n// Minimal Theme\n// ============================================\n\n/**\n * Minimal Theme - Ultra-compact with no decorations\n */\nexport const TOOLTIP_MINIMAL_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(30, 35, 45, 0.9)',\n borderColor: 'transparent',\n borderWidth: 0,\n borderRadius: 4,\n backdropBlur: 8,\n shadow: {\n color: 'rgba(0, 0, 0, 0.3)',\n offsetX: 0,\n offsetY: 2,\n blur: 8\n },\n \n // Typography\n fontFamily: 'Inter, system-ui, sans-serif',\n textColor: '#ffffff',\n textSecondaryColor: 'rgba(255, 255, 255, 0.7)',\n titleFontSize: 10,\n titleFontWeight: 500,\n contentFontSize: 10,\n lineHeight: 1.3,\n \n // Spacing\n padding: { top: 6, right: 8, bottom: 6, left: 8 },\n itemGap: 2,\n headerGap: 4,\n \n // Decorations\n showSeriesIndicator: false,\n seriesIndicatorSize: 0,\n showHeaderSeparator: false,\n separatorColor: 'transparent',\n showArrow: false,\n arrowSize: 0\n};\n\n// ============================================\n// Theme Utilities\n// ============================================\n\n/** Available tooltip theme names */\nexport type TooltipThemeName = \n | 'dark' \n | 'light' \n | 'glass' \n | 'midnight' \n | 'electrochemistry' \n | 'neon' \n | 'minimal';\n\n/** Theme registry */\nexport const TOOLTIP_THEMES: Record<TooltipThemeName, TooltipTheme> = {\n dark: TOOLTIP_DARK_THEME,\n light: TOOLTIP_LIGHT_THEME,\n glass: TOOLTIP_GLASS_THEME,\n midnight: TOOLTIP_MIDNIGHT_THEME,\n electrochemistry: TOOLTIP_ELECTROCHEM_THEME,\n neon: TOOLTIP_NEON_THEME,\n minimal: TOOLTIP_MINIMAL_THEME\n};\n\n/**\n * Get a tooltip theme by name\n */\nexport function getTooltipTheme(name: TooltipThemeName | string): TooltipTheme {\n const theme = TOOLTIP_THEMES[name as TooltipThemeName];\n if (!theme) {\n console.warn(`[Tooltip] Unknown theme \"${name}\", using dark`);\n return TOOLTIP_DARK_THEME;\n }\n return theme;\n}\n\n/**\n * Create a custom tooltip theme by merging with a base theme\n */\nexport function createTooltipTheme(\n base: TooltipTheme | TooltipThemeName,\n overrides: Partial<TooltipTheme>\n): TooltipTheme {\n const baseTheme = typeof base === 'string' ? getTooltipTheme(base) : base;\n \n return {\n ...baseTheme,\n ...overrides,\n padding: { ...baseTheme.padding, ...overrides.padding },\n shadow: { ...baseTheme.shadow, ...overrides.shadow }\n };\n}\n\n/**\n * Map chart theme name to matching tooltip theme\n */\nexport function getTooltipThemeForChartTheme(chartThemeName: string): TooltipTheme {\n switch (chartThemeName.toLowerCase()) {\n case 'light':\n return TOOLTIP_LIGHT_THEME;\n case 'midnight':\n return TOOLTIP_MIDNIGHT_THEME;\n case 'electrochemistry':\n case 'electrochem':\n return TOOLTIP_ELECTROCHEM_THEME;\n case 'dark':\n default:\n return TOOLTIP_DARK_THEME;\n }\n}\n\n/** Default tooltip theme */\nexport const DEFAULT_TOOLTIP_THEME = TOOLTIP_DARK_THEME;\n","/**\n * Tooltip Positioner - Smart positioning algorithms\n * \n * Handles intelligent tooltip positioning with:\n * - Automatic edge avoidance\n * - Flipping when space is limited\n * - Arrow positioning\n * - Constraint handling\n * \n * @module tooltip/TooltipPositioner\n */\n\nimport type { PlotArea } from '../../../types';\nimport type {\n TooltipPosition,\n TooltipMeasurement,\n TooltipPlacement,\n ArrowPosition\n} from './types';\n\nexport interface PositionerConfig {\n /** Offset from target point */\n offset: { x: number; y: number };\n /** Preferred placement */\n preferredPosition: TooltipPlacement;\n /** Keep within plot area */\n constrainToPlotArea: boolean;\n /** Keep within container */\n constrainToContainer: boolean;\n /** Flip if not enough space */\n autoFlip: boolean;\n /** Show arrow pointing to target */\n showArrow: boolean;\n /** Arrow size */\n arrowSize: number;\n}\n\nexport const DEFAULT_POSITIONER_CONFIG: PositionerConfig = {\n offset: { x: 12, y: 12 },\n preferredPosition: 'auto',\n constrainToPlotArea: true,\n constrainToContainer: true,\n autoFlip: true,\n showArrow: true,\n arrowSize: 6\n};\n\n/**\n * TooltipPositioner calculates optimal tooltip positions\n */\nexport class TooltipPositioner {\n private config: PositionerConfig;\n private containerWidth: number = 0;\n private containerHeight: number = 0;\n private plotArea: PlotArea | null = null;\n\n constructor(config: Partial<PositionerConfig> = {}) {\n this.config = { ...DEFAULT_POSITIONER_CONFIG, ...config };\n }\n\n /**\n * Update container dimensions\n */\n setContainerSize(width: number, height: number): void {\n this.containerWidth = width;\n this.containerHeight = height;\n }\n\n /**\n * Update plot area bounds\n */\n setPlotArea(plotArea: PlotArea): void {\n this.plotArea = plotArea;\n }\n\n /**\n * Update configuration\n */\n configure(config: Partial<PositionerConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n /**\n * Calculate optimal tooltip position\n * \n * @param targetX - Target X coordinate (where tooltip points to)\n * @param targetY - Target Y coordinate\n * @param measurement - Tooltip dimensions\n * @returns Calculated position with arrow configuration\n */\n calculatePosition(\n targetX: number,\n targetY: number,\n measurement: TooltipMeasurement\n ): TooltipPosition {\n const { offset, preferredPosition, autoFlip, showArrow, arrowSize } = this.config;\n \n // Total dimensions including padding\n const totalWidth = measurement.width + measurement.padding.left + measurement.padding.right;\n const totalHeight = measurement.height + measurement.padding.top + measurement.padding.bottom;\n \n // Determine best position\n let position = this.determinePosition(\n targetX, \n targetY, \n totalWidth, \n totalHeight, \n preferredPosition\n );\n \n // Calculate initial coordinates based on position\n let { x, y, arrowPosition } = this.calculateCoordinates(\n targetX,\n targetY,\n totalWidth,\n totalHeight,\n position,\n offset,\n showArrow ? arrowSize : 0\n );\n \n let wasFlipped = false;\n \n // Check if we need to flip\n if (autoFlip && !this.fitsInBounds(x, y, totalWidth, totalHeight)) {\n const flippedPosition = this.flipPosition(position);\n const flipped = this.calculateCoordinates(\n targetX,\n targetY,\n totalWidth,\n totalHeight,\n flippedPosition,\n offset,\n showArrow ? arrowSize : 0\n );\n \n // Use flipped if it fits better\n if (this.fitsInBounds(flipped.x, flipped.y, totalWidth, totalHeight)) {\n x = flipped.x;\n y = flipped.y;\n arrowPosition = flipped.arrowPosition;\n wasFlipped = true;\n }\n }\n \n // Constrain to bounds\n const constrained = this.constrainToBounds(x, y, totalWidth, totalHeight);\n \n // Calculate arrow offset based on how much we shifted\n let arrowOffset = 0;\n if (showArrow) {\n if (arrowPosition === 'top' || arrowPosition === 'bottom') {\n // Arrow on horizontal edge - calculate X offset\n const idealArrowX = targetX - constrained.x;\n arrowOffset = Math.max(arrowSize + 4, Math.min(totalWidth - arrowSize - 4, idealArrowX));\n } else if (arrowPosition === 'left' || arrowPosition === 'right') {\n // Arrow on vertical edge - calculate Y offset \n const idealArrowY = targetY - constrained.y;\n arrowOffset = Math.max(arrowSize + 4, Math.min(totalHeight - arrowSize - 4, idealArrowY));\n }\n }\n \n return {\n x: constrained.x,\n y: constrained.y,\n arrowPosition: showArrow ? arrowPosition : 'none',\n arrowOffset,\n wasFlipped\n };\n }\n\n /**\n * Determine best position based on available space\n */\n private determinePosition(\n targetX: number,\n targetY: number,\n width: number,\n height: number,\n preferred: TooltipPlacement\n ): 'top' | 'bottom' | 'left' | 'right' {\n if (preferred !== 'auto') {\n return preferred;\n }\n \n // Calculate available space in each direction\n const bounds = this.getConstraintBounds();\n \n const spaceTop = targetY - bounds.top;\n const spaceBottom = bounds.bottom - targetY;\n const spaceLeft = targetX - bounds.left;\n const spaceRight = bounds.right - targetX;\n \n // Prefer vertical placement (top/bottom) for better readability\n const canFitTop = spaceTop >= height + this.config.offset.y;\n const canFitBottom = spaceBottom >= height + this.config.offset.y;\n const canFitRight = spaceRight >= width + this.config.offset.x;\n const canFitLeft = spaceLeft >= width + this.config.offset.x;\n \n // Priority: top > bottom > right > left\n if (canFitTop && spaceTop >= spaceBottom) return 'top';\n if (canFitBottom) return 'bottom';\n if (canFitRight && spaceRight >= spaceLeft) return 'right';\n if (canFitLeft) return 'left';\n \n // Default to position with most space\n const spaces = [\n { pos: 'top' as const, space: spaceTop },\n { pos: 'bottom' as const, space: spaceBottom },\n { pos: 'right' as const, space: spaceRight },\n { pos: 'left' as const, space: spaceLeft }\n ];\n \n return spaces.sort((a, b) => b.space - a.space)[0].pos;\n }\n\n /**\n * Calculate tooltip coordinates for a given position\n */\n private calculateCoordinates(\n targetX: number,\n targetY: number,\n width: number,\n height: number,\n position: 'top' | 'bottom' | 'left' | 'right',\n offset: { x: number; y: number },\n arrowSize: number\n ): { x: number; y: number; arrowPosition: ArrowPosition } {\n let x: number;\n let y: number;\n let arrowPosition: ArrowPosition;\n \n switch (position) {\n case 'top':\n x = targetX - width / 2;\n y = targetY - height - offset.y - arrowSize;\n arrowPosition = 'bottom';\n break;\n \n case 'bottom':\n x = targetX - width / 2;\n y = targetY + offset.y + arrowSize;\n arrowPosition = 'top';\n break;\n \n case 'right':\n x = targetX + offset.x + arrowSize;\n y = targetY - height / 2;\n arrowPosition = 'left';\n break;\n \n case 'left':\n x = targetX - width - offset.x - arrowSize;\n y = targetY - height / 2;\n arrowPosition = 'right';\n break;\n }\n \n return { x, y, arrowPosition };\n }\n\n /**\n * Get the opposite position for flipping\n */\n private flipPosition(\n position: 'top' | 'bottom' | 'left' | 'right'\n ): 'top' | 'bottom' | 'left' | 'right' {\n switch (position) {\n case 'top': return 'bottom';\n case 'bottom': return 'top';\n case 'left': return 'right';\n case 'right': return 'left';\n }\n }\n\n /**\n * Check if tooltip fits within bounds\n */\n private fitsInBounds(x: number, y: number, width: number, height: number): boolean {\n const bounds = this.getConstraintBounds();\n \n return (\n x >= bounds.left &&\n y >= bounds.top &&\n x + width <= bounds.right &&\n y + height <= bounds.bottom\n );\n }\n\n /**\n * Constrain position to stay within bounds\n */\n private constrainToBounds(\n x: number,\n y: number,\n width: number,\n height: number\n ): { x: number; y: number } {\n const bounds = this.getConstraintBounds();\n const margin = 4; // Small margin from edges\n \n let constrainedX = x;\n let constrainedY = y;\n \n // Horizontal constraints\n if (constrainedX < bounds.left + margin) {\n constrainedX = bounds.left + margin;\n } else if (constrainedX + width > bounds.right - margin) {\n constrainedX = bounds.right - width - margin;\n }\n \n // Vertical constraints\n if (constrainedY < bounds.top + margin) {\n constrainedY = bounds.top + margin;\n } else if (constrainedY + height > bounds.bottom - margin) {\n constrainedY = bounds.bottom - height - margin;\n }\n \n return { x: constrainedX, y: constrainedY };\n }\n\n /**\n * Get the bounds to constrain tooltip within\n */\n private getConstraintBounds(): { top: number; left: number; right: number; bottom: number } {\n let bounds = {\n top: 0,\n left: 0,\n right: this.containerWidth,\n bottom: this.containerHeight\n };\n \n if (this.config.constrainToPlotArea && this.plotArea) {\n bounds = {\n top: Math.max(bounds.top, this.plotArea.y),\n left: Math.max(bounds.left, this.plotArea.x),\n right: Math.min(bounds.right, this.plotArea.x + this.plotArea.width),\n bottom: Math.min(bounds.bottom, this.plotArea.y + this.plotArea.height)\n };\n }\n \n return bounds;\n }\n\n /**\n * Calculate position for crosshair tooltip (follows cursor vertically)\n */\n calculateCrosshairPosition(\n cursorX: number,\n cursorY: number,\n measurement: TooltipMeasurement\n ): TooltipPosition {\n const { offset } = this.config;\n const bounds = this.getConstraintBounds();\n \n const totalWidth = measurement.width + measurement.padding.left + measurement.padding.right;\n const totalHeight = measurement.height + measurement.padding.top + measurement.padding.bottom;\n \n // Position to the right of cursor by default\n let x = cursorX + offset.x;\n let arrowPosition: ArrowPosition = 'left';\n \n // Flip to left if not enough space on right\n if (x + totalWidth > bounds.right - 4) {\n x = cursorX - totalWidth - offset.x;\n arrowPosition = 'right';\n }\n \n // Center vertically on cursor\n let y = cursorY - totalHeight / 2;\n \n // Constrain vertically\n y = Math.max(bounds.top + 4, Math.min(bounds.bottom - totalHeight - 4, y));\n \n // Calculate arrow offset (centered on cursor Y)\n const arrowOffset = cursorY - y;\n \n return {\n x,\n y,\n arrowPosition,\n arrowOffset: Math.max(8, Math.min(totalHeight - 8, arrowOffset)),\n wasFlipped: arrowPosition === 'right'\n };\n }\n}\n\n// Export singleton-like factory\nexport function createTooltipPositioner(\n config?: Partial<PositionerConfig>\n): TooltipPositioner {\n return new TooltipPositioner(config);\n}\n","/**\n * Tooltip Renderer - Canvas 2D tooltip rendering\n * \n * High-performance Canvas rendering for tooltips with:\n * - Glassmorphism effects\n * - Smooth gradients and shadows\n * - Arrow/pointer drawing\n * - Animation support\n * \n * @module tooltip/TooltipRenderer\n */\n\nimport type {\n TooltipData,\n TooltipPosition,\n TooltipTheme,\n TooltipTemplate,\n ArrowPosition\n} from './types';\n\n/**\n * TooltipRenderer handles all Canvas 2D rendering for tooltips\n */\nexport class TooltipRenderer {\n private ctx: CanvasRenderingContext2D;\n private theme: TooltipTheme;\n\n constructor(ctx: CanvasRenderingContext2D, theme: TooltipTheme) {\n this.ctx = ctx;\n this.theme = theme;\n }\n\n /**\n * Update the theme\n */\n setTheme(theme: TooltipTheme): void {\n this.theme = theme;\n }\n\n /**\n * Render a tooltip with the given template\n */\n render<T extends TooltipData>(\n data: T,\n position: TooltipPosition,\n template: TooltipTemplate<T>\n ): void {\n const measurement = template.measure(this.ctx, data, this.theme);\n const totalWidth = measurement.width + measurement.padding.left + measurement.padding.right;\n const totalHeight = measurement.height + measurement.padding.top + measurement.padding.bottom;\n\n this.ctx.save();\n\n // Draw background with effects\n this.drawBackground(position.x, position.y, totalWidth, totalHeight, position.arrowPosition || 'none');\n\n // Draw arrow if enabled\n if (position.arrowPosition && position.arrowPosition !== 'none') {\n this.drawArrow(\n position.x,\n position.y,\n totalWidth,\n totalHeight,\n position.arrowPosition,\n position.arrowOffset || 0\n );\n }\n\n // Let template render content\n template.render(this.ctx, data, position, measurement, this.theme);\n\n this.ctx.restore();\n }\n\n\n\n /**\n * Draw tooltip background with all effects\n */\n private drawBackground(\n x: number,\n y: number,\n width: number,\n height: number,\n _arrowPosition: ArrowPosition\n ): void {\n const { ctx, theme } = this;\n const r = theme.borderRadius;\n\n ctx.save();\n\n // Shadow\n if (theme.shadow.blur > 0) {\n ctx.shadowColor = theme.shadow.color;\n ctx.shadowOffsetX = theme.shadow.offsetX;\n ctx.shadowOffsetY = theme.shadow.offsetY;\n ctx.shadowBlur = theme.shadow.blur;\n }\n\n // Create rounded rect path\n ctx.beginPath();\n this.roundRect(x, y, width, height, r);\n\n // Fill with gradient or solid color\n if (theme.backgroundGradient) {\n const gradient = ctx.createLinearGradient(x, y, x, y + height);\n gradient.addColorStop(0, theme.backgroundColor);\n gradient.addColorStop(1, theme.backgroundGradient);\n ctx.fillStyle = gradient;\n } else {\n ctx.fillStyle = theme.backgroundColor;\n }\n ctx.fill();\n\n // Reset shadow for border\n ctx.shadowColor = 'transparent';\n\n // Border\n if (theme.borderWidth > 0) {\n ctx.strokeStyle = theme.borderColor;\n ctx.lineWidth = theme.borderWidth;\n ctx.stroke();\n }\n\n ctx.restore();\n }\n\n /**\n * Draw arrow pointing to target\n */\n private drawArrow(\n x: number,\n y: number,\n width: number,\n height: number,\n arrowPosition: ArrowPosition,\n arrowOffset: number\n ): void {\n const { ctx, theme } = this;\n const size = theme.arrowSize;\n\n if (size <= 0 || arrowPosition === 'none') return;\n\n ctx.save();\n ctx.fillStyle = theme.backgroundColor;\n ctx.strokeStyle = theme.borderColor;\n ctx.lineWidth = theme.borderWidth;\n\n ctx.beginPath();\n\n switch (arrowPosition) {\n case 'top':\n // Arrow pointing up (tooltip below target)\n const topX = x + arrowOffset;\n ctx.moveTo(topX - size, y);\n ctx.lineTo(topX, y - size);\n ctx.lineTo(topX + size, y);\n break;\n\n case 'bottom':\n // Arrow pointing down (tooltip above target)\n const bottomX = x + arrowOffset;\n const bottomY = y + height;\n ctx.moveTo(bottomX - size, bottomY);\n ctx.lineTo(bottomX, bottomY + size);\n ctx.lineTo(bottomX + size, bottomY);\n break;\n\n case 'left':\n // Arrow pointing left (tooltip right of target)\n const leftY = y + arrowOffset;\n ctx.moveTo(x, leftY - size);\n ctx.lineTo(x - size, leftY);\n ctx.lineTo(x, leftY + size);\n break;\n\n case 'right':\n // Arrow pointing right (tooltip left of target)\n const rightX = x + width;\n const rightY = y + arrowOffset;\n ctx.moveTo(rightX, rightY - size);\n ctx.lineTo(rightX + size, rightY);\n ctx.lineTo(rightX, rightY + size);\n break;\n }\n\n ctx.closePath();\n ctx.fill();\n\n if (theme.borderWidth > 0) {\n ctx.stroke();\n }\n\n ctx.restore();\n }\n\n /**\n * Draw a rounded rectangle path\n */\n private roundRect(x: number, y: number, width: number, height: number, radius: number): void {\n const { ctx } = this;\n const r = Math.min(radius, width / 2, height / 2);\n\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + width - r, y);\n ctx.arcTo(x + width, y, x + width, y + r, r);\n ctx.lineTo(x + width, y + height - r);\n ctx.arcTo(x + width, y + height, x + width - r, y + height, r);\n ctx.lineTo(x + r, y + height);\n ctx.arcTo(x, y + height, x, y + height - r, r);\n ctx.lineTo(x, y + r);\n ctx.arcTo(x, y, x + r, y, r);\n ctx.closePath();\n }\n\n /**\n * Draw a horizontal separator line\n */\n drawSeparator(x: number, y: number, width: number): void {\n const { ctx, theme } = this;\n\n if (!theme.showHeaderSeparator) return;\n\n ctx.save();\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + width, y);\n ctx.stroke();\n ctx.restore();\n }\n\n /**\n * Draw a series color indicator (small circle or square)\n */\n drawSeriesIndicator(x: number, y: number, color: string): void {\n const { ctx, theme } = this;\n\n if (!theme.showSeriesIndicator) return;\n\n const size = theme.seriesIndicatorSize;\n const radius = size / 2;\n\n ctx.save();\n ctx.fillStyle = color;\n ctx.beginPath();\n ctx.arc(x + radius, y, radius, 0, Math.PI * 2);\n ctx.fill();\n ctx.restore();\n }\n\n /**\n * Measure text width\n */\n measureText(text: string, fontSize: number, fontWeight: number | string = 400): number {\n const { ctx, theme } = this;\n ctx.font = `${fontWeight} ${fontSize}px ${theme.fontFamily}`;\n return ctx.measureText(text).width;\n }\n\n /**\n * Draw text with theme styling\n */\n drawText(\n text: string,\n x: number,\n y: number,\n options: {\n fontSize?: number;\n fontWeight?: number | string;\n color?: string;\n align?: CanvasTextAlign;\n baseline?: CanvasTextBaseline;\n } = {}\n ): void {\n const { ctx, theme } = this;\n const {\n fontSize = theme.contentFontSize,\n fontWeight = 400,\n color = theme.textColor,\n align = 'left',\n baseline = 'top'\n } = options;\n\n ctx.save();\n ctx.font = `${fontWeight} ${fontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = color;\n ctx.textAlign = align;\n ctx.textBaseline = baseline;\n ctx.fillText(text, x, y);\n ctx.restore();\n }\n\n /**\n * Draw a label-value pair\n */\n drawLabelValue(\n x: number,\n y: number,\n label: string,\n value: string,\n maxWidth: number\n ): void {\n const { theme } = this;\n\n // Draw label (secondary color)\n this.drawText(label, x, y, {\n color: theme.textSecondaryColor,\n fontSize: theme.contentFontSize\n });\n\n // Draw value (primary color, right-aligned)\n this.drawText(value, x + maxWidth, y, {\n color: theme.textColor,\n fontSize: theme.contentFontSize,\n align: 'right'\n });\n }\n\n /**\n * Get theme for external use\n */\n getTheme(): TooltipTheme {\n return this.theme;\n }\n}\n\n/**\n * Create a tooltip renderer\n */\nexport function createTooltipRenderer(\n ctx: CanvasRenderingContext2D,\n theme: TooltipTheme\n): TooltipRenderer {\n return new TooltipRenderer(ctx, theme);\n}\n","/**\n * Shared tooltip value formatting — delegates to axisFormat when axis context exists.\n */\nimport type { DataPointTooltip, CrosshairTooltip } from \"./types\";\nimport { formatTooltipX, formatTooltipY } from \"../../../core/format/axisFormat\";\n\nexport function formatDataPointX(data: DataPointTooltip): string {\n if (data.axisFormat) return formatTooltipX(data.dataX, data.axisFormat);\n return formatFallbackNumber(data.dataX);\n}\n\nexport function formatDataPointY(data: DataPointTooltip): string {\n if (data.axisFormat) return formatTooltipY(data.dataY, data.axisFormat);\n return formatFallbackNumber(data.dataY);\n}\n\nexport function formatCrosshairX(data: CrosshairTooltip): string {\n if (data.axisFormat) return formatTooltipX(data.dataX, data.axisFormat);\n return formatFallbackNumber(data.dataX);\n}\n\nexport function formatCrosshairY(value: number, data: CrosshairTooltip): string {\n if (data.axisFormat) return formatTooltipY(value, data.axisFormat);\n return formatFallbackNumber(value);\n}\n\nfunction formatFallbackNumber(value: number | null | undefined): string {\n if (value === null || value === undefined || isNaN(value)) return \"N/A\";\n const absVal = Math.abs(value);\n if (absVal === 0) return \"0\";\n if (absVal < 0.0001 || absVal >= 10000) return value.toExponential(2);\n if (absVal < 0.01) return value.toPrecision(4);\n if (absVal < 1) return value.toFixed(4);\n if (absVal < 100) return value.toFixed(3);\n return value.toFixed(1);\n}\n\nexport function formatCompactValue(data: DataPointTooltip, axis: \"x\" | \"y\"): string {\n const value = axis === \"x\" ? data.dataX : data.dataY;\n if (data.axisFormat) {\n return axis === \"x\"\n ? formatTooltipX(value, data.axisFormat)\n : formatTooltipY(value, data.axisFormat);\n }\n if (value === null || value === undefined || isNaN(value)) return \"N/A\";\n const absVal = Math.abs(value);\n if (absVal === 0) return \"0\";\n if (absVal >= 1e9) return (value / 1e9).toFixed(1) + \"G\";\n if (absVal >= 1e6) return (value / 1e6).toFixed(1) + \"M\";\n if (absVal >= 1e3) return (value / 1e3).toFixed(1) + \"k\";\n if (absVal >= 1) return value.toFixed(2);\n if (absVal >= 1e-3) return (value * 1e3).toFixed(1) + \"m\";\n if (absVal >= 1e-6) return (value * 1e6).toFixed(1) + \"µ\";\n if (absVal >= 1e-9) return (value * 1e9).toFixed(1) + \"n\";\n return value.toExponential(1);\n}\n","/**\n * Default Tooltip Template\n * \n * A clean, elegant template for data point tooltips with:\n * - Series color indicator\n * - Formatted X/Y values\n * - Optional error bars\n * - Cycle information\n * \n * @module tooltip/templates/DefaultTemplate\n */\n\nimport type {\n DataPointTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\nimport { formatDataPointX, formatDataPointY } from '../format';\n\nfunction formatValue(value: number | null | undefined, data?: DataPointTooltip, axis?: 'x' | 'y'): string {\n if (data && axis === 'x') return formatDataPointX(data);\n if (data && axis === 'y') return formatDataPointY(data);\n if (value === null || value === undefined || isNaN(value)) return \"N/A\";\n const absVal = Math.abs(value);\n if (absVal !== 0 && (absVal < 0.0001 || absVal >= 10000)) return value.toExponential(2);\n if (absVal < 0.01) return value.toPrecision(4);\n if (absVal < 1) return value.toFixed(4);\n if (absVal < 100) return value.toFixed(3);\n return value.toFixed(1);\n}\n\n/**\n * Default Data Point Template\n * \n * Visual layout:\n * ┌──────────────────────────┐\n * │ ● Series Name │\n * │ ─────────────────────── │\n * │ X: 0.500 │\n * │ Y: 1.234 │\n * │ ± Error: 0.05 │\n * └──────────────────────────┘\n */\nexport class DefaultTooltipTemplate implements TooltipTemplate<DataPointTooltip> {\n readonly id = 'default';\n readonly name = 'Default Data Point';\n readonly supportedTypes: TooltipType[] = ['datapoint'];\n\n // Cached measurements\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n // Create cache key\n const cacheKey = `${data.seriesId}-${data.dataIndex}-${data.dataX}-${data.dataY}`;\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Set up font for measurement\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n \n // Measure title (series name)\n const titleWidth = ctx.measureText(data.seriesName).width;\n \n // Set content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n // Format values\n const labelWidth = 35;\n const xValWidth = ctx.measureText(formatValue(data.dataX, data, 'x')).width;\n const yValWidth = ctx.measureText(formatValue(data.dataY, data, 'y')).width;\n \n // Measure content lines\n let contentWidth = labelWidth + Math.max(xValWidth, yValWidth);\n \n let contentHeight = theme.contentFontSize * theme.lineHeight * 2;\n \n // Add error info if present\n if (data.yError) {\n const errorText = `± ${formatValue(data.yError[0])} / ${formatValue(data.yError[1])}`;\n contentWidth = Math.max(contentWidth, ctx.measureText(errorText).width);\n contentHeight += theme.contentFontSize * theme.lineHeight;\n }\n \n // Add cycle info if present\n if (data.cycle !== undefined) {\n const cycleText = `Cycle: ${data.cycle}`;\n contentWidth = Math.max(contentWidth, ctx.measureText(cycleText).width);\n contentHeight += theme.contentFontSize * theme.lineHeight;\n }\n \n // Account for series indicator\n const indicatorWidth = theme.showSeriesIndicator \n ? theme.seriesIndicatorSize + 6 \n : 0;\n \n // Calculate total width\n const width = Math.max(titleWidth + indicatorWidth, contentWidth);\n \n // Calculate total height (title + separator + content)\n const height = theme.titleFontSize * theme.lineHeight + theme.headerGap + contentHeight;\n \n this.cachedMeasurement = {\n width: width + 2, // Tiny buffer\n height: height + 4,\n padding: theme.padding,\n arrow: theme.showArrow ? { width: theme.arrowSize * 2, height: theme.arrowSize } : undefined\n };\n this.cachedKey = cacheKey;\n \n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { x, y } = position;\n const { padding } = theme;\n \n // Start position for content\n let currentX = x + padding.left;\n let currentY = y + padding.top;\n \n // Explicitly set alignment to avoid inheritance issues\n ctx.save();\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n \n // Draw series indicator\n if (theme.showSeriesIndicator) {\n const indicatorY = currentY + theme.titleFontSize / 2;\n ctx.save();\n ctx.fillStyle = data.seriesColor;\n ctx.beginPath();\n ctx.arc(currentX + theme.seriesIndicatorSize / 2, indicatorY, theme.seriesIndicatorSize / 2, 0, Math.PI * 2);\n ctx.fill();\n ctx.restore();\n \n currentX += theme.seriesIndicatorSize + 6;\n }\n \n // Draw title (series name)\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n ctx.fillText(data.seriesName, currentX, currentY);\n \n currentY += theme.titleFontSize * theme.lineHeight + 2; // Extra space\n \n // Draw separator\n if (theme.showHeaderSeparator) {\n const separatorWidth = measurement.width;\n \n ctx.save();\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.globalAlpha = 0.4; // Softer separator\n ctx.beginPath();\n ctx.moveTo(x + padding.left, currentY + theme.headerGap / 2);\n ctx.lineTo(x + padding.left + separatorWidth, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.restore();\n }\n \n currentY += theme.headerGap + 2; // Better gap\n currentX = x + padding.left; // Reset X\n \n // Draw content\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n // X value\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('X:', currentX, currentY);\n ctx.fillStyle = theme.textColor;\n const labelWidth = 35; // Fixed label width for better alignment\n ctx.fillText(formatValue(data.dataX, data, 'x'), currentX + labelWidth, currentY);\n currentY += theme.contentFontSize * theme.lineHeight + 2;\n \n // Y value\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Y:', currentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.dataY, data, 'y'), currentX + labelWidth, currentY);\n currentY += theme.contentFontSize * theme.lineHeight + 2;\n \n // Error if present\n if (data.yError) {\n ctx.fillStyle = theme.textSecondaryColor;\n const errorText = `± ${formatValue(data.yError[0])} / +${formatValue(data.yError[1])}`;\n ctx.fillText(errorText, currentX, currentY);\n currentY += theme.contentFontSize * theme.lineHeight;\n }\n \n // Cycle if present\n if (data.cycle !== undefined) {\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Cycle:', currentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(String(data.cycle), currentX + 45, currentY);\n }\n \n ctx.restore();\n }\n}\n\n// Export singleton instance\nexport const defaultTooltipTemplate = new DefaultTooltipTemplate();\n","/**\n * Minimal Tooltip Template\n * \n * Ultra-compact template showing only essential values.\n * Perfect for dashboards with limited space.\n * \n * @module tooltip/templates/MinimalTemplate\n */\n\nimport type {\n DataPointTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\nimport { formatCompactValue } from '../format';\n\n/**\n * Minimal Template\n * \n * Visual layout:\n * ┌───────────────────╮\n * │ 0.500 ▪ 1.23µA │\n * ╰───────────────────╯\n */\nexport class MinimalTooltipTemplate implements TooltipTemplate<DataPointTooltip> {\n readonly id = 'minimal';\n readonly name = 'Minimal';\n readonly supportedTypes: TooltipType[] = ['datapoint'];\n\n // Cached measurements\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n // Cache key\n const cacheKey = `${data.seriesId}-${data.dataIndex}-${data.dataX}-${data.dataY}-${theme.fontFamily}`;\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Set font for measurement\n ctx.font = `${theme.contentFontSize}px ${theme.fontFamily}`;\n \n // Create compact text\n const text = `${formatCompactValue(data, 'x')} ▪ ${formatCompactValue(data, 'y')}`;\n const textWidth = ctx.measureText(text).width;\n \n this.cachedMeasurement = {\n width: textWidth,\n height: theme.contentFontSize * theme.lineHeight,\n padding: {\n top: 6,\n right: 8,\n bottom: 6,\n left: 8\n }\n };\n this.cachedKey = cacheKey;\n \n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { padding } = measurement;\n const x = position.x + padding.left;\n const y = position.y + padding.top;\n \n // Create compact text\n const xValue = formatCompactValue(data, 'x');\n const yValue = formatCompactValue(data, 'y');\n \n ctx.save();\n ctx.font = `${theme.contentFontSize}px ${theme.fontFamily}`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n \n // Draw X value\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText(xValue, x, y);\n \n // Draw separator\n const xWidth = ctx.measureText(xValue).width;\n ctx.fillStyle = data.seriesColor;\n ctx.fillText(' ▪ ', x + xWidth, y);\n \n // Draw Y value\n const sepWidth = ctx.measureText(' ▪ ').width;\n ctx.fillStyle = theme.textColor;\n ctx.fillText(yValue, x + xWidth + sepWidth, y);\n \n ctx.restore();\n }\n}\n\n// Export singleton instance\nexport const minimalTooltipTemplate = new MinimalTooltipTemplate();\n","/**\n * Crosshair Tooltip Template\n *\n * Multi-series template for crosshair tooltips showing\n * interpolated values for all visible series at cursor position.\n *\n * @module tooltip/templates/CrosshairTemplate\n */\n\nimport type {\n CrosshairTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType,\n} from \"../types\";\nimport { formatCrosshairX, formatCrosshairY } from \"../format\";\n\n// Constants for spacing and layout\nconst SPACING = {\n INDICATOR_MARGIN: 8,\n MIN_LABEL_WIDTH: 60,\n LINE_SPACING: 2,\n SAFETY_BUFFER: 4,\n HEADER_SPACING: 2,\n GAP_SPACING: 2,\n} as const;\n\n/**\n * Formatted series data for caching\n */\ninterface FormattedSeriesData {\n name: string;\n value: string;\n color: string;\n isInterpolated: boolean;\n}\n\n/**\n * Crosshair Multi-Series Template\n *\n * Visual layout:\n * ┌──────────────────────────────────╮\n * │ ⌖ X = 0.234 │\n * ├──────────────────────────────────┤\n * │ ● Forward: 45.67 µA │\n * │ ● Reverse: -32.10 µA │\n * │ ○ Baseline: 0.05 µA │\n * ╰──────────────────────────────────╯\n */\nexport class CrosshairTooltipTemplate implements TooltipTemplate<CrosshairTooltip> {\n readonly id = \"crosshair\";\n readonly name = \"Multi-Series Crosshair\";\n readonly supportedTypes: TooltipType[] = [\"crosshair\"];\n\n // Cached measurements\n private cachedKey: string = \"\";\n private cachedMeasurement: TooltipMeasurement | null = null;\n private formattedData: {\n header: string;\n series: FormattedSeriesData[];\n } | null = null;\n\n /**\n * Generate cache key from data and theme\n */\n private getCacheKey(data: CrosshairTooltip, theme: TooltipTheme): string {\n const seriesHash = data.interpolatedValues\n .map((s) => `${s.seriesName}-${s.y}`)\n .join(\"|\");\n \n return [\n data.dataX,\n seriesHash,\n theme.fontFamily,\n theme.titleFontSize,\n theme.contentFontSize,\n theme.showSeriesIndicator,\n theme.seriesIndicatorSize,\n `${theme.padding.top}-${theme.padding.right}-${theme.padding.bottom}-${theme.padding.left}`,\n ].join(\":\");\n }\n\n /**\n * Format data for rendering\n */\n private formatData(data: CrosshairTooltip): {\n header: string;\n series: FormattedSeriesData[];\n } {\n return {\n header: `⌖ X = ${formatCrosshairX(data)}`,\n series: data.interpolatedValues.map((s) => ({\n name: s.seriesName,\n value: formatCrosshairY(s.y, data),\n color: s.seriesColor,\n isInterpolated: s.isInterpolated,\n })),\n };\n }\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: CrosshairTooltip,\n theme: TooltipTheme,\n ): TooltipMeasurement {\n // Validate input\n if (!data.interpolatedValues || data.interpolatedValues.length === 0) {\n return {\n width: 100,\n height: theme.titleFontSize * theme.lineHeight,\n padding: theme.padding,\n };\n }\n\n // Check cache\n const cacheKey = this.getCacheKey(data, theme);\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Format data once\n this.formattedData = this.formatData(data);\n\n // Set title font\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n\n // Measure header\n let maxWidth = ctx.measureText(this.formattedData.header).width;\n\n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n\n // Measure each series line\n const indicatorWidth = theme.showSeriesIndicator\n ? theme.seriesIndicatorSize + SPACING.INDICATOR_MARGIN\n : 0;\n\n for (const series of this.formattedData.series) {\n const nameWidth = ctx.measureText(`${series.name}:`).width;\n const valWidth = ctx.measureText(series.value).width;\n const lineWidth =\n indicatorWidth + Math.max(nameWidth, SPACING.MIN_LABEL_WIDTH) + valWidth;\n maxWidth = Math.max(maxWidth, lineWidth);\n }\n\n // Calculate height\n const headerHeight = theme.titleFontSize * theme.lineHeight;\n const seriesCount = this.formattedData.series.length;\n const contentHeight =\n seriesCount * (theme.contentFontSize * theme.lineHeight + SPACING.LINE_SPACING);\n\n this.cachedMeasurement = {\n width: maxWidth + SPACING.SAFETY_BUFFER,\n height: headerHeight + theme.headerGap + contentHeight,\n padding: theme.padding,\n };\n this.cachedKey = cacheKey;\n\n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: CrosshairTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme,\n ): void {\n // Validate input\n if (!data.interpolatedValues || data.interpolatedValues.length === 0) {\n return;\n }\n\n // Use cached formatted data if available\n const formatted = this.formattedData || this.formatData(data);\n\n const { x, y } = position;\n const { padding } = theme;\n\n let currentY = y + padding.top;\n const contentX = x + padding.left;\n\n // Draw header: \"⌖ X = value\"\n ctx.save();\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"top\";\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n\n ctx.fillText(formatted.header, contentX, currentY);\n\n currentY += theme.titleFontSize * theme.lineHeight + SPACING.HEADER_SPACING;\n\n // Draw separator\n if (theme.showHeaderSeparator) {\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.globalAlpha = 0.4;\n ctx.beginPath();\n ctx.moveTo(contentX, currentY + theme.headerGap / 2);\n ctx.lineTo(contentX + measurement.width, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1.0;\n }\n\n currentY += theme.headerGap + SPACING.GAP_SPACING;\n\n // Draw each series\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n\n for (const series of formatted.series) {\n let itemX = contentX;\n\n // Series indicator\n if (theme.showSeriesIndicator && theme.seriesIndicatorSize > 0) {\n const indicatorY = currentY + theme.contentFontSize / 2;\n const radius = theme.seriesIndicatorSize / 2;\n\n ctx.save();\n ctx.beginPath();\n ctx.arc(itemX + radius, indicatorY, radius, 0, Math.PI * 2);\n\n if (series.isInterpolated) {\n ctx.strokeStyle = series.color;\n ctx.lineWidth = 1.5;\n ctx.stroke();\n } else {\n ctx.fillStyle = series.color;\n ctx.fill();\n }\n ctx.restore();\n\n itemX += theme.seriesIndicatorSize + SPACING.INDICATOR_MARGIN;\n }\n\n // Series name\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText(`${series.name}:`, itemX, currentY);\n\n const nameWidth = ctx.measureText(`${series.name}: `).width;\n const labelOffset = Math.max(nameWidth, SPACING.MIN_LABEL_WIDTH);\n\n // Series value\n ctx.fillStyle = theme.textColor;\n ctx.fillText(series.value, itemX + labelOffset, currentY);\n\n currentY += theme.contentFontSize * theme.lineHeight + SPACING.LINE_SPACING;\n }\n\n ctx.restore();\n }\n}\n\n// Export singleton instance\nexport const crosshairTooltipTemplate = new CrosshairTooltipTemplate();\n","/**\n * Heatmap Tooltip Template\n * \n * Specialized template for heatmap tooltips showing:\n * - Grid position\n * - Z value with color preview\n * - Scale information\n * \n * @module tooltip/templates/HeatmapTemplate\n */\n\nimport type {\n HeatmapTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\n\n/**\n * Format a number for display\n */\nfunction formatValue(value: number | null | undefined): string {\n if (value === null || value === undefined || isNaN(value)) {\n return \"N/A\";\n }\n\n const absVal = Math.abs(value);\n\n if (absVal === 0) return \"0\";\n if (absVal < 0.0001 || absVal >= 10000) {\n return value.toExponential(3);\n }\n if (absVal < 0.01) return value.toPrecision(4);\n if (absVal < 1) return value.toFixed(4);\n if (absVal < 100) return value.toFixed(3);\n return value.toFixed(2);\n}\n\n/**\n * Heatmap Template\n * \n * Visual layout:\n * ┌────────────────────────────╮\n * │ Grid [45, 128] │\n * │ ──────────────────────────│\n * │ ████ Value: 0.847 │\n * │ Min: 0.0 Max: 1.0 │\n * │ │\n * │ X: 100.0 Hz │\n * │ Y: 2.50 s │\n * ╰────────────────────────────╯\n */\nexport class HeatmapTooltipTemplate implements TooltipTemplate<HeatmapTooltip> {\n readonly id = 'heatmap';\n readonly name = 'Heatmap Value';\n readonly supportedTypes: TooltipType[] = ['heatmap'];\n\n // Color swatch dimensions\n private readonly swatchSize = 14;\n private readonly swatchGap = 8;\n\n // Cached measurements\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: HeatmapTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n // Cache key\n const cacheKey = `${data.seriesId}-${data.xIndex}-${data.yIndex}-${theme.fontFamily}-${theme.titleFontSize}`;\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Set title font\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n \n // Header: \"Grid [x, y]\"\n const headerText = `Grid [${data.xIndex}, ${data.yIndex}]`;\n let maxWidth = ctx.measureText(headerText).width;\n \n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n // Value line with color swatch (swatch + gap + text)\n const valueText = `Value: ${formatValue(data.zValue)}`;\n const valueWidth = this.swatchSize + this.swatchGap + ctx.measureText(valueText).width;\n maxWidth = Math.max(maxWidth, valueWidth);\n \n // Scale info\n if (data.colorScale) {\n const scaleText = `Min: ${formatValue(data.colorScale.min)} Max: ${formatValue(data.colorScale.max)}`;\n maxWidth = Math.max(maxWidth, this.swatchSize + this.swatchGap + ctx.measureText(scaleText).width);\n }\n \n // X/Y data values\n const xyLabelWidth = 25; // Adjusted to match fixed offset in render\n const dataXWidth = xyLabelWidth + ctx.measureText(formatValue(data.dataX)).width;\n const dataYWidth = xyLabelWidth + ctx.measureText(formatValue(data.dataY)).width;\n maxWidth = Math.max(maxWidth, dataXWidth, dataYWidth);\n \n // Calculate height\n const headerHeight = theme.titleFontSize * theme.lineHeight;\n const contentLines = data.colorScale ? 4 : 3; // value, (scale), X, Y\n const contentHeight = contentLines * theme.contentFontSize * theme.lineHeight;\n \n this.cachedMeasurement = {\n width: maxWidth + 4, // Small buffer\n height: headerHeight + theme.headerGap + contentHeight + theme.itemGap,\n padding: theme.padding\n };\n this.cachedKey = cacheKey;\n \n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: HeatmapTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { x, y } = position;\n const { padding } = theme;\n \n let currentY = y + padding.top;\n const contentX = x + padding.left;\n \n // Draw header: \"Grid [x, y]\"\n ctx.save();\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n \n const headerText = `Grid [${data.xIndex}, ${data.yIndex}]`;\n ctx.fillText(headerText, contentX, currentY);\n \n currentY += theme.titleFontSize * theme.lineHeight + 2;\n \n // Draw separator\n if (theme.showHeaderSeparator) {\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.globalAlpha = 0.4;\n ctx.beginPath();\n ctx.moveTo(contentX, currentY + theme.headerGap / 2);\n ctx.lineTo(contentX + measurement.width, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1.0;\n }\n \n currentY += theme.headerGap + 2;\n \n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n // Draw color swatch with value\n const swatchY = currentY + (theme.contentFontSize * theme.lineHeight - this.swatchSize) / 2;\n \n // Color swatch with border\n ctx.fillStyle = data.mappedColor || theme.textColor;\n ctx.fillRect(contentX, swatchY, this.swatchSize, this.swatchSize);\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.strokeRect(contentX, swatchY, this.swatchSize, this.swatchSize);\n \n // Value text\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Value:', contentX + this.swatchSize + this.swatchGap, currentY);\n ctx.fillStyle = theme.textColor;\n const labelWidth = ctx.measureText('Value: ').width;\n ctx.fillText(formatValue(data.zValue), contentX + this.swatchSize + this.swatchGap + labelWidth, currentY);\n \n currentY += theme.contentFontSize * theme.lineHeight;\n \n // Scale info (indented to align with value)\n if (data.colorScale) {\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.font = `400 ${theme.contentFontSize - 1}px ${theme.fontFamily}`;\n const scaleText = `Min: ${formatValue(data.colorScale.min)} Max: ${formatValue(data.colorScale.max)}`;\n ctx.fillText(scaleText, contentX + this.swatchSize + this.swatchGap, currentY);\n currentY += theme.contentFontSize * theme.lineHeight;\n }\n \n currentY += theme.itemGap + 2;\n \n // X value\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('X:', contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.dataX), contentX + 25, currentY);\n \n currentY += theme.contentFontSize * theme.lineHeight + 2;\n \n // Y value\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Y:', contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.dataY), contentX + 25, currentY);\n \n ctx.restore();\n }\n}\n\n// Export singleton instance\nexport const heatmapTooltipTemplate = new HeatmapTooltipTemplate();\n","/**\n * Scientific Tooltip Template\n * \n * Full precision scientific template with:\n * - Proper scientific notation with superscripts\n * - Units and prefixes\n * - Complete error values\n * - Extended metadata\n * \n * @module tooltip/templates/ScientificTemplate\n */\n\nimport type {\n DataPointTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\nimport { formatDataPointX, formatDataPointY } from '../format';\n\nfunction formatXValue(data: DataPointTooltip): string {\n if (data.axisFormat?.x?.type === 'time') return formatDataPointX(data);\n return toScientificUnicode(data.dataX);\n}\n\nfunction formatYValue(data: DataPointTooltip): string {\n if (data.axisFormat?.y?.scientific === false) return formatDataPointY(data);\n return toScientificUnicode(data.dataY);\n}\n\n/**\n * Convert number to scientific notation with Unicode superscripts\n */\nfunction toScientificUnicode(\n value: number | null | undefined,\n precision: number = 3\n): string {\n if (value === null || value === undefined || isNaN(value)) {\n return \"N/A\";\n }\n\n if (value === 0) return \"0\";\n\n const exp = Math.floor(Math.log10(Math.abs(value)));\n const mantissa = value / Math.pow(10, exp);\n\n if (Math.abs(exp) <= 2) {\n // Don't use scientific notation for small exponents\n return value.toPrecision(precision);\n }\n\n // Superscript map\n const superscripts: Record<string, string> = {\n \"0\": \"⁰\",\n \"1\": \"¹\",\n \"2\": \"²\",\n \"3\": \"³\",\n \"4\": \"⁴\",\n \"5\": \"⁵\",\n \"6\": \"⁶\",\n \"7\": \"⁷\",\n \"8\": \"⁸\",\n \"9\": \"⁹\",\n \"-\": \"⁻\",\n \"+\": \"⁺\",\n };\n\n // Convert exponent to superscript\n const expStr = exp.toString();\n let superExp = \"\";\n for (const char of expStr) {\n superExp += superscripts[char] || char;\n }\n\n return `${mantissa.toFixed(precision - 1)} × 10${superExp}`;\n}\n\n/**\n * Format with SI prefix (for future use)\n */\n// function formatWithPrefix(value: number, unit: string = ''): string {\n// const prefixes = [\n// { exp: 12, prefix: 'T' },\n// { exp: 9, prefix: 'G' },\n// { exp: 6, prefix: 'M' },\n// { exp: 3, prefix: 'k' },\n// { exp: 0, prefix: '' },\n// { exp: -3, prefix: 'm' },\n// { exp: -6, prefix: 'µ' },\n// { exp: -9, prefix: 'n' },\n// { exp: -12, prefix: 'p' }\n// ];\n// \n// if (value === 0) return `0 ${unit}`;\n// \n// const absVal = Math.abs(value);\n// \n// for (const { exp, prefix } of prefixes) {\n// if (absVal >= Math.pow(10, exp - 1)) {\n// const scaled = value / Math.pow(10, exp);\n// return `${scaled.toFixed(3)} ${prefix}${unit}`;\n// }\n// }\n// \n// return `${value.toExponential(3)} ${unit}`;\n// }\n\n/**\n * Scientific Template\n * \n * Visual layout:\n * ┌────────────────────────────────────────╮\n * │ 📍 Series Name │\n * │ ───────────────────────────────────── │\n * │ X: 1.234×10³ │\n * │ Y: 5.678×10⁻² ± 0.001 │\n * │ ───────────────────────────────────── │\n * │ Index: 1523 │ Cycle: 3 │\n * ╰────────────────────────────────────────╯\n */\nexport class ScientificTooltipTemplate implements TooltipTemplate<DataPointTooltip> {\n readonly id = 'scientific';\n readonly name = 'Scientific Notation';\n readonly supportedTypes: TooltipType[] = ['datapoint'];\n\n // Cached measurements\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n // Cache key\n const cacheKey = `${data.seriesId}-${data.dataIndex}-${data.dataX}-${data.dataY}-${theme.fontFamily}-${theme.titleFontSize}`;\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Title font\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n \n const titleWidth = ctx.measureText(data.seriesName).width + \n (theme.showSeriesIndicator ? theme.seriesIndicatorSize + 8 : 0);\n \n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n const labelWidth = 28; // Fixed width used in render\n \n // X value\n const xVal = formatXValue(data);\n let maxWidth = Math.max(titleWidth, labelWidth + ctx.measureText(xVal).width);\n \n // Y value with optional error\n const yVal = formatYValue(data);\n let yWidth = labelWidth + ctx.measureText(yVal).width;\n if (data.yError) {\n yWidth += ctx.measureText(` ± ${toScientificUnicode(data.yError[0])}`).width;\n }\n maxWidth = Math.max(maxWidth, yWidth);\n \n // Footer line\n let footerText = `Index: ${data.dataIndex}`;\n if (data.cycle !== undefined) {\n footerText += ` │ Cycle: ${data.cycle}`;\n }\n maxWidth = Math.max(maxWidth, ctx.measureText(footerText).width);\n \n // Height calculation\n let lineCount = 3; // title, X, Y\n if (data.cycle !== undefined || data.yError) {\n lineCount += 1; // footer\n }\n \n const headerHeight = theme.titleFontSize * theme.lineHeight + theme.headerGap;\n const contentHeight = (lineCount - 1) * theme.contentFontSize * theme.lineHeight;\n const extraGap = (data.cycle !== undefined) ? theme.itemGap : 0;\n \n this.cachedMeasurement = {\n width: maxWidth,\n height: headerHeight + contentHeight + extraGap,\n padding: theme.padding\n };\n this.cachedKey = cacheKey;\n \n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { x, y } = position;\n const { padding } = theme;\n \n let currentY = y + padding.top;\n let currentX = x + padding.left;\n \n ctx.save();\n \n // Explicitly set alignment\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n \n // Draw series indicator\n if (theme.showSeriesIndicator) {\n const indicatorY = currentY + theme.titleFontSize / 2;\n ctx.fillStyle = data.seriesColor;\n ctx.beginPath();\n ctx.arc(currentX + theme.seriesIndicatorSize / 2, indicatorY, theme.seriesIndicatorSize / 2, 0, Math.PI * 2);\n ctx.fill();\n currentX += theme.seriesIndicatorSize + 8;\n }\n \n // Title\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n ctx.fillText(data.seriesName, currentX, currentY);\n \n currentY += theme.titleFontSize * theme.lineHeight + 2;\n currentX = x + padding.left;\n \n // Separator\n if (theme.showHeaderSeparator) {\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.globalAlpha = 0.4;\n ctx.beginPath();\n ctx.moveTo(currentX, currentY + theme.headerGap / 2);\n ctx.lineTo(currentX + measurement.width, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1.0;\n }\n \n currentY += theme.headerGap + 2;\n \n // Content\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n const labelWidth = 28;\n \n // X value\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('X:', currentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatXValue(data), currentX + labelWidth, currentY);\n currentY += theme.contentFontSize * theme.lineHeight + 2;\n \n // Y value with error\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Y:', currentX, currentY);\n ctx.fillStyle = theme.textColor;\n \n let yText = formatYValue(data);\n ctx.fillText(yText, currentX + labelWidth, currentY);\n \n if (data.yError) {\n const yWidth = ctx.measureText(yText).width;\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText(` ± ${toScientificUnicode(data.yError[0])}`, currentX + labelWidth + yWidth, currentY);\n }\n currentY += theme.contentFontSize * theme.lineHeight + 2;\n \n // Footer with index and cycle\n if (data.cycle !== undefined) {\n currentY += theme.itemGap;\n \n // Light separator\n ctx.strokeStyle = theme.separatorColor;\n ctx.globalAlpha = 0.3;\n ctx.beginPath();\n ctx.moveTo(currentX, currentY - theme.itemGap / 2);\n ctx.lineTo(currentX + measurement.width, currentY - theme.itemGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1;\n \n // Footer text\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.font = `400 ${theme.contentFontSize - 1}px ${theme.fontFamily}`;\n \n let footerText = `Index: ${data.dataIndex}`;\n if (data.cycle !== undefined) {\n footerText += ` │ Cycle: ${data.cycle}`;\n }\n ctx.fillText(footerText, currentX, currentY);\n }\n \n ctx.restore();\n }\n}\n\n// Export singleton instance\nexport const scientificTooltipTemplate = new ScientificTooltipTemplate();\n","/**\n * Annotation Tooltip Template\n * \n * Template for displaying information about chart annotations:\n * - Annotation type and ID\n * - Labeled values\n * - Custom metadata\n * \n * @module tooltip/templates/AnnotationTemplate\n */\n\nimport type {\n AnnotationTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\n\n/**\n * Format a number for display\n */\nfunction formatValue(value: number | null | undefined): string {\n if (value === null || value === undefined || isNaN(value)) {\n return \"N/A\";\n }\n\n const absVal = Math.abs(value);\n if (absVal === 0) return \"0\";\n if (absVal < 0.0001 || absVal >= 10000) return value.toExponential(2);\n if (absVal < 1) return value.toFixed(4);\n return value.toFixed(2);\n}\n\nexport class AnnotationTooltipTemplate implements TooltipTemplate<AnnotationTooltip> {\n readonly id = 'annotation';\n readonly name = 'Annotation Info';\n readonly supportedTypes: TooltipType[] = ['annotation'];\n\n // Cache\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: AnnotationTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n const cacheKey = `${data.annotationId}-${data.label}-${theme.fontFamily}-${theme.titleFontSize}`;\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Header font\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n const headerText = data.label || `Annotation: ${data.annotationType}`;\n let maxWidth = ctx.measureText(headerText).width;\n\n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n let contentHeight = 0;\n const labelWidth = 50;\n\n // Value lines\n if (data.value !== undefined) {\n const valText = formatValue(data.value);\n maxWidth = Math.max(maxWidth, labelWidth + ctx.measureText(valText).width);\n contentHeight += theme.contentFontSize * theme.lineHeight;\n }\n if (data.valueX !== undefined && data.valueY !== undefined) {\n const xText = formatValue(data.valueX);\n const yText = formatValue(data.valueY);\n maxWidth = Math.max(maxWidth, labelWidth + ctx.measureText(xText).width, labelWidth + ctx.measureText(yText).width);\n contentHeight += (theme.contentFontSize * theme.lineHeight) * 2;\n }\n\n const headerHeight = theme.titleFontSize * theme.lineHeight + theme.headerGap;\n \n this.cachedMeasurement = {\n width: maxWidth + 10,\n height: headerHeight + contentHeight + 4,\n padding: theme.padding\n };\n this.cachedKey = cacheKey;\n\n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: AnnotationTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { x, y } = position;\n const { padding } = theme;\n \n let currentY = y + padding.top;\n const contentX = x + padding.left;\n\n ctx.save();\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n\n // Header\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n const headerText = data.label || `${data.annotationType.toUpperCase()}`;\n ctx.fillText(headerText, contentX, currentY);\n \n currentY += theme.titleFontSize * theme.lineHeight + 2;\n\n // Separator\n if (theme.showHeaderSeparator) {\n ctx.strokeStyle = theme.separatorColor;\n ctx.globalAlpha = 0.4;\n ctx.beginPath();\n ctx.moveTo(contentX, currentY + theme.headerGap / 2);\n ctx.lineTo(contentX + measurement.width, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1.0;\n }\n\n currentY += theme.headerGap + 2;\n\n // Content\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n const labelW = 50;\n\n if (data.value !== undefined) {\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Value:', contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.value), contentX + labelW, currentY);\n currentY += theme.contentFontSize * theme.lineHeight;\n }\n\n if (data.valueX !== undefined && data.valueY !== undefined) {\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('X:', contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.valueX), contentX + labelW, currentY);\n currentY += theme.contentFontSize * theme.lineHeight;\n\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Y:', contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.valueY), contentX + labelW, currentY);\n }\n\n ctx.restore();\n }\n}\n\nexport const annotationTooltipTemplate = new AnnotationTooltipTemplate();\n","/**\n * Range Tooltip Template\n * \n * Displays statistical information for a selected range:\n * - Count of points\n * - Min/Max/Mean values\n * - Area and Peaks\n * \n * @module tooltip/templates/RangeTemplate\n */\n\nimport type {\n RangeTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\n\n/**\n * Format a number for display\n */\nfunction formatValue(value: number | null | undefined): string {\n if (value === null || value === undefined || isNaN(value)) {\n return \"N/A\";\n }\n\n const absVal = Math.abs(value);\n if (absVal === 0) return \"0\";\n if (absVal < 0.0001 || absVal >= 10000) return value.toExponential(3);\n if (absVal < 1) return value.toFixed(4);\n return value.toFixed(3);\n}\n\nexport class RangeTooltipTemplate implements TooltipTemplate<RangeTooltip> {\n readonly id = 'range';\n readonly name = 'Range Statistics';\n readonly supportedTypes: TooltipType[] = ['range'];\n\n // Cache\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: RangeTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n const stats = data.statistics;\n const cacheKey = `${data.xMin}-${data.xMax}-${stats.count}-${stats.mean}-${theme.fontFamily}`;\n \n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Title font\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n const headerText = 'Range Statistics';\n let maxWidth = ctx.measureText(headerText).width;\n\n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n let contentHeight = theme.contentFontSize * theme.lineHeight * 2; // Range and Count are always shown\n \n const lines = [\n `Range: ${formatValue(data.xMin)} to ${formatValue(data.xMax)}`,\n `Count: ${stats.count}`\n ];\n\n if (stats.min !== undefined) lines.push(`Min: ${formatValue(stats.min)}`);\n if (stats.max !== undefined) lines.push(`Max: ${formatValue(stats.max)}`);\n if (stats.mean !== undefined) lines.push(`Mean: ${formatValue(stats.mean)}`);\n if (stats.area !== undefined) lines.push(`Area: ${formatValue(stats.area)}`);\n\n for (const line of lines) {\n maxWidth = Math.max(maxWidth, ctx.measureText(line).width + 10);\n }\n \n contentHeight = lines.length * theme.contentFontSize * theme.lineHeight;\n\n const headerHeight = theme.titleFontSize * theme.lineHeight + theme.headerGap;\n \n this.cachedMeasurement = {\n width: Math.max(maxWidth, 140),\n height: headerHeight + contentHeight + 10,\n padding: theme.padding\n };\n this.cachedKey = cacheKey;\n\n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: RangeTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { x, y } = position;\n const { padding } = theme;\n const stats = data.statistics;\n \n let currentY = y + padding.top;\n const contentX = x + padding.left;\n\n ctx.save();\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n\n // Title\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n ctx.fillText('Range Statistics', contentX, currentY);\n \n currentY += theme.titleFontSize * theme.lineHeight + 2;\n\n // Header Separator\n if (theme.showHeaderSeparator) {\n ctx.strokeStyle = theme.separatorColor;\n ctx.globalAlpha = 0.4;\n ctx.beginPath();\n ctx.moveTo(contentX, currentY + theme.headerGap / 2);\n ctx.lineTo(contentX + measurement.width, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1.0;\n }\n\n currentY += theme.headerGap + 2;\n\n // Content\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n const labelW = 60;\n\n const renderLine = (label: string, value: string | number) => {\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText(label, contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(String(value), contentX + labelW, currentY);\n currentY += theme.contentFontSize * theme.lineHeight;\n };\n\n renderLine('Points:', stats.count);\n if (stats.min !== undefined) renderLine('Min:', formatValue(stats.min));\n if (stats.max !== undefined) renderLine('Max:', formatValue(stats.max));\n if (stats.mean !== undefined) renderLine('Mean:', formatValue(stats.mean));\n if (stats.stdDev !== undefined) renderLine('StdDev:', formatValue(stats.stdDev));\n if (stats.area !== undefined) renderLine('Area:', formatValue(stats.area));\n \n if (stats.peakX !== undefined) {\n currentY += 4;\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.font = `italic ${theme.contentFontSize - 1}px ${theme.fontFamily}`;\n ctx.fillText(`Peak: ${formatValue(stats.peakY ?? 0)} at X=${formatValue(stats.peakX)}`, contentX, currentY);\n }\n\n ctx.restore();\n }\n}\n\nexport const rangeTooltipTemplate = new RangeTooltipTemplate();\n","/**\n * Tooltip Templates - Barrel Export\n * \n * All available tooltip templates for different use cases.\n * \n * @module tooltip/templates\n */\n\n// Default template - Clean data point display\nexport { DefaultTooltipTemplate, defaultTooltipTemplate } from './DefaultTemplate';\n\n// Minimal template - Ultra-compact values\nexport { MinimalTooltipTemplate, minimalTooltipTemplate } from './MinimalTemplate';\n\n// Crosshair template - Multi-series at X position\nexport { CrosshairTooltipTemplate, crosshairTooltipTemplate } from './CrosshairTemplate';\n\n// Heatmap template - Z values with color preview\nexport { HeatmapTooltipTemplate, heatmapTooltipTemplate } from './HeatmapTemplate';\n\n// Scientific template - Full precision with notation\nexport { ScientificTooltipTemplate, scientificTooltipTemplate } from './ScientificTemplate';\n\n// Annotation template - Labels and values for markers/lines\nexport { AnnotationTooltipTemplate, annotationTooltipTemplate } from './AnnotationTemplate';\n\n// Range template - Statistics for data selections\nexport { RangeTooltipTemplate, rangeTooltipTemplate } from './RangeTemplate';\n\n// Template registry for easy lookup\nimport type { TooltipTemplate, TooltipData } from '../types';\nimport { defaultTooltipTemplate } from './DefaultTemplate';\nimport { minimalTooltipTemplate } from './MinimalTemplate';\nimport { crosshairTooltipTemplate } from './CrosshairTemplate';\nimport { heatmapTooltipTemplate } from './HeatmapTemplate';\nimport { scientificTooltipTemplate } from './ScientificTemplate';\nimport { annotationTooltipTemplate } from './AnnotationTemplate';\nimport { rangeTooltipTemplate } from './RangeTemplate';\n\n/** All built-in templates */\nexport const BUILTIN_TEMPLATES: TooltipTemplate<TooltipData>[] = [\n defaultTooltipTemplate as TooltipTemplate<TooltipData>,\n minimalTooltipTemplate as TooltipTemplate<TooltipData>,\n crosshairTooltipTemplate as TooltipTemplate<TooltipData>,\n heatmapTooltipTemplate as TooltipTemplate<TooltipData>,\n scientificTooltipTemplate as TooltipTemplate<TooltipData>,\n annotationTooltipTemplate as TooltipTemplate<TooltipData>,\n rangeTooltipTemplate as TooltipTemplate<TooltipData>\n];\n\n/** Template ID type */\nexport type BuiltinTemplateId = 'default' | 'minimal' | 'crosshair' | 'heatmap' | 'scientific' | 'annotation' | 'range';\n\n/**\n * Get a built-in template by ID\n */\nexport function getBuiltinTemplate(id: BuiltinTemplateId | string): TooltipTemplate<TooltipData> | undefined {\n return BUILTIN_TEMPLATES.find(t => t.id === id);\n}\n\n/**\n * Get template for a tooltip type\n */\nexport function getDefaultTemplateForType(type: string): TooltipTemplate<TooltipData> {\n switch (type) {\n case 'datapoint':\n return defaultTooltipTemplate as TooltipTemplate<TooltipData>;\n case 'crosshair':\n return crosshairTooltipTemplate as TooltipTemplate<TooltipData>;\n case 'heatmap':\n return heatmapTooltipTemplate as TooltipTemplate<TooltipData>;\n case 'annotation':\n return annotationTooltipTemplate as TooltipTemplate<TooltipData>;\n case 'range':\n return rangeTooltipTemplate as TooltipTemplate<TooltipData>;\n default:\n return defaultTooltipTemplate as TooltipTemplate<TooltipData>;\n }\n}\n","/**\n * TooltipManager - Coordinates the tooltip system\n *\n * This is the main entry point for the tooltip system, integrating:\n * - Template management\n * - Theme management\n * - Hit-testing for data points\n * - Tooltip positioning and rendering\n * - Event handling\n *\n * @module tooltip/TooltipManager\n */\n\nimport type { PlotArea, Bounds, AxisOptions } from \"../../../types\";\nimport type { Scale } from \"../../../scales\";\nimport type { Series } from \"../../../core/Series\";\nimport type { TooltipAxisFormat } from \"../../../core/format/axisFormat\";\nimport type {\n TooltipData,\n DataPointTooltip,\n CrosshairTooltip,\n TooltipOptions,\n TooltipTheme,\n TooltipTemplate,\n TooltipPosition,\n ShowTooltipOptions,\n TooltipEventMap,\n} from \"./types\";\nimport { EventEmitter } from \"../../../core/EventEmitter\";\nimport { TooltipPositioner } from \"./TooltipPositioner\";\nimport { TooltipRenderer } from \"./TooltipRenderer\";\nimport {\n DEFAULT_TOOLTIP_THEME,\n getTooltipThemeForChartTheme,\n createTooltipTheme,\n} from \"./themes\";\nimport {\n defaultTooltipTemplate,\n minimalTooltipTemplate,\n crosshairTooltipTemplate,\n heatmapTooltipTemplate,\n scientificTooltipTemplate,\n annotationTooltipTemplate,\n rangeTooltipTemplate,\n getBuiltinTemplate,\n getDefaultTemplateForType,\n} from \"./templates\";\nimport type { ChartTheme } from \"../../../theme\";\n\n// ============================================\n// Types for TooltipManager\n// ============================================\n\nexport interface TooltipManagerConfig {\n /** Canvas 2D context for rendering */\n overlayCtx: CanvasRenderingContext2D;\n /** Chart theme (for auto-selecting tooltip theme) */\n chartTheme: ChartTheme;\n /** Function to get current plot area */\n getPlotArea: () => PlotArea;\n /** Function to get all series */\n getSeries: () => Series[];\n /** Function to convert pixel X to data X */\n pixelToDataX: (px: number) => number;\n /** Function to convert pixel Y to data Y */\n pixelToDataY: (py: number) => number;\n /** Function to get X scale */\n getXScale: () => Scale;\n /** Function to get Y scales */\n getYScales: () => Map<string, Scale>;\n /** Function to get view bounds */\n getViewBounds: () => Bounds;\n /** Function to get X axis options */\n getXAxisOptions?: () => AxisOptions;\n /** Function to get Y axis options for a series axis id */\n getYAxisOptions?: (axisId?: string) => AxisOptions | undefined;\n /** Initial options */\n options?: TooltipOptions;\n}\n\ninterface ActiveTooltip {\n id: string;\n data: TooltipData;\n position: TooltipPosition;\n template: TooltipTemplate<TooltipData>;\n}\n\n/** Internal fully-populated options type */\ninterface FullTooltipOptions {\n enabled: boolean;\n showDelay: number;\n hideDelay: number;\n followCursor: boolean;\n offset: { x: number; y: number };\n dataPoint: {\n enabled: boolean;\n templateId: string;\n snapToPoint: boolean;\n hitRadius: number;\n };\n crosshair: {\n enabled: boolean;\n templateId: string;\n interpolate: boolean;\n visibleSeriesOnly: boolean;\n };\n range: {\n enabled: boolean;\n templateId: string;\n calculateStats: boolean;\n };\n annotation: {\n enabled: boolean;\n templateId: string;\n };\n heatmap: {\n enabled: boolean;\n templateId: string;\n showColorInfo: boolean;\n };\n positioning: \"auto\" | \"fixed\" | \"follow\";\n preferredPosition: \"top\" | \"bottom\" | \"left\" | \"right\" | \"auto\";\n constrainToPlotArea: boolean;\n constrainToContainer: boolean;\n autoFlip: boolean;\n theme?: string | Partial<TooltipTheme>;\n}\n\n// ============================================\n// TooltipManager Implementation\n// ============================================\n\nexport class TooltipManager {\n private ctx: CanvasRenderingContext2D;\n private getPlotArea: () => PlotArea;\n private getSeries: () => Series[];\n private pixelToDataX: (px: number) => number;\n private pixelToDataY: (py: number) => number;\n private getXScale: () => Scale;\n private getYScales: () => Map<string, Scale>;\n private getViewBounds: () => Bounds;\n private getXAxisOptions?: () => AxisOptions;\n private getYAxisOptions?: (axisId?: string) => AxisOptions | undefined;\n\n private options: FullTooltipOptions;\n private theme: TooltipTheme;\n private positioner: TooltipPositioner;\n private renderer: TooltipRenderer;\n private templates: Map<string, TooltipTemplate<TooltipData>> = new Map();\n private events = new EventEmitter<TooltipEventMap>();\n\n private activeTooltips: Map<string, ActiveTooltip> = new Map();\n private tooltipIdCounter = 0;\n private showTimeoutId: number | null = null;\n private hideTimeoutId: number | null = null;\n\n private lastCursorX: number | null = null;\n private lastCursorY: number | null = null;\n private hoveredSeriesId: string | null = null;\n private hoveredDataIndex: number | null = null;\n private cachedNearestResult: DataPointTooltip | null = null;\n\n // Large dataset optimizations\n private snapMode: \"nearest\" | \"x-only\" | \"auto\" = \"auto\";\n private largeDatasetThreshold = 50000;\n private lastKnownDataSize = 0;\n // Hysteresis factor: new point must be this much closer to switch (2 = 2x closer)\n private hysteresisRatio = 2.0;\n // Suspended state - used during drag operations to hide tooltip\n private suspended = false;\n\n constructor(config: TooltipManagerConfig) {\n this.ctx = config.overlayCtx;\n this.getPlotArea = config.getPlotArea;\n this.getSeries = config.getSeries;\n this.pixelToDataX = config.pixelToDataX;\n this.pixelToDataY = config.pixelToDataY;\n this.getXScale = config.getXScale;\n this.getYScales = config.getYScales;\n this.getViewBounds = config.getViewBounds;\n this.getXAxisOptions = config.getXAxisOptions;\n this.getYAxisOptions = config.getYAxisOptions;\n\n // Default options\n this.options = {\n enabled: true,\n showDelay: 50,\n hideDelay: 100,\n followCursor: false,\n offset: { x: 12, y: 12 },\n dataPoint: {\n enabled: true,\n templateId: \"default\",\n snapToPoint: true,\n hitRadius: 20,\n },\n crosshair: {\n enabled: false,\n templateId: \"crosshair\",\n interpolate: true,\n visibleSeriesOnly: true,\n },\n range: {\n enabled: false,\n templateId: \"default\",\n calculateStats: true,\n },\n annotation: {\n enabled: true,\n templateId: \"default\",\n },\n heatmap: {\n enabled: true,\n templateId: \"heatmap\",\n showColorInfo: true,\n },\n positioning: \"auto\",\n preferredPosition: \"auto\",\n constrainToPlotArea: true,\n constrainToContainer: true,\n autoFlip: true,\n };\n\n // Initialize theme first (needed for positioner)\n this.theme = config.options?.theme\n ? typeof config.options.theme === \"string\"\n ? getTooltipThemeForChartTheme(config.options.theme)\n : createTooltipTheme(DEFAULT_TOOLTIP_THEME, config.options.theme)\n : getTooltipThemeForChartTheme(config.chartTheme.name);\n\n // Initialize components before applying user options\n this.positioner = new TooltipPositioner({\n offset: this.options.offset,\n preferredPosition: this.options.preferredPosition,\n constrainToPlotArea: this.options.constrainToPlotArea,\n constrainToContainer: this.options.constrainToContainer,\n autoFlip: this.options.autoFlip,\n showArrow: this.theme.showArrow,\n arrowSize: this.theme.arrowSize,\n });\n\n this.renderer = new TooltipRenderer(this.ctx, this.theme);\n\n // Register built-in templates\n this.registerBuiltinTemplates();\n\n // Apply user options after components are initialized\n if (config.options) {\n this.configure(config.options);\n }\n }\n\n /**\n * Register built-in templates\n */\n private registerBuiltinTemplates(): void {\n this.templates.set(\n \"default\",\n defaultTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"minimal\",\n minimalTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"crosshair\",\n crosshairTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"heatmap\",\n heatmapTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"scientific\",\n scientificTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"annotation\",\n annotationTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"range\",\n rangeTooltipTemplate as TooltipTemplate<TooltipData>\n );\n }\n\n /**\n * Configure tooltip options\n */\n configure(options: TooltipOptions): void {\n if (options.enabled !== undefined) this.options.enabled = options.enabled;\n if (options.showDelay !== undefined)\n this.options.showDelay = options.showDelay;\n if (options.hideDelay !== undefined)\n this.options.hideDelay = options.hideDelay;\n if (options.followCursor !== undefined)\n this.options.followCursor = options.followCursor;\n if (options.offset)\n this.options.offset = { ...this.options.offset, ...options.offset };\n\n if (options.dataPoint) {\n this.options.dataPoint = {\n ...this.options.dataPoint,\n ...options.dataPoint,\n };\n }\n if (options.crosshair) {\n this.options.crosshair = {\n ...this.options.crosshair,\n ...options.crosshair,\n };\n }\n if (options.heatmap) {\n this.options.heatmap = { ...this.options.heatmap, ...options.heatmap };\n }\n\n if (options.preferredPosition)\n this.options.preferredPosition = options.preferredPosition;\n if (options.constrainToPlotArea !== undefined)\n this.options.constrainToPlotArea = options.constrainToPlotArea;\n if (options.constrainToContainer !== undefined)\n this.options.constrainToContainer = options.constrainToContainer;\n if (options.autoFlip !== undefined)\n this.options.autoFlip = options.autoFlip;\n\n // Large dataset optimization options\n if (options.snapMode !== undefined) {\n this.snapMode = options.snapMode;\n }\n if (options.largeDatasetThreshold !== undefined) {\n this.largeDatasetThreshold = Math.max(\n 1000,\n options.largeDatasetThreshold\n );\n }\n\n // Update positioner\n this.positioner.configure({\n offset: this.options.offset,\n preferredPosition: this.options.preferredPosition,\n constrainToPlotArea: this.options.constrainToPlotArea,\n constrainToContainer: this.options.constrainToContainer,\n autoFlip: this.options.autoFlip,\n });\n }\n\n /**\n * Get current options\n */\n getOptions(): TooltipOptions {\n return { ...this.options };\n }\n\n /**\n * Enable/disable tooltips\n */\n setEnabled(enabled: boolean): void {\n this.options.enabled = enabled;\n if (!enabled) {\n this.hideAll();\n }\n }\n\n /**\n * Check if tooltips are enabled\n */\n isEnabled(): boolean {\n return this.options.enabled;\n }\n\n /**\n * Suspend tooltip display (used during drag operations)\n * When suspended, tooltips are immediately hidden and cursor movements are ignored\n */\n setSuspended(suspended: boolean): void {\n this.suspended = suspended;\n if (suspended) {\n this.hideAll();\n }\n }\n\n /**\n * Check if tooltips are suspended\n */\n isSuspended(): boolean {\n return this.suspended;\n }\n\n /**\n * Set tooltip theme\n */\n setTheme(theme: TooltipTheme | string): void {\n this.theme =\n typeof theme === \"string\" ? getTooltipThemeForChartTheme(theme) : theme;\n this.renderer.setTheme(this.theme);\n this.positioner.configure({\n showArrow: this.theme.showArrow,\n arrowSize: this.theme.arrowSize,\n });\n }\n\n /**\n * Update theme based on chart theme\n */\n updateChartTheme(chartTheme: ChartTheme): void {\n if (!this.options.theme) {\n // Only auto-update if user hasn't set a custom theme\n this.theme = getTooltipThemeForChartTheme(chartTheme.name);\n this.renderer.setTheme(this.theme);\n }\n }\n\n /**\n * Get current theme\n */\n getTheme(): TooltipTheme {\n return this.theme;\n }\n\n /**\n * Register a custom template\n */\n registerTemplate<T extends TooltipData>(template: TooltipTemplate<T>): void {\n this.templates.set(template.id, template as TooltipTemplate<TooltipData>);\n }\n\n /**\n * Get a template by ID\n */\n getTemplate(id: string): TooltipTemplate<TooltipData> | undefined {\n return this.templates.get(id) || getBuiltinTemplate(id);\n }\n\n /**\n * Handle cursor movement - main entry point for hover detection\n * Optimized with hysteresis to prevent jumping between nearby points\n */\n handleCursorMove(pixelX: number, pixelY: number): void {\n if (!this.options.enabled || this.suspended) return;\n\n this.lastCursorX = pixelX;\n this.lastCursorY = pixelY;\n\n const plotArea = this.getPlotArea();\n\n // Check if cursor is in plot area (fast path)\n const inPlotArea =\n pixelX >= plotArea.x &&\n pixelX <= plotArea.x + plotArea.width &&\n pixelY >= plotArea.y &&\n pixelY <= plotArea.y + plotArea.height;\n\n if (!inPlotArea) {\n this.cachedNearestResult = null;\n this.scheduleHide();\n return;\n }\n\n // Update positioner with current bounds\n this.positioner.setContainerSize(\n this.ctx.canvas.width / (window.devicePixelRatio || 1),\n this.ctx.canvas.height / (window.devicePixelRatio || 1)\n );\n this.positioner.setPlotArea(plotArea);\n\n // Track data size for auto mode\n this.lastKnownDataSize = this.getTotalDataPoints();\n\n // Find and show tooltip with hysteresis\n this.performTooltipUpdateWithHysteresis(pixelX, pixelY);\n }\n\n /**\n * Handle cursor leave\n */\n handleCursorLeave(): void {\n this.lastCursorX = null;\n this.lastCursorY = null;\n this.cachedNearestResult = null;\n this.scheduleHide();\n }\n\n /**\n * Get total number of data points across all visible series\n */\n private getTotalDataPoints(): number {\n let total = 0;\n const series = this.getSeries();\n for (const s of series) {\n if (!s.isVisible()) continue;\n const data = s.getData();\n if (data.x) total += data.x.length;\n }\n return total;\n }\n\n /**\n * Determine the effective snap mode based on configuration and data size\n */\n private getEffectiveSnapMode(): \"nearest\" | \"x-only\" {\n if (this.snapMode === \"x-only\") return \"x-only\";\n if (this.snapMode === \"nearest\") return \"nearest\";\n\n // Auto mode - use x-only for large datasets\n return this.lastKnownDataSize > this.largeDatasetThreshold\n ? \"x-only\"\n : \"nearest\";\n }\n\n /**\n * Perform tooltip update with hysteresis to prevent jumping.\n * The tooltip \"sticks\" to the current point unless the cursor is\n * significantly closer to a new point.\n */\n private performTooltipUpdateWithHysteresis(\n pixelX: number,\n pixelY: number\n ): void {\n // Try to find a data point\n if (!this.options.dataPoint?.enabled) {\n this.performFallbackTooltipUpdate(pixelX, pixelY);\n return;\n }\n\n const effectiveMode = this.getEffectiveSnapMode();\n const newResult =\n effectiveMode === \"x-only\"\n ? this.findDataPointByXOnly(pixelX)\n : this.findNearestDataPointOptimized(pixelX, pixelY);\n\n if (!newResult) {\n this.performFallbackTooltipUpdate(pixelX, pixelY);\n return;\n }\n\n // Hysteresis: If we already have a point, only switch if new point is MUCH closer\n if (this.cachedNearestResult && this.hoveredSeriesId !== null) {\n const currentPoint = this.cachedNearestResult;\n\n // Calculate distances to current and new points\n const currentDx = currentPoint.pixelX - pixelX;\n const currentDy = currentPoint.pixelY - pixelY;\n const currentDistSq = currentDx * currentDx + currentDy * currentDy;\n\n const newDx = newResult.pixelX - pixelX;\n const newDy = newResult.pixelY - pixelY;\n const newDistSq = newDx * newDx + newDy * newDy;\n\n // Only switch to new point if it's significantly closer\n if (newDistSq * this.hysteresisRatio >= currentDistSq) {\n // Stay with current point - just update position if needed\n this.updateTooltipPosition(this.cachedNearestResult);\n return;\n }\n }\n\n // Switch to new point\n this.cachedNearestResult = newResult;\n this.scheduleShow(newResult);\n }\n\n /**\n * Handle heatmap and crosshair tooltip types (fallback)\n */\n private performFallbackTooltipUpdate(pixelX: number, pixelY: number): void {\n // Try heatmap\n if (this.options.heatmap?.enabled) {\n const heatmapResult = this.findHeatmapCell(pixelX, pixelY);\n if (heatmapResult) {\n this.scheduleShow(heatmapResult);\n return;\n }\n }\n\n // Crosshair mode\n if (this.options.crosshair?.enabled) {\n const crosshairData = this.buildCrosshairTooltip(pixelX, pixelY);\n if (crosshairData) {\n this.scheduleShow(crosshairData);\n return;\n }\n }\n\n // No hit - hide tooltip\n this.cachedNearestResult = null;\n this.scheduleHide();\n }\n\n private buildAxisFormat(yAxisId?: string): TooltipAxisFormat | undefined {\n const bounds = this.getViewBounds();\n const xSpan = bounds.xMax - bounds.xMin;\n const x = this.getXAxisOptions?.();\n const y = this.getYAxisOptions?.(yAxisId);\n\n if (!x && !y && !Number.isFinite(xSpan)) {\n return undefined;\n }\n\n return {\n x,\n y,\n xSpan: Number.isFinite(xSpan) ? xSpan : undefined,\n };\n }\n\n /**\n * Find data point by X coordinate only (O(log n) - fastest method)\n * Best for very large datasets where precision is less important than speed\n */\n private findDataPointByXOnly(pixelX: number): DataPointTooltip | null {\n const series = this.getSeries().filter(\n (s) => s.isVisible() && s.getType() !== \"heatmap\"\n );\n if (series.length === 0) return null;\n\n const xScale = this.getXScale();\n const yScales = this.getYScales();\n const cursorDataX = this.pixelToDataX(pixelX);\n\n let bestResult: DataPointTooltip | null = null;\n let bestXDistance = Infinity;\n\n for (const s of series) {\n const data = s.getData();\n if (!data.x || data.x.length === 0) continue;\n\n const yScale =\n yScales.get(s.getYAxisId?.() || \"default\") ||\n yScales.values().next().value;\n if (!yScale) continue;\n\n // Pure binary search for closest X\n const idx = this.binarySearchClosest(data.x, cursorDataX);\n const xDistance = Math.abs(data.x[idx] - cursorDataX);\n\n if (xDistance < bestXDistance) {\n bestXDistance = xDistance;\n const style = s.getStyle();\n const px = xScale.transform(data.x[idx]);\n const py = yScale.transform(data.y[idx]);\n\n bestResult = {\n type: \"datapoint\",\n seriesId: s.getId(),\n seriesName: s.getId(),\n seriesColor: style.color || \"#ff0055\",\n dataIndex: idx,\n dataX: data.x[idx],\n dataY: data.y[idx],\n pixelX: px,\n pixelY: py,\n cycle: (s as any).getCycle?.(),\n axisFormat: this.buildAxisFormat(s.getYAxisId?.()),\n };\n\n const yError = s.getYError(idx);\n if (yError) bestResult.yError = yError;\n }\n }\n\n return bestResult;\n }\n\n /**\n * Optimized nearest data point finder\n */\n private findNearestDataPointOptimized(\n pixelX: number,\n pixelY: number\n ): DataPointTooltip | null {\n const series = this.getSeries().filter((s) => s.isVisible());\n const hitRadius = this.options.dataPoint?.hitRadius ?? 20;\n const xScale = this.getXScale();\n const yScales = this.getYScales();\n\n let nearestDistanceSq = hitRadius * hitRadius;\n let nearestResult: DataPointTooltip | null = null;\n\n const cursorDataX = this.pixelToDataX(pixelX);\n\n for (const s of series) {\n if (s.getType() === \"heatmap\") continue;\n\n const data = s.getData();\n const yScale =\n yScales.get(s.getYAxisId?.() || \"default\") ||\n yScales.values().next().value;\n\n if (!yScale || !data.x || data.x.length === 0) continue;\n\n const closestIdx = this.binarySearchClosest(data.x, cursorDataX);\n\n // Adaptive search range\n const dataLength = data.x.length;\n const searchRadius = dataLength > 100000 ? 2 : dataLength > 10000 ? 3 : 5;\n const checkStart = Math.max(0, closestIdx - searchRadius);\n const checkEnd = Math.min(dataLength, closestIdx + searchRadius + 1);\n\n for (let i = checkStart; i < checkEnd; i++) {\n const px = xScale.transform(data.x[i]);\n const py = yScale.transform(data.y[i]);\n\n const dx = px - pixelX;\n const dy = py - pixelY;\n const distSq = dx * dx + dy * dy;\n\n if (distSq < nearestDistanceSq) {\n nearestDistanceSq = distSq;\n const style = s.getStyle();\n\n nearestResult = {\n type: \"datapoint\",\n seriesId: s.getId(),\n seriesName: s.getId(),\n seriesColor: style.color || \"#ff0055\",\n dataIndex: i,\n dataX: data.x[i],\n dataY: data.y[i],\n pixelX: px,\n pixelY: py,\n cycle: (s as any).getCycle?.(),\n axisFormat: this.buildAxisFormat(s.getYAxisId?.()),\n };\n\n const yError = s.getYError(i);\n if (yError) nearestResult.yError = yError;\n }\n }\n }\n\n return nearestResult;\n }\n\n /**\n * Find heatmap cell under cursor\n */\n private findHeatmapCell(\n pixelX: number,\n pixelY: number\n ): import(\"./types\").HeatmapTooltip | null {\n const series = this.getSeries().filter(\n (s) => s.isVisible() && s.getType() === \"heatmap\"\n );\n if (series.length === 0) return null;\n\n const xScale = this.getXScale();\n const yScales = this.getYScales();\n const dataX = this.pixelToDataX(pixelX);\n const dataY = this.pixelToDataY(pixelY);\n\n for (const s of series) {\n const data = s.getHeatmapData();\n if (!data || !data.xValues || !data.yValues || !data.zValues) continue;\n\n const colIdx = this.binarySearchClosest(data.xValues as any, dataX);\n const rowIdx = this.binarySearchClosest(data.yValues as any, dataY);\n\n const xValue = data.xValues[colIdx];\n const yValue = data.yValues[rowIdx];\n\n const yScale =\n yScales.get(s.getYAxisId?.() || \"default\") ||\n yScales.values().next().value;\n if (!yScale) continue;\n\n const px = xScale.transform(xValue);\n const py = yScale.transform(yValue);\n\n const zValue = data.zValues[rowIdx * data.xValues.length + colIdx];\n const style = s.getHeatmapStyle?.() || {};\n\n return {\n type: \"heatmap\",\n seriesId: s.getId(),\n seriesName: s.getId(),\n xIndex: colIdx,\n yIndex: rowIdx,\n dataX: xValue,\n dataY: yValue,\n zValue,\n pixelX: px,\n pixelY: py,\n colorScale: style.colorScale as any,\n };\n }\n\n return null;\n }\n\n /**\n * Binary search for closest value\n */\n private binarySearchClosest(\n arr: Float32Array | Float64Array,\n target: number\n ): number {\n let left = 0;\n let right = arr.length - 1;\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n if (arr[mid] < target) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n\n if (\n left > 0 &&\n Math.abs(arr[left - 1] - target) < Math.abs(arr[left] - target)\n ) {\n return left - 1;\n }\n\n return left;\n }\n\n /**\n * Build crosshair tooltip data\n */\n private buildCrosshairTooltip(\n pixelX: number,\n pixelY: number\n ): CrosshairTooltip | null {\n const series = this.getSeries().filter(\n (s) => s.isVisible() && s.getType() !== \"heatmap\"\n );\n if (series.length === 0) return null;\n\n const dataX = this.pixelToDataX(pixelX);\n const yScales = this.getYScales();\n\n const interpolatedValues: CrosshairTooltip[\"interpolatedValues\"] = [];\n\n for (const s of series) {\n const data = s.getData();\n if (!data.x || data.x.length === 0) continue;\n\n const yScale =\n yScales.get(s.getYAxisId?.() || \"default\") ||\n yScales.values().next().value;\n if (!yScale) continue;\n\n const idx = this.binarySearchClosest(data.x, dataX);\n let y: number;\n let isInterpolated = false;\n\n if (idx === 0 || idx >= data.x.length - 1 || data.x[idx] === dataX) {\n y = data.y[idx];\n } else if (this.options.crosshair?.interpolate) {\n const x0 = data.x[idx - 1];\n const x1 = data.x[idx];\n const y0 = data.y[idx - 1];\n const y1 = data.y[idx];\n const t = (dataX - x0) / (x1 - x0);\n y = y0 + t * (y1 - y0);\n isInterpolated = true;\n } else {\n y = data.y[idx];\n }\n\n const style = s.getStyle();\n interpolatedValues.push({\n seriesId: s.getId(),\n seriesName: s.getId(),\n seriesColor: style.color || \"#ff0055\",\n x: dataX,\n y,\n isInterpolated,\n });\n }\n\n if (interpolatedValues.length === 0) return null;\n\n return {\n type: \"crosshair\",\n cursorX: pixelX,\n cursorY: pixelY,\n dataX,\n interpolatedValues,\n axisFormat: this.buildAxisFormat(),\n };\n }\n\n /**\n * Schedule showing a tooltip\n */\n private scheduleShow(data: TooltipData): void {\n this.clearHideTimeout();\n\n // If same data point, just update position\n if (data.type === \"datapoint\") {\n const dp = data as DataPointTooltip;\n if (\n this.hoveredSeriesId === dp.seriesId &&\n this.hoveredDataIndex === dp.dataIndex\n ) {\n this.updateTooltipPosition(data);\n return;\n }\n this.hoveredSeriesId = dp.seriesId;\n this.hoveredDataIndex = dp.dataIndex;\n }\n\n this.clearShowTimeout();\n\n // Use short or no delay when already showing a tooltip\n const effectiveDelay =\n this.activeTooltips.size > 0 ? 0 : this.options.showDelay;\n\n if (effectiveDelay > 0) {\n this.showTimeoutId = window.setTimeout(() => {\n this.showTooltip(data);\n }, effectiveDelay);\n } else {\n this.showTooltip(data);\n }\n }\n\n /**\n * Schedule hiding tooltips\n */\n private scheduleHide(): void {\n this.clearShowTimeout();\n this.hoveredSeriesId = null;\n this.hoveredDataIndex = null;\n\n if (this.options.hideDelay > 0) {\n this.hideTimeoutId = window.setTimeout(() => {\n this.hideAll();\n }, this.options.hideDelay);\n } else {\n this.hideAll();\n }\n }\n\n private clearShowTimeout(): void {\n if (this.showTimeoutId !== null) {\n clearTimeout(this.showTimeoutId);\n this.showTimeoutId = null;\n }\n }\n\n private clearHideTimeout(): void {\n if (this.hideTimeoutId !== null) {\n clearTimeout(this.hideTimeoutId);\n this.hideTimeoutId = null;\n }\n }\n\n /**\n * Show a tooltip with the given data\n */\n private showTooltip(data: TooltipData): void {\n const templateId = this.getTemplateIdForType(data.type);\n const template =\n this.templates.get(templateId) || getDefaultTemplateForType(data.type);\n\n const targetX = (data as any).pixelX ?? this.lastCursorX ?? 0;\n const targetY = (data as any).pixelY ?? this.lastCursorY ?? 0;\n\n const measurement = template.measure(this.ctx, data, this.theme);\n const position = this.positioner.calculatePosition(\n targetX,\n targetY,\n measurement\n );\n\n const tooltipId = \"main\";\n\n this.activeTooltips.set(tooltipId, {\n id: tooltipId,\n data,\n position,\n template,\n });\n }\n\n /**\n * Update tooltip position\n */\n private updateTooltipPosition(data: TooltipData | null): void {\n const tooltip = this.activeTooltips.get(\"main\");\n if (!tooltip) return;\n\n const tooltipData = data || tooltip.data;\n const targetX = (tooltipData as any).pixelX ?? this.lastCursorX ?? 0;\n const targetY = (tooltipData as any).pixelY ?? this.lastCursorY ?? 0;\n\n const measurement = tooltip.template.measure(\n this.ctx,\n tooltipData,\n this.theme\n );\n tooltip.position = this.positioner.calculatePosition(\n targetX,\n targetY,\n measurement\n );\n tooltip.data = tooltipData;\n }\n\n /**\n * Get template ID for a tooltip type\n */\n private getTemplateIdForType(type: string): string {\n switch (type) {\n case \"datapoint\":\n return this.options.dataPoint?.templateId || \"default\";\n case \"crosshair\":\n return this.options.crosshair?.templateId || \"crosshair\";\n case \"heatmap\":\n return this.options.heatmap?.templateId || \"heatmap\";\n default:\n return \"default\";\n }\n }\n\n /**\n * Show a tooltip programmatically\n */\n show(data: TooltipData, options?: ShowTooltipOptions): string {\n const tooltipId = `tooltip-${++this.tooltipIdCounter}`;\n const templateId =\n options?.templateId || this.getTemplateIdForType(data.type);\n const template =\n this.templates.get(templateId) || getDefaultTemplateForType(data.type);\n\n let position: TooltipPosition;\n\n if (options?.position) {\n const measurement = template.measure(this.ctx, data, this.theme);\n position = this.positioner.calculatePosition(\n options.position.x,\n options.position.y,\n measurement\n );\n } else {\n const targetX = (data as any).pixelX ?? 0;\n const targetY = (data as any).pixelY ?? 0;\n const measurement = template.measure(this.ctx, data, this.theme);\n position = this.positioner.calculatePosition(\n targetX,\n targetY,\n measurement\n );\n }\n\n this.activeTooltips.set(tooltipId, {\n id: tooltipId,\n data,\n position,\n template,\n });\n\n if (options?.duration && options.duration > 0) {\n setTimeout(() => this.hide(tooltipId), options.duration);\n }\n\n return tooltipId;\n }\n\n /**\n * Hide a specific tooltip\n */\n hide(tooltipId: string): void {\n this.activeTooltips.delete(tooltipId);\n }\n\n /**\n * Hide all tooltips immediately\n */\n hideAll(): void {\n this.activeTooltips.clear();\n this.hoveredSeriesId = null;\n this.hoveredDataIndex = null;\n }\n\n /**\n * Render all active tooltips\n */\n render(): void {\n if (!this.options.enabled || this.activeTooltips.size === 0) return;\n\n for (const tooltip of this.activeTooltips.values()) {\n this.renderer.render(tooltip.data, tooltip.position, tooltip.template);\n }\n }\n\n /**\n * Check if any tooltip is currently visible\n */\n hasActiveTooltip(): boolean {\n return this.activeTooltips.size > 0;\n }\n\n /**\n * Subscribe to tooltip events\n */\n on<K extends keyof TooltipEventMap>(\n event: K,\n handler: (data: TooltipEventMap[K]) => void\n ): void {\n this.events.on(event, handler);\n }\n\n /**\n * Unsubscribe from tooltip events\n */\n off<K extends keyof TooltipEventMap>(\n event: K,\n handler: (data: TooltipEventMap[K]) => void\n ): void {\n this.events.off(event, handler);\n }\n\n /**\n * Destroy the tooltip manager\n */\n destroy(): void {\n this.clearShowTimeout();\n this.clearHideTimeout();\n this.activeTooltips.clear();\n this.templates.clear();\n this.events.clear();\n }\n}\n\n/**\n * Create a tooltip manager\n */\nexport function createTooltipManager(\n config: TooltipManagerConfig\n): TooltipManager {\n return new TooltipManager(config);\n}\n","/**\n * SciPlot Engine - Interactive Tools Plugin\n * \n * Provides specialized interaction tools:\n * - Delta Tool: Measurement between two points\n * - Peak Tool: Peak detection and area under curve\n * - Enhanced Tooltips: Point and crosshair tooltips\n * \n * @module plugins/tools\n */\n\nimport { DeltaTool } from \"./delta-tool\";\nimport { PeakTool } from \"./peak-tool\";\nimport { TooltipManager } from \"./tooltip\";\nimport type { PluginManifest, ChartPlugin, PluginContext } from \"../types\";\n\nexport interface PluginToolsConfig {\n /** Enable Delta measurement tool */\n enableDeltaTool?: boolean;\n /** Enable Peak detection tool */\n enablePeakTool?: boolean;\n /** Use advanced tooltip manager */\n useEnhancedTooltips?: boolean;\n}\n\nconst manifestTools: PluginManifest = {\n name: \"velo-plot-tools\",\n version: \"1.0.0\",\n description: \"Advanced interaction and measurement tools for velo-plot\",\n provides: [\"interaction\"],\n tags: [\"delta-tool\", \"peak-tool\", \"tooltip\"],\n};\n\n/**\n * SciPlot Tools Plugin\n * \n * Adds specialized tools for scientific data analysis and interaction.\n */\nexport function PluginTools(_config: PluginToolsConfig = {}): ChartPlugin<PluginToolsConfig> {\n let deltaTool: DeltaTool | null = null;\n let peakTool: PeakTool | null = null;\n let tooltipManager: TooltipManager | null = null;\n\n return {\n manifest: manifestTools,\n\n onInit(ctx: PluginContext) {\n\n // Bridge between PluginContext and DeltaTool/PeakTool context\n const toolContext = {\n container: ctx.ui.container,\n getPlotArea: () => ctx.render.plotArea,\n getViewBounds: () => ctx.data.getViewBounds(),\n getYBounds: (id?: string) => ctx.data.getYAxisBounds(id),\n requestRender: () => ctx.requestRender(),\n getSeries: () => {\n // Transform Series objects to the format expected by DeltaTool/PeakTool\n return ctx.data.getAllSeries().map((s: any) => {\n const data = s.getData();\n return {\n id: s.getId(),\n x: data.x,\n y: data.y,\n yAxisId: s.getYAxisId?.() || undefined\n };\n });\n },\n onMeasure: (m: any) => ctx.events.emit('measure', m)\n };\n\n if (_config.enableDeltaTool ?? true) {\n deltaTool = new DeltaTool(toolContext);\n }\n if (_config.enablePeakTool ?? true) {\n peakTool = new PeakTool(toolContext);\n }\n if (_config.useEnhancedTooltips ?? true) {\n // Safely access internal properties for bridge\n const chart = ctx.chart as any;\n \n // Debug logging\n ctx.log.debug(\"TooltipManager init - checking deps:\", {\n hasCtx2d: !!ctx.render.ctx2d,\n hasXScale: !!chart.xScale,\n hasYScales: !!chart.yScales,\n seriesCount: ctx.data.getAllSeries().length\n });\n \n if (!ctx.render.ctx2d) {\n ctx.log.warn(\"TooltipManager: No 2D context available, tooltips disabled\");\n } else {\n tooltipManager = new TooltipManager({\n overlayCtx: ctx.render.ctx2d,\n chartTheme: ctx.ui.theme,\n getPlotArea: () => ctx.render.plotArea,\n getSeries: () => ctx.data.getAllSeries() as any,\n pixelToDataX: (px) => ctx.coords.pixelToDataX(px),\n pixelToDataY: (py) => ctx.coords.pixelToDataY(py),\n getXScale: () => chart.xScale,\n getYScales: () => chart.yScales,\n getViewBounds: () => ctx.data.getViewBounds(),\n getXAxisOptions: () => ctx.chart.getXAxis(),\n getYAxisOptions: (id) => ctx.chart.getYAxis(id || ctx.chart.getPrimaryYAxisId()),\n options: chart.initialOptions?.tooltip,\n });\n }\n }\n },\n\n onRenderOverlay(_ctx) {\n tooltipManager?.render();\n deltaTool?.renderOverlay();\n peakTool?.renderOverlay();\n },\n\n onDestroy(_ctx: PluginContext) {\n deltaTool?.destroy();\n peakTool?.destroy();\n tooltipManager?.destroy();\n deltaTool = null;\n peakTool = null;\n tooltipManager = null;\n },\n\n api: {\n setMode(mode: 'delta' | 'peak' | 'none') {\n deltaTool?.disable();\n peakTool?.disable();\n\n if (mode === 'delta') deltaTool?.enable();\n if (mode === 'peak') peakTool?.enable();\n },\n getDeltaTool: () => deltaTool,\n getPeakTool: () => peakTool,\n getTooltipManager: () => tooltipManager\n }\n };\n}\n\nexport { DeltaTool, PeakTool, TooltipManager };\nexport default PluginTools;\n"],"names":["DeltaTool","context","options","__publicField","seriesList","updatePoint","p","s","ser","plotArea","bounds","yBounds","p1Valid","p2Valid","rect","dpr","e","pixelX","pixelY","nearestPoint","_a","measurement","series","minDistance","xData","yData","len","i","dataX","dataY","px","py","distance","p1","p2","deltaX","deltaY","slope","opts","ctx","cx","cy","hp","point","label","text","metrics","padding","boxWidth","boxHeight","boxX","boxY","x","y","color","pillWidth","pillHeight","m","midX","midY","lines","lineHeight","container","line","statusText","statusColor","w","h","r","val","abs","PeakTool","seriesFilter","seriesIdFilter","idx1","idx2","win","baselinePointsX","baselinePointsY","n","sumX","sumY","sumXY","sumXX","baselineSlope","baselineIntercept","area","integral","peakHeight","peakX","peakY","x_a","y_a","x_b","y_b","dx","avgY","bl_a","bl_b","avgBL","h_a","seriesYBounds","peakYBounds","peakPX","peakPY","baselineAtPeak","basePY","DEFAULT_PADDING","TOOLTIP_DARK_THEME","TOOLTIP_LIGHT_THEME","TOOLTIP_GLASS_THEME","TOOLTIP_MIDNIGHT_THEME","TOOLTIP_ELECTROCHEM_THEME","TOOLTIP_NEON_THEME","TOOLTIP_MINIMAL_THEME","TOOLTIP_THEMES","getTooltipTheme","name","theme","createTooltipTheme","base","overrides","baseTheme","getTooltipThemeForChartTheme","chartThemeName","DEFAULT_TOOLTIP_THEME","DEFAULT_POSITIONER_CONFIG","TooltipPositioner","config","width","height","targetX","targetY","offset","preferredPosition","autoFlip","showArrow","arrowSize","totalWidth","totalHeight","position","arrowPosition","wasFlipped","flippedPosition","flipped","constrained","arrowOffset","idealArrowX","idealArrowY","preferred","spaceTop","spaceBottom","spaceLeft","spaceRight","canFitTop","canFitBottom","canFitRight","canFitLeft","a","b","margin","constrainedX","constrainedY","cursorX","cursorY","TooltipRenderer","data","template","_arrowPosition","gradient","size","topX","bottomX","bottomY","leftY","rightX","rightY","radius","fontSize","fontWeight","align","baseline","value","maxWidth","formatDataPointX","formatTooltipX","formatFallbackNumber","formatDataPointY","formatTooltipY","formatCrosshairX","formatCrosshairY","absVal","formatCompactValue","axis","formatValue","DefaultTooltipTemplate","cacheKey","titleWidth","labelWidth","xValWidth","yValWidth","contentWidth","contentHeight","errorText","cycleText","indicatorWidth","currentX","currentY","indicatorY","separatorWidth","defaultTooltipTemplate","MinimalTooltipTemplate","textWidth","xValue","yValue","xWidth","sepWidth","minimalTooltipTemplate","SPACING","CrosshairTooltipTemplate","seriesHash","nameWidth","valWidth","lineWidth","headerHeight","formatted","contentX","itemX","labelOffset","crosshairTooltipTemplate","HeatmapTooltipTemplate","headerText","valueText","valueWidth","scaleText","xyLabelWidth","dataXWidth","dataYWidth","swatchY","heatmapTooltipTemplate","formatXValue","_b","toScientificUnicode","formatYValue","precision","exp","mantissa","superscripts","expStr","superExp","char","ScientificTooltipTemplate","xVal","yVal","yWidth","footerText","lineCount","extraGap","yText","scientificTooltipTemplate","AnnotationTooltipTemplate","valText","xText","labelW","annotationTooltipTemplate","RangeTooltipTemplate","stats","renderLine","rangeTooltipTemplate","BUILTIN_TEMPLATES","getBuiltinTemplate","id","getDefaultTemplateForType","type","TooltipManager","EventEmitter","enabled","suspended","chartTheme","total","newResult","currentPoint","currentDx","currentDy","currentDistSq","newDx","newDy","heatmapResult","crosshairData","yAxisId","xSpan","xScale","yScales","cursorDataX","bestResult","bestXDistance","yScale","idx","xDistance","style","_c","yError","hitRadius","nearestDistanceSq","nearestResult","closestIdx","dataLength","searchRadius","checkStart","checkEnd","dy","distSq","_d","colIdx","rowIdx","zValue","arr","target","left","right","mid","interpolatedValues","isInterpolated","x0","x1","y0","y1","t","dp","effectiveDelay","templateId","tooltipId","tooltip","tooltipData","event","handler","manifestTools","PluginTools","_config","deltaTool","peakTool","tooltipManager","toolContext","chart","_ctx","mode"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-CWipqOLP.js","sources":["../src/plugins/tools/delta-tool/index.ts","../src/plugins/tools/peak-tool/index.ts","../src/plugins/tools/tooltip/themes.ts","../src/plugins/tools/tooltip/TooltipPositioner.ts","../src/plugins/tools/tooltip/TooltipRenderer.ts","../src/plugins/tools/tooltip/format.ts","../src/plugins/tools/tooltip/templates/DefaultTemplate.ts","../src/plugins/tools/tooltip/templates/MinimalTemplate.ts","../src/plugins/tools/tooltip/templates/CrosshairTemplate.ts","../src/plugins/tools/tooltip/templates/HeatmapTemplate.ts","../src/plugins/tools/tooltip/templates/ScientificTemplate.ts","../src/plugins/tools/tooltip/templates/AnnotationTemplate.ts","../src/plugins/tools/tooltip/templates/RangeTemplate.ts","../src/plugins/tools/tooltip/templates/index.ts","../src/plugins/tools/tooltip/TooltipManager.ts","../src/plugins/tools/index.ts"],"sourcesContent":["/**\n * Sci Plot - Delta Tool Module\n * \n * Provides interactive measurement tool for measuring distances,\n * differences, and slopes between two data points on the chart.\n * \n * Features:\n * - Click to select first point (snaps to nearest data point)\n * - Click to select second point \n * - Highlight points on hover\n * - Show delta measurements between points\n * \n * @module delta-tool\n */\n\nimport type { DeltaMeasurement, Bounds } from '../../../types';\nimport type { AnimationEngine } from '../../../core/animation';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface DeltaToolOptions {\n /** Line color for measurement (default: '#ff6b6b') */\n lineColor?: string;\n /** Line width in pixels (default: 2) */\n lineWidth?: number;\n /** Show labels at measurement points (default: true) */\n showLabels?: boolean;\n /** Label font size (default: 12) */\n labelFontSize?: number;\n /** Label background color (default: 'rgba(0,0,0,0.8)') */\n labelBackground?: string;\n /** Label text color (default: '#ffffff') */\n labelColor?: string;\n /** Show delta values inline (default: true) */\n showDelta?: boolean;\n /** Number precision for values (default: 4) */\n precision?: number;\n /** Show slope value (default: true) */\n showSlope?: boolean;\n /** Show distance value (default: true) */\n showDistance?: boolean;\n /** Custom CSS class for overlay elements */\n className?: string;\n /** Point highlight size when hovering (default: 10) */\n highlightSize?: number;\n /** Point highlight color (default: '#00f2ff') */\n highlightColor?: string;\n /** Snap radius in pixels for detecting nearby points (default: 20) */\n snapRadius?: number;\n}\n\n/** Data point with series information */\nexport interface DataPoint {\n x: number;\n y: number;\n seriesId: string;\n yAxisId?: string;\n index: number;\n pixelX: number;\n pixelY: number;\n}\n\nexport interface DeltaToolState {\n /** Whether the tool is enabled */\n enabled: boolean;\n /** Selection state: 'idle' | 'waitingSecond' | 'complete' */\n selectionState: 'idle' | 'waitingSecond' | 'complete';\n /** First selected point */\n point1: DataPoint | null;\n /** Second selected point */\n point2: DataPoint | null;\n /** Currently hovered point (for highlighting) */\n hoveredPoint: DataPoint | null;\n /** Last completed measurement */\n lastMeasurement: DeltaMeasurement | null;\n}\n\nexport interface SeriesData {\n id: string;\n x: Float32Array | Float64Array | number[];\n y: Float32Array | Float64Array | number[];\n yAxisId?: string;\n}\n\nexport interface DeltaToolContext {\n container: HTMLElement;\n getPlotArea: () => { x: number; y: number; width: number; height: number };\n getViewBounds: () => Bounds;\n getYBounds?: (yAxisId?: string) => { yMin: number; yMax: number };\n requestRender: () => void;\n getSeries?: () => SeriesData[];\n onMeasure?: (measurement: DeltaMeasurement) => void;\n animationEngine?: AnimationEngine;\n}\n\n// ============================================\n// Delta Tool Implementation\n// ============================================\n\nexport class DeltaTool {\n private ctx: DeltaToolContext;\n private options: Required<DeltaToolOptions>;\n private state: DeltaToolState = {\n enabled: false,\n selectionState: 'idle',\n point1: null,\n point2: null,\n hoveredPoint: null,\n lastMeasurement: null,\n };\n\n private overlayCanvas: HTMLCanvasElement | null = null;\n private overlayCtx: CanvasRenderingContext2D | null = null;\n\n // Label dragging\n private labelOffset: { x: number; y: number } = { x: 15, y: 0 };\n private isDraggingLabel = false;\n private labelBounds: { x: number; y: number; width: number; height: number } | null = null;\n private dragStart: { x: number; y: number } = { x: 0, y: 0 };\n private crosshairPosition: { x: number; y: number } | null = null;\n\n // Bound handlers\n private boundMouseMove: (e: MouseEvent) => void;\n private boundClick: (e: MouseEvent) => void;\n private boundKeyDown: (e: KeyboardEvent) => void;\n private boundMouseDown: (e: MouseEvent) => void;\n private boundMouseUp: (e: MouseEvent) => void;\n private boundResize: () => void;\n\n constructor(context: DeltaToolContext, options?: DeltaToolOptions) {\n this.ctx = context;\n this.options = {\n lineColor: '#ff6b6b',\n lineWidth: 2,\n showLabels: true,\n labelFontSize: 12,\n labelBackground: 'rgba(0, 0, 0, 0.85)',\n labelColor: '#ffffff',\n showDelta: true,\n precision: 4,\n showSlope: true,\n showDistance: true,\n className: 'velo-plot-delta-tool',\n highlightSize: 12,\n highlightColor: '#00f2ff',\n snapRadius: 30,\n ...options,\n };\n\n this.boundMouseMove = this.handleMouseMove.bind(this);\n this.boundClick = this.handleClick.bind(this);\n this.boundKeyDown = this.handleKeyDown.bind(this);\n this.boundMouseDown = this.handleLabelMouseDown.bind(this);\n this.boundMouseUp = this.handleLabelMouseUp.bind(this);\n this.boundResize = this.resizeOverlay.bind(this);\n }\n\n /**\n * Enable the delta measurement tool\n */\n enable(): void {\n if (this.state.enabled) return;\n\n this.state.enabled = true;\n this.state.selectionState = 'idle';\n this.createOverlay();\n this.attachListeners();\n this.ctx.container.style.cursor = 'crosshair';\n \n }\n\n /**\n * Disable the delta measurement tool\n */\n disable(): void {\n if (!this.state.enabled) return;\n\n this.state.enabled = false;\n this.state.selectionState = 'idle';\n this.state.point1 = null;\n this.state.point2 = null;\n this.state.hoveredPoint = null;\n\n this.detachListeners();\n this.destroyOverlay();\n this.ctx.container.style.cursor = '';\n }\n\n /**\n * Toggle the tool on/off\n */\n toggle(): void {\n if (this.state.enabled) {\n this.disable();\n } else {\n this.enable();\n }\n }\n\n /**\n * Check if tool is enabled\n */\n isEnabled(): boolean {\n return this.state.enabled;\n }\n\n /**\n * Get the current state\n */\n getState(): DeltaToolState {\n return { ...this.state };\n }\n\n /**\n * Get the last completed measurement\n */\n getMeasurement(): DeltaMeasurement | null {\n return this.state.lastMeasurement;\n }\n\n /**\n * Clear the current measurement\n */\n clear(): void {\n this.state.point1 = null;\n this.state.point2 = null;\n this.state.selectionState = 'idle';\n this.state.lastMeasurement = null;\n this.labelBounds = null;\n this.labelOffset = { x: 15, y: 0 };\n this.renderOverlay();\n }\n\n /**\n * Destroy the tool and cleanup\n */\n destroy(): void {\n this.disable();\n this.state.lastMeasurement = null;\n }\n\n /**\n * Recalculate measurements (useful if data changes)\n */\n public recalculate(): void {\n if (!this.state.point1 || !this.state.point2) return;\n\n // Refresh data points from series\n const seriesList = this.ctx.getSeries ? this.ctx.getSeries() : [];\n\n const updatePoint = (p: DataPoint) => {\n const s = seriesList.find(ser => ser.id === p.seriesId);\n if (s && p.index < s.x.length) {\n p.x = s.x[p.index];\n p.y = s.y[p.index];\n p.yAxisId = s.yAxisId;\n\n // Update pixel coordinates\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(s.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n return true;\n }\n return false;\n };\n\n const p1Valid = updatePoint(this.state.point1);\n const p2Valid = updatePoint(this.state.point2);\n\n if (p1Valid && p2Valid) {\n this.state.lastMeasurement = this.calculateMeasurement();\n if (this.ctx.onMeasure) {\n this.ctx.onMeasure(this.state.lastMeasurement);\n }\n } else {\n this.clear();\n }\n\n this.renderOverlay();\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private createOverlay(): void {\n if (this.overlayCanvas) return;\n\n this.overlayCanvas = document.createElement('canvas');\n this.overlayCanvas.className = this.options.className;\n this.overlayCanvas.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 1000;\n `;\n\n this.resizeOverlay();\n this.overlayCtx = this.overlayCanvas.getContext('2d');\n this.ctx.container.appendChild(this.overlayCanvas);\n }\n\n private resizeOverlay(): void {\n if (!this.overlayCanvas) return;\n const rect = this.ctx.container.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n this.overlayCanvas.width = rect.width * dpr;\n this.overlayCanvas.height = rect.height * dpr;\n if (this.overlayCtx) {\n this.overlayCtx.setTransform(1, 0, 0, 1, 0, 0);\n this.overlayCtx.scale(dpr, dpr);\n }\n }\n\n private destroyOverlay(): void {\n if (this.overlayCanvas && this.overlayCanvas.parentNode) {\n this.overlayCanvas.parentNode.removeChild(this.overlayCanvas);\n }\n this.overlayCanvas = null;\n this.overlayCtx = null;\n }\n\n private attachListeners(): void {\n // Use capture phase to get events before InteractionManager\n this.ctx.container.addEventListener('mousemove', this.boundMouseMove, true);\n this.ctx.container.addEventListener('mousedown', this.boundClick, true);\n this.ctx.container.addEventListener('mousedown', this.boundMouseDown, true);\n this.ctx.container.addEventListener('mouseup', this.boundMouseUp, true);\n window.addEventListener('resize', this.boundResize);\n document.addEventListener('keydown', this.boundKeyDown);\n }\n\n private detachListeners(): void {\n this.ctx.container.removeEventListener('mousemove', this.boundMouseMove, true);\n this.ctx.container.removeEventListener('mousedown', this.boundClick, true);\n this.ctx.container.removeEventListener('mousedown', this.boundMouseDown, true);\n this.ctx.container.removeEventListener('mouseup', this.boundMouseUp, true);\n window.removeEventListener('resize', this.boundResize);\n document.removeEventListener('keydown', this.boundKeyDown);\n }\n\n private handleMouseMove(e: MouseEvent): void {\n if (!this.state.enabled) return;\n\n const rect = this.ctx.container.getBoundingClientRect();\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n // Handle label dragging\n if (this.isDraggingLabel) {\n this.labelOffset.x += pixelX - this.dragStart.x;\n this.labelOffset.y += pixelY - this.dragStart.y;\n this.dragStart = { x: pixelX, y: pixelY };\n this.renderOverlay();\n return;\n }\n\n // Update cursor if over label\n if (this.labelBounds &&\n pixelX >= this.labelBounds.x && pixelX <= this.labelBounds.x + this.labelBounds.width &&\n pixelY >= this.labelBounds.y && pixelY <= this.labelBounds.y + this.labelBounds.height) {\n this.ctx.container.style.cursor = 'move';\n } else {\n this.ctx.container.style.cursor = 'crosshair';\n }\n\n // Check if inside plot area\n if (\n pixelX < plotArea.x ||\n pixelX > plotArea.x + plotArea.width ||\n pixelY < plotArea.y ||\n pixelY > plotArea.y + plotArea.height\n ) {\n this.state.hoveredPoint = null;\n this.crosshairPosition = null;\n this.renderOverlay();\n return;\n }\n\n // Store current mouse position for crosshair\n this.crosshairPosition = { x: pixelX, y: pixelY };\n\n // Find nearest data point\n const nearestPoint = this.findNearestPoint(pixelX, pixelY, plotArea, bounds);\n this.state.hoveredPoint = nearestPoint;\n this.renderOverlay();\n }\n\n private handleLabelMouseDown(e: MouseEvent): void {\n if (!this.state.enabled || !this.labelBounds) return;\n\n const rect = this.ctx.container.getBoundingClientRect();\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n if (pixelX >= this.labelBounds.x && pixelX <= this.labelBounds.x + this.labelBounds.width &&\n pixelY >= this.labelBounds.y && pixelY <= this.labelBounds.y + this.labelBounds.height) {\n this.isDraggingLabel = true;\n this.dragStart = { x: pixelX, y: pixelY };\n e.stopPropagation();\n e.preventDefault();\n }\n }\n\n private handleLabelMouseUp(): void {\n this.isDraggingLabel = false;\n }\n\n private async handleClick(e: MouseEvent): Promise<void> {\n if (!this.state.enabled) return;\n\n // If chart is animating, wait for it to settle to get accurate coordinates\n if (this.ctx.animationEngine?.isAnimating()) {\n await this.ctx.animationEngine.waitForIdle();\n }\n\n // Stop propagation to prevent InteractionManager from handling this\n e.stopPropagation();\n e.preventDefault();\n\n const rect = this.ctx.container.getBoundingClientRect();\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n // Check if inside plot area\n if (\n pixelX < plotArea.x ||\n pixelX > plotArea.x + plotArea.width ||\n pixelY < plotArea.y ||\n pixelY > plotArea.y + plotArea.height\n ) {\n return;\n }\n\n // Find nearest data point\n const nearestPoint = this.findNearestPoint(pixelX, pixelY, plotArea, bounds);\n\n if (!nearestPoint) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n if (this.state.selectionState === 'idle' || this.state.selectionState === 'complete') {\n // Select first point\n this.state.point1 = nearestPoint;\n this.state.point2 = null;\n this.state.selectionState = 'waitingSecond';\n this.state.lastMeasurement = null;\n } else if (this.state.selectionState === 'waitingSecond') {\n // Select second point\n this.state.point2 = nearestPoint;\n this.state.selectionState = 'complete';\n\n // Calculate measurement\n const measurement = this.calculateMeasurement();\n this.state.lastMeasurement = measurement;\n\n if (this.ctx.onMeasure) {\n this.ctx.onMeasure(measurement);\n }\n }\n\n this.renderOverlay();\n }\n\n private handleKeyDown(e: KeyboardEvent): void {\n if (e.key === 'Escape' && this.state.enabled) {\n this.clear();\n }\n }\n\n private findNearestPoint(\n pixelX: number,\n pixelY: number,\n plotArea: { x: number; y: number; width: number; height: number },\n bounds: Bounds\n ): DataPoint | null {\n if (!this.ctx.getSeries) return null;\n\n const series = this.ctx.getSeries();\n let nearestPoint: DataPoint | null = null;\n let minDistance = this.options.snapRadius;\n\n for (const s of series) {\n const xData = s.x;\n const yData = s.y;\n const len = Math.min(xData.length, yData.length);\n\n // Get Y bounds for this series (may be different if using secondary Y axis)\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(s.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n\n for (let i = 0; i < len; i++) {\n const dataX = xData[i];\n const dataY = yData[i];\n\n // Convert data to pixel coordinates\n const px = plotArea.x + ((dataX - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n const py = plotArea.y + (1 - (dataY - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n\n // Skip if outside visible range\n if (px < plotArea.x || px > plotArea.x + plotArea.width) continue;\n if (py < plotArea.y || py > plotArea.y + plotArea.height) continue;\n\n const distance = Math.sqrt((pixelX - px) ** 2 + (pixelY - py) ** 2);\n\n if (distance < minDistance) {\n minDistance = distance;\n nearestPoint = {\n x: dataX,\n y: dataY,\n seriesId: s.id,\n yAxisId: s.yAxisId,\n index: i,\n pixelX: px,\n pixelY: py,\n };\n }\n }\n }\n\n return nearestPoint;\n }\n\n private calculateMeasurement(): DeltaMeasurement {\n const p1 = this.state.point1!;\n const p2 = this.state.point2!;\n\n const deltaX = p2.x - p1.x;\n const deltaY = p2.y - p1.y;\n const slope = deltaX !== 0 ? deltaY / deltaX : Infinity;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n\n return {\n x1: p1.x,\n y1: p1.y,\n x2: p2.x,\n y2: p2.y,\n deltaX,\n deltaY,\n slope,\n distance,\n pixelX1: p1.pixelX,\n pixelY1: p1.pixelY,\n pixelX2: p2.pixelX,\n pixelY2: p2.pixelY,\n };\n }\n\n public renderOverlay(): void {\n if (!this.overlayCtx || !this.overlayCanvas) return;\n\n // Resize if needed\n this.resizeOverlay();\n\n const rect = this.ctx.container.getBoundingClientRect();\n this.overlayCtx.clearRect(0, 0, rect.width, rect.height);\n\n const opts = this.options;\n const ctx = this.overlayCtx;\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n // Update pixel coordinates of selected points to follow zoom/pan\n if (this.state.point1) {\n const p = this.state.point1;\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(p.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n }\n if (this.state.point2) {\n const p = this.state.point2;\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(p.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n }\n\n // Draw crosshair lines (dotted lines from cursor to axes)\n if (this.crosshairPosition && this.state.selectionState !== 'complete') {\n const cx = this.crosshairPosition.x;\n const cy = this.crosshairPosition.y;\n\n ctx.save();\n ctx.setLineDash([4, 4]);\n ctx.strokeStyle = 'rgba(150, 150, 150, 0.7)';\n ctx.lineWidth = 1;\n\n // Vertical line (to X axis)\n ctx.beginPath();\n ctx.moveTo(cx, plotArea.y);\n ctx.lineTo(cx, plotArea.y + plotArea.height);\n ctx.stroke();\n\n // Horizontal line (to Y axis)\n ctx.beginPath();\n ctx.moveTo(plotArea.x, cy);\n ctx.lineTo(plotArea.x + plotArea.width, cy);\n ctx.stroke();\n\n ctx.restore();\n }\n\n // Draw hovered point highlight (pulsing effect)\n if (this.state.hoveredPoint && this.state.selectionState !== 'complete') {\n const hp = this.state.hoveredPoint;\n\n // Outer glow\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, opts.highlightSize + 4, 0, Math.PI * 2);\n ctx.fillStyle = opts.highlightColor + '30';\n ctx.fill();\n\n // Main highlight\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.strokeStyle = opts.highlightColor;\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Center dot\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, 4, 0, Math.PI * 2);\n ctx.fillStyle = opts.highlightColor;\n ctx.fill();\n\n // Show coordinates tooltip\n this.drawPointTooltip(ctx, hp, 'Hover');\n }\n\n // Draw selected point 1\n if (this.state.point1) {\n const p1 = this.state.point1;\n\n // Selected point marker\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.fillStyle = opts.lineColor;\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, opts.highlightSize - 3, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, 3, 0, Math.PI * 2);\n ctx.fillStyle = opts.lineColor;\n ctx.fill();\n\n // Label for point 1\n this.drawPointLabel(ctx, p1.pixelX, p1.pixelY - opts.highlightSize - 8, 'P1', opts.lineColor);\n }\n\n // Draw selected point 2\n if (this.state.point2) {\n const p2 = this.state.point2;\n\n // Selected point marker\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.fillStyle = '#4ade80';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, opts.highlightSize - 3, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, 3, 0, Math.PI * 2);\n ctx.fillStyle = '#4ade80';\n ctx.fill();\n\n // Label for point 2\n this.drawPointLabel(ctx, p2.pixelX, p2.pixelY - opts.highlightSize - 8, 'P2', '#4ade80');\n }\n\n // Draw measurement line between points\n if (this.state.point1 && this.state.point2) {\n const p1 = this.state.point1;\n const p2 = this.state.point2;\n\n // Dashed line connecting points\n ctx.beginPath();\n ctx.moveTo(p1.pixelX, p1.pixelY);\n ctx.lineTo(p2.pixelX, p2.pixelY);\n ctx.strokeStyle = opts.lineColor;\n ctx.lineWidth = opts.lineWidth;\n ctx.setLineDash([6, 4]);\n ctx.stroke();\n ctx.setLineDash([]);\n\n // Delta lines (horizontal and vertical)\n ctx.beginPath();\n ctx.moveTo(p1.pixelX, p1.pixelY);\n ctx.lineTo(p2.pixelX, p1.pixelY);\n ctx.lineTo(p2.pixelX, p2.pixelY);\n ctx.strokeStyle = 'rgba(255, 107, 107, 0.4)';\n ctx.lineWidth = 1;\n ctx.setLineDash([3, 3]);\n ctx.stroke();\n ctx.setLineDash([]);\n\n // Draw measurement label\n if (opts.showLabels && this.state.lastMeasurement) {\n this.drawMeasurementLabel(ctx, p1, p2, this.state.lastMeasurement);\n }\n }\n\n // Draw status indicator\n this.drawStatusIndicator(ctx);\n }\n\n private drawPointTooltip(\n ctx: CanvasRenderingContext2D,\n point: DataPoint,\n label: string\n ): void {\n const opts = this.options;\n const text = `${label}: (${this.formatValue(point.x)}, ${this.formatValue(point.y)})`;\n\n ctx.font = `${opts.labelFontSize}px system-ui, sans-serif`;\n const metrics = ctx.measureText(text);\n const padding = 6;\n const boxWidth = metrics.width + padding * 2;\n const boxHeight = opts.labelFontSize + padding * 2;\n\n let boxX = point.pixelX + 15;\n let boxY = point.pixelY - boxHeight / 2;\n\n // Keep within container\n const rect = this.ctx.container.getBoundingClientRect();\n if (boxX + boxWidth > rect.width) boxX = point.pixelX - boxWidth - 15;\n if (boxY < 0) boxY = 5;\n if (boxY + boxHeight > rect.height) boxY = rect.height - boxHeight - 5;\n\n // Background\n ctx.fillStyle = opts.labelBackground;\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 4);\n ctx.fill();\n\n // Text\n ctx.fillStyle = opts.labelColor;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(text, boxX + padding, boxY + boxHeight / 2);\n }\n\n private drawPointLabel(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n label: string,\n color: string\n ): void {\n const opts = this.options;\n ctx.font = `bold ${opts.labelFontSize}px system-ui, sans-serif`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'bottom';\n\n // Background pill\n const metrics = ctx.measureText(label);\n const padding = 4;\n const pillWidth = metrics.width + padding * 2;\n const pillHeight = opts.labelFontSize + padding;\n\n ctx.fillStyle = color;\n this.roundRect(ctx, x - pillWidth / 2, y - pillHeight, pillWidth, pillHeight, 3);\n ctx.fill();\n\n // Text\n ctx.fillStyle = '#ffffff';\n ctx.fillText(label, x, y - 2);\n }\n\n private drawMeasurementLabel(\n ctx: CanvasRenderingContext2D,\n p1: DataPoint,\n p2: DataPoint,\n m: DeltaMeasurement\n ): void {\n const opts = this.options;\n const midX = (p1.pixelX + p2.pixelX) / 2;\n const midY = (p1.pixelY + p2.pixelY) / 2;\n\n const lines: string[] = [];\n\n if (opts.showDelta) {\n lines.push(`ΔX: ${this.formatValue(m.deltaX)}`);\n lines.push(`ΔY: ${this.formatValue(m.deltaY)}`);\n }\n\n if (opts.showSlope && isFinite(m.slope)) {\n lines.push(`Slope: ${this.formatValue(m.slope)}`);\n }\n\n if (opts.showDistance) {\n lines.push(`Distance: ${this.formatValue(m.distance)}`);\n }\n\n const lineHeight = opts.labelFontSize + 4;\n const padding = 10;\n const boxWidth = 170;\n const boxHeight = lines.length * lineHeight + padding * 2;\n\n // Position box using offset from midpoint\n let boxX = midX + this.labelOffset.x;\n let boxY = midY + this.labelOffset.y;\n\n // Keep within bounds\n const container = this.ctx.container.getBoundingClientRect();\n if (boxX < 0) boxX = 0;\n if (boxX + boxWidth > container.width) boxX = container.width - boxWidth;\n if (boxY < 0) boxY = 0;\n if (boxY + boxHeight > container.height) boxY = container.height - boxHeight;\n\n // Store bounds for hit testing\n this.labelBounds = { x: boxX, y: boxY, width: boxWidth, height: boxHeight };\n\n // Draw box with border\n ctx.fillStyle = opts.labelBackground;\n ctx.strokeStyle = opts.lineColor;\n ctx.lineWidth = 2;\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 8);\n ctx.fill();\n ctx.stroke();\n\n // Draw text\n ctx.fillStyle = opts.labelColor;\n ctx.font = `${opts.labelFontSize}px system-ui, sans-serif`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n\n lines.forEach((line, i) => {\n ctx.fillText(line, boxX + padding, boxY + padding + i * lineHeight);\n });\n }\n\n private drawStatusIndicator(\n ctx: CanvasRenderingContext2D\n ): void {\n const opts = this.options;\n const plotArea = this.ctx.getPlotArea();\n\n let statusText = '';\n let statusColor = '#666';\n\n if (this.state.selectionState === 'idle') {\n statusText = '📏 Click a point to start measuring';\n statusColor = opts.highlightColor;\n } else if (this.state.selectionState === 'waitingSecond') {\n statusText = '📏 Click second point to complete';\n statusColor = '#f59e0b';\n } else if (this.state.selectionState === 'complete') {\n statusText = '📏 Measurement complete (ESC to clear)';\n statusColor = '#4ade80';\n }\n\n if (!statusText) return;\n\n ctx.font = `12px system-ui, sans-serif`;\n const metrics = ctx.measureText(statusText);\n const padding = 8;\n const boxWidth = metrics.width + padding * 2;\n const boxHeight = 24;\n const boxX = plotArea.x + 10;\n const boxY = plotArea.y + 10;\n\n // Background\n ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 4);\n ctx.fill();\n\n // Status dot\n ctx.beginPath();\n ctx.arc(boxX + 16, boxY + boxHeight / 2, 4, 0, Math.PI * 2);\n ctx.fillStyle = statusColor;\n ctx.fill();\n\n // Text\n ctx.fillStyle = '#fff';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(statusText, boxX + 26, boxY + boxHeight / 2);\n }\n\n private roundRect(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n r: number\n ): void {\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + w - r, y);\n ctx.quadraticCurveTo(x + w, y, x + w, y + r);\n ctx.lineTo(x + w, y + h - r);\n ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\n ctx.lineTo(x + r, y + h);\n ctx.quadraticCurveTo(x, y + h, x, y + h - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n }\n\n private formatValue(val: number): string {\n const abs = Math.abs(val);\n if (abs === 0) return '0';\n if (abs >= 1e6 || abs < 0.001) {\n return val.toExponential(this.options.precision - 1);\n }\n return val.toPrecision(this.options.precision);\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\n/**\n * Create a delta tool for a chart context\n */\nexport function createDeltaTool(\n context: DeltaToolContext,\n options?: DeltaToolOptions\n): DeltaTool {\n return new DeltaTool(context, options);\n}\n","/**\n * Sci Plot - Peak Tool Module\n * \n * Provides interactive measurement tool for measuring distances,\n * differences, and slopes between two data points on the chart.\n * \n * Features:\n * - Click to select first point (snaps to nearest data point)\n * - Click to select second point \n * - Highlight points on hover\n * - Show peak measurements between points\n * \n * @module peak-tool\n */\n\nimport type { PeakMeasurement, Bounds } from '../../../types';\nimport type { AnimationEngine } from '../../../core/animation';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface PeakToolOptions {\n /** Line color for measurement (default: '#ff6b6b') */\n lineColor?: string;\n /** Line width in pixels (default: 2) */\n lineWidth?: number;\n /** Show labels at measurement points (default: true) */\n showLabels?: boolean;\n /** Label font size (default: 12) */\n labelFontSize?: number;\n /** Label background color (default: 'rgba(0,0,0,0.8)') */\n labelBackground?: string;\n /** Label text color (default: '#ffffff') */\n labelColor?: string;\n /** Show peak values inline (default: true) */\n showPeak?: boolean;\n /** Number precision for values (default: 4) */\n precision?: number;\n /** Custom CSS class for overlay elements */\n className?: string;\n /** Number of points to use for baseline regression (default: 10) */\n baselineWindow?: number;\n /** Area fill color (default: 'rgba(255, 107, 107, 0.3)') */\n areaFill?: string;\n /** Point highlight size when hovering (default: 10) */\n highlightSize?: number;\n /** Point highlight color (default: '#00f2ff') */\n highlightColor?: string;\n /** Snap radius in pixels for detecting nearby points (default: 20) */\n snapRadius?: number;\n}\n\n/** Data point with series information */\nexport interface DataPoint {\n x: number;\n y: number;\n seriesId: string;\n yAxisId?: string;\n index: number;\n pixelX: number;\n pixelY: number;\n}\n\nexport interface PeakToolState {\n /** Whether the tool is enabled */\n enabled: boolean;\n /** Selection state: 'idle' | 'waitingSecond' | 'complete' */\n selectionState: 'idle' | 'waitingSecond' | 'complete';\n /** First selected point */\n point1: DataPoint | null;\n /** Second selected point */\n point2: DataPoint | null;\n /** Currently hovered point (for highlighting) */\n hoveredPoint: DataPoint | null;\n /** Last completed measurement */\n lastMeasurement: PeakMeasurement | null;\n}\n\nexport interface SeriesData {\n id: string;\n x: Float32Array | Float64Array | number[];\n y: Float32Array | Float64Array | number[];\n yAxisId?: string;\n}\n\nexport interface PeakToolContext {\n container: HTMLElement;\n getPlotArea: () => { x: number; y: number; width: number; height: number };\n getViewBounds: () => Bounds;\n getYBounds?: (yAxisId?: string) => { yMin: number; yMax: number };\n requestRender: () => void;\n getSeries?: () => SeriesData[];\n onMeasure?: (measurement: PeakMeasurement) => void;\n animationEngine?: AnimationEngine;\n}\n\n// ============================================\n// Peak Tool Implementation\n// ============================================\n\nexport class PeakTool {\n private ctx: PeakToolContext;\n private options: Required<PeakToolOptions>;\n private state: PeakToolState = {\n enabled: false,\n selectionState: 'idle',\n point1: null,\n point2: null,\n hoveredPoint: null,\n lastMeasurement: null,\n };\n\n private overlayCanvas: HTMLCanvasElement | null = null;\n private overlayCtx: CanvasRenderingContext2D | null = null;\n\n // Label dragging\n private labelOffset: { x: number; y: number } = { x: 15, y: 0 };\n private isDraggingLabel = false;\n private labelBounds: { x: number; y: number; width: number; height: number } | null = null;\n private dragStart: { x: number; y: number } = { x: 0, y: 0 };\n private crosshairPosition: { x: number; y: number } | null = null;\n\n // Bound handlers\n private boundMouseMove: (e: MouseEvent) => void;\n private boundClick: (e: MouseEvent) => void;\n private boundKeyDown: (e: KeyboardEvent) => void;\n private boundMouseDown: (e: MouseEvent) => void;\n private boundMouseUp: (e: MouseEvent) => void;\n private boundResize: () => void;\n\n constructor(context: PeakToolContext, options?: PeakToolOptions) {\n this.ctx = context;\n this.options = {\n lineColor: '#ff6b6b',\n lineWidth: 2,\n showLabels: true,\n labelFontSize: 12,\n labelBackground: 'rgba(0, 0, 0, 0.85)',\n labelColor: '#ffffff',\n showPeak: true,\n precision: 4,\n className: 'velo-plot-peak-tool',\n highlightSize: 12,\n highlightColor: '#00f2ff',\n snapRadius: 30,\n baselineWindow: 10,\n areaFill: 'rgba(255, 107, 107, 0.3)',\n ...options,\n };\n\n this.boundMouseMove = this.handleMouseMove.bind(this);\n this.boundClick = this.handleClick.bind(this);\n this.boundKeyDown = this.handleKeyDown.bind(this);\n this.boundMouseDown = this.handleLabelMouseDown.bind(this);\n this.boundMouseUp = this.handleLabelMouseUp.bind(this);\n this.boundResize = this.resizeOverlay.bind(this);\n }\n\n /**\n * Enable the peak measurement tool\n */\n enable(): void {\n if (this.state.enabled) return;\n\n this.state.enabled = true;\n this.state.selectionState = 'idle';\n this.createOverlay();\n this.attachListeners();\n this.ctx.container.style.cursor = 'crosshair';\n }\n\n /**\n * Disable the peak measurement tool\n */\n disable(): void {\n if (!this.state.enabled) return;\n\n this.state.enabled = false;\n this.state.selectionState = 'idle';\n this.state.point1 = null;\n this.state.point2 = null;\n this.state.hoveredPoint = null;\n\n this.detachListeners();\n this.destroyOverlay();\n this.ctx.container.style.cursor = '';\n }\n\n /**\n * Toggle the tool on/off\n */\n toggle(): void {\n if (this.state.enabled) {\n this.disable();\n } else {\n this.enable();\n }\n }\n\n /**\n * Check if tool is enabled\n */\n isEnabled(): boolean {\n return this.state.enabled;\n }\n\n /**\n * Get the current state\n */\n getState(): PeakToolState {\n return { ...this.state };\n }\n\n /**\n * Get the last completed measurement\n */\n getMeasurement(): PeakMeasurement | null {\n return this.state.lastMeasurement;\n }\n\n /**\n * Clear the current measurement\n */\n clear(): void {\n this.state.point1 = null;\n this.state.point2 = null;\n this.state.selectionState = 'idle';\n this.state.lastMeasurement = null;\n this.labelBounds = null;\n this.labelOffset = { x: 15, y: 0 };\n this.renderOverlay();\n }\n\n /**\n * Destroy the tool and cleanup\n */\n destroy(): void {\n this.disable();\n this.state.lastMeasurement = null;\n }\n\n /**\n * Recalculate measurements (useful if data changes)\n */\n public recalculate(): void {\n if (!this.state.point1 || !this.state.point2) return;\n\n // Refresh data points from series\n const seriesList = this.ctx.getSeries ? this.ctx.getSeries() : [];\n\n const updatePoint = (p: DataPoint) => {\n const s = seriesList.find(ser => ser.id === p.seriesId);\n if (s && p.index < s.x.length) {\n p.x = s.x[p.index];\n p.y = s.y[p.index];\n p.yAxisId = s.yAxisId;\n\n // Update pixel coordinates\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(s.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n return true;\n }\n return false;\n };\n\n const p1Valid = updatePoint(this.state.point1);\n const p2Valid = updatePoint(this.state.point2);\n\n if (p1Valid && p2Valid) {\n this.state.lastMeasurement = this.calculateMeasurement();\n if (this.ctx.onMeasure) {\n this.ctx.onMeasure(this.state.lastMeasurement);\n }\n } else {\n this.clear();\n }\n\n this.renderOverlay();\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private createOverlay(): void {\n if (this.overlayCanvas) return;\n\n this.overlayCanvas = document.createElement('canvas');\n this.overlayCanvas.className = this.options.className;\n this.overlayCanvas.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 1000;\n `;\n\n this.resizeOverlay();\n this.overlayCtx = this.overlayCanvas.getContext('2d');\n this.ctx.container.appendChild(this.overlayCanvas);\n }\n\n private resizeOverlay(): void {\n if (!this.overlayCanvas) return;\n const rect = this.ctx.container.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n this.overlayCanvas.width = rect.width * dpr;\n this.overlayCanvas.height = rect.height * dpr;\n if (this.overlayCtx) {\n this.overlayCtx.setTransform(1, 0, 0, 1, 0, 0);\n this.overlayCtx.scale(dpr, dpr);\n }\n }\n\n private destroyOverlay(): void {\n if (this.overlayCanvas && this.overlayCanvas.parentNode) {\n this.overlayCanvas.parentNode.removeChild(this.overlayCanvas);\n }\n this.overlayCanvas = null;\n this.overlayCtx = null;\n }\n\n private attachListeners(): void {\n // Use capture phase to get events before InteractionManager\n this.ctx.container.addEventListener('mousemove', this.boundMouseMove, true);\n this.ctx.container.addEventListener('mousedown', this.boundClick, true);\n this.ctx.container.addEventListener('mousedown', this.boundMouseDown, true);\n this.ctx.container.addEventListener('mouseup', this.boundMouseUp, true);\n window.addEventListener('resize', this.boundResize);\n document.addEventListener('keydown', this.boundKeyDown);\n }\n\n private detachListeners(): void {\n this.ctx.container.removeEventListener('mousemove', this.boundMouseMove, true);\n this.ctx.container.removeEventListener('mousedown', this.boundClick, true);\n this.ctx.container.removeEventListener('mousedown', this.boundMouseDown, true);\n this.ctx.container.removeEventListener('mouseup', this.boundMouseUp, true);\n window.removeEventListener('resize', this.boundResize);\n document.removeEventListener('keydown', this.boundKeyDown);\n }\n\n private handleMouseMove(e: MouseEvent): void {\n if (!this.state.enabled) return;\n\n const rect = this.ctx.container.getBoundingClientRect();\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n // Handle label dragging\n if (this.isDraggingLabel) {\n this.labelOffset.x += pixelX - this.dragStart.x;\n this.labelOffset.y += pixelY - this.dragStart.y;\n this.dragStart = { x: pixelX, y: pixelY };\n this.renderOverlay();\n return;\n }\n\n // Update cursor if over label\n if (this.labelBounds &&\n pixelX >= this.labelBounds.x && pixelX <= this.labelBounds.x + this.labelBounds.width &&\n pixelY >= this.labelBounds.y && pixelY <= this.labelBounds.y + this.labelBounds.height) {\n this.ctx.container.style.cursor = 'move';\n } else {\n this.ctx.container.style.cursor = 'crosshair';\n }\n\n // Check if inside plot area\n if (\n pixelX < plotArea.x ||\n pixelX > plotArea.x + plotArea.width ||\n pixelY < plotArea.y ||\n pixelY > plotArea.y + plotArea.height\n ) {\n this.state.hoveredPoint = null;\n this.crosshairPosition = null;\n this.renderOverlay();\n return;\n }\n\n // Store current mouse position for crosshair\n this.crosshairPosition = { x: pixelX, y: pixelY };\n\n // Find nearest data point\n // When waiting for second point, only show points from the same series\n const seriesFilter = this.state.selectionState === 'waitingSecond' && this.state.point1\n ? this.state.point1.seriesId\n : undefined;\n const nearestPoint = this.findNearestPoint(pixelX, pixelY, plotArea, bounds, seriesFilter);\n this.state.hoveredPoint = nearestPoint;\n this.renderOverlay();\n }\n\n private handleLabelMouseDown(e: MouseEvent): void {\n if (!this.state.enabled || !this.labelBounds) return;\n\n const rect = this.ctx.container.getBoundingClientRect();\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n if (pixelX >= this.labelBounds.x && pixelX <= this.labelBounds.x + this.labelBounds.width &&\n pixelY >= this.labelBounds.y && pixelY <= this.labelBounds.y + this.labelBounds.height) {\n this.isDraggingLabel = true;\n this.dragStart = { x: pixelX, y: pixelY };\n e.stopPropagation();\n e.preventDefault();\n }\n }\n\n private handleLabelMouseUp(): void {\n this.isDraggingLabel = false;\n }\n\n private async handleClick(e: MouseEvent): Promise<void> {\n if (!this.state.enabled) return;\n\n // If chart is animating, wait for it to settle to get accurate coordinates\n if (this.ctx.animationEngine?.isAnimating()) {\n await this.ctx.animationEngine.waitForIdle();\n }\n\n // Stop propagation to prevent InteractionManager from handling this\n e.stopPropagation();\n e.preventDefault();\n\n const rect = this.ctx.container.getBoundingClientRect();\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n const pixelX = e.clientX - rect.left;\n const pixelY = e.clientY - rect.top;\n\n // Check if inside plot area\n if (\n pixelX < plotArea.x ||\n pixelX > plotArea.x + plotArea.width ||\n pixelY < plotArea.y ||\n pixelY > plotArea.y + plotArea.height\n ) {\n return;\n }\n\n // Find nearest data point\n // When waiting for second point, only look for points from the same series\n const seriesFilter = this.state.selectionState === 'waitingSecond' && this.state.point1\n ? this.state.point1.seriesId\n : undefined;\n const nearestPoint = this.findNearestPoint(pixelX, pixelY, plotArea, bounds, seriesFilter);\n\n if (!nearestPoint) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n if (this.state.selectionState === 'idle' || this.state.selectionState === 'complete') {\n // Select first point\n this.state.point1 = nearestPoint;\n this.state.point2 = null;\n this.state.selectionState = 'waitingSecond';\n this.state.lastMeasurement = null;\n } else if (this.state.selectionState === 'waitingSecond') {\n // For peak integration, both points MUST be on the same series\n if (this.state.point1 && nearestPoint.seriesId !== this.state.point1.seriesId) {\n // Ignore - user clicked on a different series\n return;\n }\n\n // Select second point\n this.state.point2 = nearestPoint;\n this.state.selectionState = 'complete';\n\n // Calculate measurement\n const measurement = this.calculateMeasurement();\n this.state.lastMeasurement = measurement;\n\n if (this.ctx.onMeasure) {\n this.ctx.onMeasure(measurement);\n }\n }\n\n this.renderOverlay();\n }\n\n private handleKeyDown(e: KeyboardEvent): void {\n if (e.key === 'Escape' && this.state.enabled) {\n this.clear();\n }\n }\n\n private findNearestPoint(\n pixelX: number,\n pixelY: number,\n plotArea: { x: number; y: number; width: number; height: number },\n bounds: Bounds,\n seriesIdFilter?: string\n ): DataPoint | null {\n if (!this.ctx.getSeries) return null;\n\n const series = this.ctx.getSeries();\n let nearestPoint: DataPoint | null = null;\n let minDistance = this.options.snapRadius;\n\n for (const s of series) {\n // If filtering by series ID, skip other series\n if (seriesIdFilter && s.id !== seriesIdFilter) continue;\n\n const xData = s.x;\n const yData = s.y;\n const len = Math.min(xData.length, yData.length);\n\n // Get Y bounds for this series (may be different if using secondary Y axis)\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(s.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n\n for (let i = 0; i < len; i++) {\n const dataX = xData[i];\n const dataY = yData[i];\n\n // Convert data to pixel coordinates\n const px = plotArea.x + ((dataX - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n const py = plotArea.y + (1 - (dataY - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n\n // Skip if outside visible range\n if (px < plotArea.x || px > plotArea.x + plotArea.width) continue;\n if (py < plotArea.y || py > plotArea.y + plotArea.height) continue;\n\n const distance = Math.sqrt((pixelX - px) ** 2 + (pixelY - py) ** 2);\n\n if (distance < minDistance) {\n minDistance = distance;\n nearestPoint = {\n x: dataX,\n y: dataY,\n seriesId: s.id,\n yAxisId: s.yAxisId,\n index: i,\n pixelX: px,\n pixelY: py,\n };\n }\n }\n }\n\n return nearestPoint;\n }\n\n private calculateMeasurement(): PeakMeasurement {\n const p1 = this.state.point1!;\n const p2 = this.state.point2!;\n const seriesList = this.ctx.getSeries ? this.ctx.getSeries() : [];\n const series = seriesList.find(s => s.id === p1.seriesId);\n\n if (!series) {\n return {\n x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y,\n area: 0, integral: 0, baselineSlope: 0, baselineIntercept: 0,\n peakHeight: 0, peakX: 0, peakY: 0,\n pixelX1: p1.pixelX, pixelY1: p1.pixelY, pixelX2: p2.pixelX, pixelY2: p2.pixelY\n };\n }\n\n const xData = series.x;\n const yData = series.y;\n const idx1 = Math.min(p1.index, p2.index);\n const idx2 = Math.max(p1.index, p2.index);\n\n // Baseline detection using linear regression on windows around p1 and p2 (noise segments)\n const win = this.options.baselineWindow;\n const baselinePointsX: number[] = [];\n const baselinePointsY: number[] = [];\n\n // Window around idx1\n for (let i = Math.max(0, idx1 - Math.floor(win / 2)); i <= Math.min(xData.length - 1, idx1 + Math.floor(win / 2)); i++) {\n baselinePointsX.push(xData[i]);\n baselinePointsY.push(yData[i]);\n }\n // Window around idx2\n for (let i = Math.max(0, idx2 - Math.floor(win / 2)); i <= Math.min(xData.length - 1, idx2 + Math.floor(win / 2)); i++) {\n baselinePointsX.push(xData[i]);\n baselinePointsY.push(yData[i]);\n }\n\n // Linear regression: y = mx + b\n const n = baselinePointsX.length;\n let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0;\n for (let i = 0; i < n; i++) {\n sumX += baselinePointsX[i];\n sumY += baselinePointsY[i];\n sumXY += baselinePointsX[i] * baselinePointsY[i];\n sumXX += baselinePointsX[i] * baselinePointsX[i];\n }\n const baselineSlope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);\n const baselineIntercept = (sumY - baselineSlope * sumX) / n;\n\n // Numerical integration (trapezoidal rule)\n let area = 0;\n let integral = 0;\n let peakHeight = -Infinity;\n let peakX = 0;\n let peakY = 0;\n\n for (let i = idx1; i < idx2; i++) {\n const x_a = xData[i];\n const y_a = yData[i];\n const x_b = xData[i + 1];\n const y_b = yData[i + 1];\n\n const dx = x_b - x_a;\n const avgY = (y_a + y_b) / 2;\n\n integral += avgY * dx;\n\n // Baseline value at these points\n const bl_a = baselineSlope * x_a + baselineIntercept;\n const bl_b = baselineSlope * x_b + baselineIntercept;\n const avgBL = (bl_a + bl_b) / 2;\n\n area += (avgY - avgBL) * dx;\n\n // Find maximum elevation above baseline\n const h_a = y_a - bl_a;\n if (h_a > peakHeight) {\n peakHeight = h_a;\n peakX = x_a;\n peakY = y_a;\n }\n }\n\n return {\n x1: p1.x, y1: p1.y,\n x2: p2.x, y2: p2.y,\n area, integral, baselineSlope, baselineIntercept,\n peakHeight, peakX, peakY,\n pixelX1: p1.pixelX, pixelY1: p1.pixelY,\n pixelX2: p2.pixelX, pixelY2: p2.pixelY\n };\n }\n\n public renderOverlay(): void {\n if (!this.overlayCtx || !this.overlayCanvas) return;\n\n // Resize if needed\n this.resizeOverlay();\n\n const rect = this.ctx.container.getBoundingClientRect();\n this.overlayCtx.clearRect(0, 0, rect.width, rect.height);\n\n const opts = this.options;\n const ctx = this.overlayCtx;\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n // Update pixel coordinates of selected points to follow zoom/pan\n if (this.state.point1) {\n const p = this.state.point1;\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(p.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n }\n if (this.state.point2) {\n const p = this.state.point2;\n const yBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(p.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n p.pixelX = plotArea.x + ((p.x - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n p.pixelY = plotArea.y + (1 - (p.y - yBounds.yMin) / (yBounds.yMax - yBounds.yMin)) * plotArea.height;\n }\n\n // Draw crosshair lines (dotted lines from cursor to axes)\n if (this.crosshairPosition && this.state.selectionState !== 'complete') {\n const cx = this.crosshairPosition.x;\n const cy = this.crosshairPosition.y;\n\n ctx.save();\n ctx.setLineDash([4, 4]);\n ctx.strokeStyle = 'rgba(150, 150, 150, 0.7)';\n ctx.lineWidth = 1;\n\n // Vertical line (to X axis)\n ctx.beginPath();\n ctx.moveTo(cx, plotArea.y);\n ctx.lineTo(cx, plotArea.y + plotArea.height);\n ctx.stroke();\n\n // Horizontal line (to Y axis)\n ctx.beginPath();\n ctx.moveTo(plotArea.x, cy);\n ctx.lineTo(plotArea.x + plotArea.width, cy);\n ctx.stroke();\n\n ctx.restore();\n }\n\n // Draw hovered point highlight (pulsing effect)\n if (this.state.hoveredPoint && this.state.selectionState !== 'complete') {\n const hp = this.state.hoveredPoint;\n\n // Outer glow\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, opts.highlightSize + 4, 0, Math.PI * 2);\n ctx.fillStyle = opts.highlightColor + '30';\n ctx.fill();\n\n // Main highlight\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.strokeStyle = opts.highlightColor;\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Center dot\n ctx.beginPath();\n ctx.arc(hp.pixelX, hp.pixelY, 4, 0, Math.PI * 2);\n ctx.fillStyle = opts.highlightColor;\n ctx.fill();\n\n // Show coordinates tooltip\n this.drawPointTooltip(ctx, hp, 'Hover');\n }\n\n // Draw selected point 1\n if (this.state.point1) {\n const p1 = this.state.point1;\n\n // Selected point marker\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.fillStyle = opts.lineColor;\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, opts.highlightSize - 3, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p1.pixelX, p1.pixelY, 3, 0, Math.PI * 2);\n ctx.fillStyle = opts.lineColor;\n ctx.fill();\n\n // Label for point 1\n this.drawPointLabel(ctx, p1.pixelX, p1.pixelY - opts.highlightSize - 8, 'P1', opts.lineColor);\n }\n\n // Draw selected point 2\n if (this.state.point2) {\n const p2 = this.state.point2;\n\n // Selected point marker\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, opts.highlightSize, 0, Math.PI * 2);\n ctx.fillStyle = '#4ade80';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, opts.highlightSize - 3, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.beginPath();\n ctx.arc(p2.pixelX, p2.pixelY, 3, 0, Math.PI * 2);\n ctx.fillStyle = '#4ade80';\n ctx.fill();\n\n // Label for point 2\n this.drawPointLabel(ctx, p2.pixelX, p2.pixelY - opts.highlightSize - 8, 'P2', '#4ade80');\n }\n\n // Draw baseline and area\n if (this.state.point1 && this.state.point2 && this.state.lastMeasurement) {\n const p1 = this.state.point1;\n const p2 = this.state.point2;\n const m = this.state.lastMeasurement;\n const plotArea = this.ctx.getPlotArea();\n const bounds = this.ctx.getViewBounds();\n\n // Draw area fill\n const seriesList = this.ctx.getSeries ? this.ctx.getSeries() : [];\n const series = seriesList.find(s => s.id === p1.seriesId);\n if (series) {\n const xData = series.x;\n const yData = series.y;\n const idx1 = Math.min(p1.index, p2.index);\n const idx2 = Math.max(p1.index, p2.index);\n\n // Get correct Y bounds for this series\n const seriesYBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(series.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n\n ctx.beginPath();\n // Start from first point on baseline\n ctx.moveTo(p1.pixelX, p1.pixelY);\n\n // Trace the peak curve\n for (let i = idx1; i <= idx2; i++) {\n const px = plotArea.x + ((xData[i] - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n const py = plotArea.y + (1 - (yData[i] - seriesYBounds.yMin) / (seriesYBounds.yMax - seriesYBounds.yMin)) * plotArea.height;\n ctx.lineTo(px, py);\n }\n\n // Close back along baseline\n ctx.lineTo(p2.pixelX, p2.pixelY);\n ctx.closePath();\n\n ctx.fillStyle = opts.areaFill;\n ctx.fill();\n }\n\n // Draw baseline (straight line from regression)\n ctx.beginPath();\n ctx.moveTo(p1.pixelX, p1.pixelY);\n ctx.lineTo(p2.pixelX, p2.pixelY);\n ctx.strokeStyle = opts.lineColor;\n ctx.lineWidth = 1;\n ctx.stroke();\n\n // Peak height indicator - use correct Y bounds\n const peakYBounds = this.ctx.getYBounds\n ? this.ctx.getYBounds(p1.yAxisId)\n : { yMin: bounds.yMin, yMax: bounds.yMax };\n const peakPX = plotArea.x + ((m.peakX - bounds.xMin) / (bounds.xMax - bounds.xMin)) * plotArea.width;\n const peakPY = plotArea.y + (1 - (m.peakY - peakYBounds.yMin) / (peakYBounds.yMax - peakYBounds.yMin)) * plotArea.height;\n const baselineAtPeak = m.baselineSlope * m.peakX + m.baselineIntercept;\n const basePY = plotArea.y + (1 - (baselineAtPeak - peakYBounds.yMin) / (peakYBounds.yMax - peakYBounds.yMin)) * plotArea.height;\n\n ctx.beginPath();\n ctx.moveTo(peakPX, peakPY);\n ctx.lineTo(peakPX, basePY);\n ctx.strokeStyle = opts.lineColor;\n ctx.setLineDash([2, 2]);\n ctx.stroke();\n ctx.setLineDash([]);\n\n // Draw measurement label\n if (opts.showLabels) {\n this.drawMeasurementLabel(ctx, p1, p2, m);\n }\n }\n\n // Draw status indicator\n this.drawStatusIndicator(ctx);\n }\n\n private drawPointTooltip(\n ctx: CanvasRenderingContext2D,\n point: DataPoint,\n label: string\n ): void {\n const opts = this.options;\n const text = `${label}: (${this.formatValue(point.x)}, ${this.formatValue(point.y)})`;\n\n ctx.font = `${opts.labelFontSize}px system-ui, sans-serif`;\n const metrics = ctx.measureText(text);\n const padding = 6;\n const boxWidth = metrics.width + padding * 2;\n const boxHeight = opts.labelFontSize + padding * 2;\n\n let boxX = point.pixelX + 15;\n let boxY = point.pixelY - boxHeight / 2;\n\n // Keep within container\n const rect = this.ctx.container.getBoundingClientRect();\n if (boxX + boxWidth > rect.width) boxX = point.pixelX - boxWidth - 15;\n if (boxY < 0) boxY = 5;\n if (boxY + boxHeight > rect.height) boxY = rect.height - boxHeight - 5;\n\n // Background\n ctx.fillStyle = opts.labelBackground;\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 4);\n ctx.fill();\n\n // Text\n ctx.fillStyle = opts.labelColor;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(text, boxX + padding, boxY + boxHeight / 2);\n }\n\n private drawPointLabel(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n label: string,\n color: string\n ): void {\n const opts = this.options;\n ctx.font = `bold ${opts.labelFontSize}px system-ui, sans-serif`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'bottom';\n\n // Background pill\n const metrics = ctx.measureText(label);\n const padding = 4;\n const pillWidth = metrics.width + padding * 2;\n const pillHeight = opts.labelFontSize + padding;\n\n ctx.fillStyle = color;\n this.roundRect(ctx, x - pillWidth / 2, y - pillHeight, pillWidth, pillHeight, 3);\n ctx.fill();\n\n // Text\n ctx.fillStyle = '#ffffff';\n ctx.fillText(label, x, y - 2);\n }\n\n private drawMeasurementLabel(\n ctx: CanvasRenderingContext2D,\n p1: DataPoint,\n p2: DataPoint,\n m: PeakMeasurement\n ): void {\n const opts = this.options;\n const midX = (p1.pixelX + p2.pixelX) / 2;\n const midY = (p1.pixelY + p2.pixelY) / 2;\n\n const lines: string[] = [];\n if (opts.showPeak) {\n lines.push(`Peak Area: ${this.formatValue(m.area)}`);\n lines.push(`Peak Height: ${this.formatValue(m.peakHeight)}`);\n lines.push(`Integral: ${this.formatValue(m.integral)}`);\n }\n\n const lineHeight = opts.labelFontSize + 4;\n const padding = 10;\n const boxWidth = 170;\n const boxHeight = lines.length * lineHeight + padding * 2;\n\n // Position box using offset from midpoint\n let boxX = midX + this.labelOffset.x;\n let boxY = midY + this.labelOffset.y;\n\n // Keep within bounds\n const container = this.ctx.container.getBoundingClientRect();\n if (boxX < 0) boxX = 0;\n if (boxX + boxWidth > container.width) boxX = container.width - boxWidth;\n if (boxY < 0) boxY = 0;\n if (boxY + boxHeight > container.height) boxY = container.height - boxHeight;\n\n // Store bounds for hit testing\n this.labelBounds = { x: boxX, y: boxY, width: boxWidth, height: boxHeight };\n\n // Draw box with border\n ctx.fillStyle = opts.labelBackground;\n ctx.strokeStyle = opts.lineColor;\n ctx.lineWidth = 2;\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 8);\n ctx.fill();\n ctx.stroke();\n\n // Draw text\n ctx.fillStyle = opts.labelColor;\n ctx.font = `${opts.labelFontSize}px system-ui, sans-serif`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n\n lines.forEach((line, i) => {\n ctx.fillText(line, boxX + padding, boxY + padding + i * lineHeight);\n });\n }\n\n private drawStatusIndicator(\n ctx: CanvasRenderingContext2D\n ): void {\n const opts = this.options;\n const plotArea = this.ctx.getPlotArea();\n\n let statusText = '';\n let statusColor = '#666';\n\n if (this.state.selectionState === 'idle') {\n statusText = '📏 Click a point to start measuring';\n statusColor = opts.highlightColor;\n } else if (this.state.selectionState === 'waitingSecond') {\n statusText = '📏 Click second point to complete';\n statusColor = '#f59e0b';\n } else if (this.state.selectionState === 'complete') {\n statusText = '📏 Measurement complete (ESC to clear)';\n statusColor = '#4ade80';\n }\n\n if (!statusText) return;\n\n ctx.font = `12px system-ui, sans-serif`;\n const metrics = ctx.measureText(statusText);\n const padding = 8;\n const boxWidth = metrics.width + padding * 2;\n const boxHeight = 24;\n const boxX = plotArea.x + 10;\n const boxY = plotArea.y + 10;\n\n // Background\n ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';\n this.roundRect(ctx, boxX, boxY, boxWidth, boxHeight, 4);\n ctx.fill();\n\n // Status dot\n ctx.beginPath();\n ctx.arc(boxX + 16, boxY + boxHeight / 2, 4, 0, Math.PI * 2);\n ctx.fillStyle = statusColor;\n ctx.fill();\n\n // Text\n ctx.fillStyle = '#fff';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(statusText, boxX + 26, boxY + boxHeight / 2);\n }\n\n private roundRect(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n r: number\n ): void {\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + w - r, y);\n ctx.quadraticCurveTo(x + w, y, x + w, y + r);\n ctx.lineTo(x + w, y + h - r);\n ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\n ctx.lineTo(x + r, y + h);\n ctx.quadraticCurveTo(x, y + h, x, y + h - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n }\n\n private formatValue(val: number): string {\n const abs = Math.abs(val);\n if (abs === 0) return '0';\n if (abs >= 1e6 || abs < 0.001) {\n return val.toExponential(this.options.precision - 1);\n }\n return val.toPrecision(this.options.precision);\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\n/**\n * Create a peak tool for a chart context\n */\nexport function createPeakTool(\n context: PeakToolContext,\n options?: PeakToolOptions\n): PeakTool {\n return new PeakTool(context, options);\n}\n","/**\n * Tooltip Themes - Predefined visual styles for tooltips\n * \n * This module provides beautiful, high-quality tooltip themes that\n * integrate seamlessly with the chart theme system.\n * \n * @module tooltip/themes\n */\n\nimport type { TooltipTheme } from './types';\n\n// ============================================\n// Base Defaults\n// ============================================\n\nconst DEFAULT_PADDING = {\n top: 10,\n right: 12,\n bottom: 10,\n left: 12\n};\n\n// ============================================\n// Dark Theme\n// ============================================\n\n/**\n * Dark Theme - Elegant dark tooltip with subtle glow\n */\nexport const TOOLTIP_DARK_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(15, 18, 25, 0.95)',\n backgroundGradient: 'rgba(25, 30, 40, 0.90)',\n borderColor: 'rgba(255, 255, 255, 0.12)',\n borderWidth: 1,\n borderRadius: 8,\n backdropBlur: 12,\n shadow: {\n color: 'rgba(0, 0, 0, 0.4)',\n offsetX: 0,\n offsetY: 4,\n blur: 16\n },\n \n // Typography\n fontFamily: 'Inter, system-ui, -apple-system, BlinkMacSystemFont, sans-serif',\n textColor: '#ffffff',\n textSecondaryColor: 'rgba(255, 255, 255, 0.6)',\n titleFontSize: 12,\n titleFontWeight: 600,\n contentFontSize: 11,\n lineHeight: 1.4,\n \n // Spacing\n padding: DEFAULT_PADDING,\n itemGap: 4,\n headerGap: 8,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 8,\n showHeaderSeparator: true,\n separatorColor: 'rgba(255, 255, 255, 0.1)',\n showArrow: true,\n arrowSize: 6\n};\n\n// ============================================\n// Light Theme\n// ============================================\n\n/**\n * Light Theme - Clean and professional for light backgrounds\n */\nexport const TOOLTIP_LIGHT_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(255, 255, 255, 0.98)',\n borderColor: 'rgba(0, 0, 0, 0.12)',\n borderWidth: 1,\n borderRadius: 8,\n backdropBlur: 8,\n shadow: {\n color: 'rgba(0, 0, 0, 0.12)',\n offsetX: 0,\n offsetY: 4,\n blur: 12\n },\n \n // Typography\n fontFamily: 'Inter, system-ui, -apple-system, BlinkMacSystemFont, sans-serif',\n textColor: '#1a1a1a',\n textSecondaryColor: 'rgba(0, 0, 0, 0.55)',\n titleFontSize: 12,\n titleFontWeight: 600,\n contentFontSize: 11,\n lineHeight: 1.4,\n \n // Spacing\n padding: DEFAULT_PADDING,\n itemGap: 4,\n headerGap: 8,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 8,\n showHeaderSeparator: true,\n separatorColor: 'rgba(0, 0, 0, 0.08)',\n showArrow: true,\n arrowSize: 6\n};\n\n// ============================================\n// Glassmorphism Theme\n// ============================================\n\n/**\n * Glassmorphism Theme - Modern frosted glass effect\n */\nexport const TOOLTIP_GLASS_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(255, 255, 255, 0.08)',\n backgroundGradient: 'rgba(255, 255, 255, 0.04)',\n borderColor: 'rgba(255, 255, 255, 0.2)',\n borderWidth: 1,\n borderRadius: 12,\n backdropBlur: 20,\n shadow: {\n color: 'rgba(0, 0, 0, 0.3)',\n offsetX: 0,\n offsetY: 8,\n blur: 32\n },\n \n // Typography\n fontFamily: 'Inter, system-ui, sans-serif',\n textColor: 'rgba(255, 255, 255, 0.95)',\n textSecondaryColor: 'rgba(255, 255, 255, 0.6)',\n titleFontSize: 12,\n titleFontWeight: 600,\n contentFontSize: 11,\n lineHeight: 1.5,\n \n // Spacing\n padding: { top: 12, right: 14, bottom: 12, left: 14 },\n itemGap: 5,\n headerGap: 10,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 8,\n showHeaderSeparator: true,\n separatorColor: 'rgba(255, 255, 255, 0.15)',\n showArrow: true,\n arrowSize: 7\n};\n\n// ============================================\n// Midnight Theme\n// ============================================\n\n/**\n * Midnight Theme - Deep blue tones for night mode\n */\nexport const TOOLTIP_MIDNIGHT_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(10, 15, 30, 0.95)',\n backgroundGradient: 'rgba(20, 25, 50, 0.90)',\n borderColor: 'rgba(100, 120, 255, 0.25)',\n borderWidth: 1,\n borderRadius: 8,\n backdropBlur: 15,\n shadow: {\n color: 'rgba(50, 70, 150, 0.25)',\n offsetX: 0,\n offsetY: 4,\n blur: 20\n },\n \n // Typography\n fontFamily: 'Inter, system-ui, sans-serif',\n textColor: '#e0e8ff',\n textSecondaryColor: 'rgba(180, 190, 255, 0.6)',\n titleFontSize: 12,\n titleFontWeight: 600,\n contentFontSize: 11,\n lineHeight: 1.4,\n \n // Spacing\n padding: DEFAULT_PADDING,\n itemGap: 4,\n headerGap: 8,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 8,\n showHeaderSeparator: true,\n separatorColor: 'rgba(100, 120, 255, 0.15)',\n showArrow: true,\n arrowSize: 6\n};\n\n// ============================================\n// Electrochemistry Theme\n// ============================================\n\n/**\n * Electrochemistry Theme - Professional blue tones for scientific data\n */\nexport const TOOLTIP_ELECTROCHEM_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(8, 20, 40, 0.96)',\n backgroundGradient: 'rgba(15, 35, 60, 0.92)',\n borderColor: 'rgba(30, 136, 229, 0.35)',\n borderWidth: 1,\n borderRadius: 6,\n backdropBlur: 10,\n shadow: {\n color: 'rgba(30, 136, 229, 0.2)',\n offsetX: 0,\n offsetY: 4,\n blur: 16\n },\n \n // Typography\n fontFamily: '\"JetBrains Mono\", \"Fira Code\", monospace',\n textColor: '#bbdefb',\n textSecondaryColor: 'rgba(144, 202, 249, 0.7)',\n titleFontSize: 11,\n titleFontWeight: 600,\n contentFontSize: 11,\n lineHeight: 1.5,\n \n // Spacing\n padding: { top: 8, right: 10, bottom: 8, left: 10 },\n itemGap: 3,\n headerGap: 6,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 6,\n showHeaderSeparator: true,\n separatorColor: 'rgba(30, 136, 229, 0.2)',\n showArrow: true,\n arrowSize: 5\n};\n\n// ============================================\n// Neon Theme\n// ============================================\n\n/**\n * Neon Theme - Vibrant glowing effect for futuristic UIs\n */\nexport const TOOLTIP_NEON_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(0, 0, 0, 0.92)',\n borderColor: '#00ffff',\n borderWidth: 1,\n borderRadius: 4,\n backdropBlur: 0,\n shadow: {\n color: 'rgba(0, 255, 255, 0.35)',\n offsetX: 0,\n offsetY: 0,\n blur: 20\n },\n \n // Typography\n fontFamily: '\"Orbitron\", \"Exo 2\", sans-serif',\n textColor: '#00ffff',\n textSecondaryColor: 'rgba(0, 255, 255, 0.6)',\n titleFontSize: 11,\n titleFontWeight: 700,\n contentFontSize: 10,\n lineHeight: 1.4,\n \n // Spacing\n padding: { top: 8, right: 12, bottom: 8, left: 12 },\n itemGap: 4,\n headerGap: 6,\n \n // Decorations\n showSeriesIndicator: true,\n seriesIndicatorSize: 6,\n showHeaderSeparator: true,\n separatorColor: 'rgba(0, 255, 255, 0.3)',\n showArrow: false,\n arrowSize: 0\n};\n\n// ============================================\n// Minimal Theme\n// ============================================\n\n/**\n * Minimal Theme - Ultra-compact with no decorations\n */\nexport const TOOLTIP_MINIMAL_THEME: TooltipTheme = {\n // Container\n backgroundColor: 'rgba(30, 35, 45, 0.9)',\n borderColor: 'transparent',\n borderWidth: 0,\n borderRadius: 4,\n backdropBlur: 8,\n shadow: {\n color: 'rgba(0, 0, 0, 0.3)',\n offsetX: 0,\n offsetY: 2,\n blur: 8\n },\n \n // Typography\n fontFamily: 'Inter, system-ui, sans-serif',\n textColor: '#ffffff',\n textSecondaryColor: 'rgba(255, 255, 255, 0.7)',\n titleFontSize: 10,\n titleFontWeight: 500,\n contentFontSize: 10,\n lineHeight: 1.3,\n \n // Spacing\n padding: { top: 6, right: 8, bottom: 6, left: 8 },\n itemGap: 2,\n headerGap: 4,\n \n // Decorations\n showSeriesIndicator: false,\n seriesIndicatorSize: 0,\n showHeaderSeparator: false,\n separatorColor: 'transparent',\n showArrow: false,\n arrowSize: 0\n};\n\n// ============================================\n// Theme Utilities\n// ============================================\n\n/** Available tooltip theme names */\nexport type TooltipThemeName = \n | 'dark' \n | 'light' \n | 'glass' \n | 'midnight' \n | 'electrochemistry' \n | 'neon' \n | 'minimal';\n\n/** Theme registry */\nexport const TOOLTIP_THEMES: Record<TooltipThemeName, TooltipTheme> = {\n dark: TOOLTIP_DARK_THEME,\n light: TOOLTIP_LIGHT_THEME,\n glass: TOOLTIP_GLASS_THEME,\n midnight: TOOLTIP_MIDNIGHT_THEME,\n electrochemistry: TOOLTIP_ELECTROCHEM_THEME,\n neon: TOOLTIP_NEON_THEME,\n minimal: TOOLTIP_MINIMAL_THEME\n};\n\n/**\n * Get a tooltip theme by name\n */\nexport function getTooltipTheme(name: TooltipThemeName | string): TooltipTheme {\n const theme = TOOLTIP_THEMES[name as TooltipThemeName];\n if (!theme) {\n console.warn(`[Tooltip] Unknown theme \"${name}\", using dark`);\n return TOOLTIP_DARK_THEME;\n }\n return theme;\n}\n\n/**\n * Create a custom tooltip theme by merging with a base theme\n */\nexport function createTooltipTheme(\n base: TooltipTheme | TooltipThemeName,\n overrides: Partial<TooltipTheme>\n): TooltipTheme {\n const baseTheme = typeof base === 'string' ? getTooltipTheme(base) : base;\n \n return {\n ...baseTheme,\n ...overrides,\n padding: { ...baseTheme.padding, ...overrides.padding },\n shadow: { ...baseTheme.shadow, ...overrides.shadow }\n };\n}\n\n/**\n * Map chart theme name to matching tooltip theme\n */\nexport function getTooltipThemeForChartTheme(chartThemeName: string): TooltipTheme {\n switch (chartThemeName.toLowerCase()) {\n case 'light':\n return TOOLTIP_LIGHT_THEME;\n case 'midnight':\n return TOOLTIP_MIDNIGHT_THEME;\n case 'electrochemistry':\n case 'electrochem':\n return TOOLTIP_ELECTROCHEM_THEME;\n case 'dark':\n default:\n return TOOLTIP_DARK_THEME;\n }\n}\n\n/** Default tooltip theme */\nexport const DEFAULT_TOOLTIP_THEME = TOOLTIP_DARK_THEME;\n","/**\n * Tooltip Positioner - Smart positioning algorithms\n * \n * Handles intelligent tooltip positioning with:\n * - Automatic edge avoidance\n * - Flipping when space is limited\n * - Arrow positioning\n * - Constraint handling\n * \n * @module tooltip/TooltipPositioner\n */\n\nimport type { PlotArea } from '../../../types';\nimport type {\n TooltipPosition,\n TooltipMeasurement,\n TooltipPlacement,\n ArrowPosition\n} from './types';\n\nexport interface PositionerConfig {\n /** Offset from target point */\n offset: { x: number; y: number };\n /** Preferred placement */\n preferredPosition: TooltipPlacement;\n /** Keep within plot area */\n constrainToPlotArea: boolean;\n /** Keep within container */\n constrainToContainer: boolean;\n /** Flip if not enough space */\n autoFlip: boolean;\n /** Show arrow pointing to target */\n showArrow: boolean;\n /** Arrow size */\n arrowSize: number;\n}\n\nexport const DEFAULT_POSITIONER_CONFIG: PositionerConfig = {\n offset: { x: 12, y: 12 },\n preferredPosition: 'auto',\n constrainToPlotArea: true,\n constrainToContainer: true,\n autoFlip: true,\n showArrow: true,\n arrowSize: 6\n};\n\n/**\n * TooltipPositioner calculates optimal tooltip positions\n */\nexport class TooltipPositioner {\n private config: PositionerConfig;\n private containerWidth: number = 0;\n private containerHeight: number = 0;\n private plotArea: PlotArea | null = null;\n\n constructor(config: Partial<PositionerConfig> = {}) {\n this.config = { ...DEFAULT_POSITIONER_CONFIG, ...config };\n }\n\n /**\n * Update container dimensions\n */\n setContainerSize(width: number, height: number): void {\n this.containerWidth = width;\n this.containerHeight = height;\n }\n\n /**\n * Update plot area bounds\n */\n setPlotArea(plotArea: PlotArea): void {\n this.plotArea = plotArea;\n }\n\n /**\n * Update configuration\n */\n configure(config: Partial<PositionerConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n /**\n * Calculate optimal tooltip position\n * \n * @param targetX - Target X coordinate (where tooltip points to)\n * @param targetY - Target Y coordinate\n * @param measurement - Tooltip dimensions\n * @returns Calculated position with arrow configuration\n */\n calculatePosition(\n targetX: number,\n targetY: number,\n measurement: TooltipMeasurement\n ): TooltipPosition {\n const { offset, preferredPosition, autoFlip, showArrow, arrowSize } = this.config;\n \n // Total dimensions including padding\n const totalWidth = measurement.width + measurement.padding.left + measurement.padding.right;\n const totalHeight = measurement.height + measurement.padding.top + measurement.padding.bottom;\n \n // Determine best position\n let position = this.determinePosition(\n targetX, \n targetY, \n totalWidth, \n totalHeight, \n preferredPosition\n );\n \n // Calculate initial coordinates based on position\n let { x, y, arrowPosition } = this.calculateCoordinates(\n targetX,\n targetY,\n totalWidth,\n totalHeight,\n position,\n offset,\n showArrow ? arrowSize : 0\n );\n \n let wasFlipped = false;\n \n // Check if we need to flip\n if (autoFlip && !this.fitsInBounds(x, y, totalWidth, totalHeight)) {\n const flippedPosition = this.flipPosition(position);\n const flipped = this.calculateCoordinates(\n targetX,\n targetY,\n totalWidth,\n totalHeight,\n flippedPosition,\n offset,\n showArrow ? arrowSize : 0\n );\n \n // Use flipped if it fits better\n if (this.fitsInBounds(flipped.x, flipped.y, totalWidth, totalHeight)) {\n x = flipped.x;\n y = flipped.y;\n arrowPosition = flipped.arrowPosition;\n wasFlipped = true;\n }\n }\n \n // Constrain to bounds\n const constrained = this.constrainToBounds(x, y, totalWidth, totalHeight);\n \n // Calculate arrow offset based on how much we shifted\n let arrowOffset = 0;\n if (showArrow) {\n if (arrowPosition === 'top' || arrowPosition === 'bottom') {\n // Arrow on horizontal edge - calculate X offset\n const idealArrowX = targetX - constrained.x;\n arrowOffset = Math.max(arrowSize + 4, Math.min(totalWidth - arrowSize - 4, idealArrowX));\n } else if (arrowPosition === 'left' || arrowPosition === 'right') {\n // Arrow on vertical edge - calculate Y offset \n const idealArrowY = targetY - constrained.y;\n arrowOffset = Math.max(arrowSize + 4, Math.min(totalHeight - arrowSize - 4, idealArrowY));\n }\n }\n \n return {\n x: constrained.x,\n y: constrained.y,\n arrowPosition: showArrow ? arrowPosition : 'none',\n arrowOffset,\n wasFlipped\n };\n }\n\n /**\n * Determine best position based on available space\n */\n private determinePosition(\n targetX: number,\n targetY: number,\n width: number,\n height: number,\n preferred: TooltipPlacement\n ): 'top' | 'bottom' | 'left' | 'right' {\n if (preferred !== 'auto') {\n return preferred;\n }\n \n // Calculate available space in each direction\n const bounds = this.getConstraintBounds();\n \n const spaceTop = targetY - bounds.top;\n const spaceBottom = bounds.bottom - targetY;\n const spaceLeft = targetX - bounds.left;\n const spaceRight = bounds.right - targetX;\n \n // Prefer vertical placement (top/bottom) for better readability\n const canFitTop = spaceTop >= height + this.config.offset.y;\n const canFitBottom = spaceBottom >= height + this.config.offset.y;\n const canFitRight = spaceRight >= width + this.config.offset.x;\n const canFitLeft = spaceLeft >= width + this.config.offset.x;\n \n // Priority: top > bottom > right > left\n if (canFitTop && spaceTop >= spaceBottom) return 'top';\n if (canFitBottom) return 'bottom';\n if (canFitRight && spaceRight >= spaceLeft) return 'right';\n if (canFitLeft) return 'left';\n \n // Default to position with most space\n const spaces = [\n { pos: 'top' as const, space: spaceTop },\n { pos: 'bottom' as const, space: spaceBottom },\n { pos: 'right' as const, space: spaceRight },\n { pos: 'left' as const, space: spaceLeft }\n ];\n \n return spaces.sort((a, b) => b.space - a.space)[0].pos;\n }\n\n /**\n * Calculate tooltip coordinates for a given position\n */\n private calculateCoordinates(\n targetX: number,\n targetY: number,\n width: number,\n height: number,\n position: 'top' | 'bottom' | 'left' | 'right',\n offset: { x: number; y: number },\n arrowSize: number\n ): { x: number; y: number; arrowPosition: ArrowPosition } {\n let x: number;\n let y: number;\n let arrowPosition: ArrowPosition;\n \n switch (position) {\n case 'top':\n x = targetX - width / 2;\n y = targetY - height - offset.y - arrowSize;\n arrowPosition = 'bottom';\n break;\n \n case 'bottom':\n x = targetX - width / 2;\n y = targetY + offset.y + arrowSize;\n arrowPosition = 'top';\n break;\n \n case 'right':\n x = targetX + offset.x + arrowSize;\n y = targetY - height / 2;\n arrowPosition = 'left';\n break;\n \n case 'left':\n x = targetX - width - offset.x - arrowSize;\n y = targetY - height / 2;\n arrowPosition = 'right';\n break;\n }\n \n return { x, y, arrowPosition };\n }\n\n /**\n * Get the opposite position for flipping\n */\n private flipPosition(\n position: 'top' | 'bottom' | 'left' | 'right'\n ): 'top' | 'bottom' | 'left' | 'right' {\n switch (position) {\n case 'top': return 'bottom';\n case 'bottom': return 'top';\n case 'left': return 'right';\n case 'right': return 'left';\n }\n }\n\n /**\n * Check if tooltip fits within bounds\n */\n private fitsInBounds(x: number, y: number, width: number, height: number): boolean {\n const bounds = this.getConstraintBounds();\n \n return (\n x >= bounds.left &&\n y >= bounds.top &&\n x + width <= bounds.right &&\n y + height <= bounds.bottom\n );\n }\n\n /**\n * Constrain position to stay within bounds\n */\n private constrainToBounds(\n x: number,\n y: number,\n width: number,\n height: number\n ): { x: number; y: number } {\n const bounds = this.getConstraintBounds();\n const margin = 4; // Small margin from edges\n \n let constrainedX = x;\n let constrainedY = y;\n \n // Horizontal constraints\n if (constrainedX < bounds.left + margin) {\n constrainedX = bounds.left + margin;\n } else if (constrainedX + width > bounds.right - margin) {\n constrainedX = bounds.right - width - margin;\n }\n \n // Vertical constraints\n if (constrainedY < bounds.top + margin) {\n constrainedY = bounds.top + margin;\n } else if (constrainedY + height > bounds.bottom - margin) {\n constrainedY = bounds.bottom - height - margin;\n }\n \n return { x: constrainedX, y: constrainedY };\n }\n\n /**\n * Get the bounds to constrain tooltip within\n */\n private getConstraintBounds(): { top: number; left: number; right: number; bottom: number } {\n let bounds = {\n top: 0,\n left: 0,\n right: this.containerWidth,\n bottom: this.containerHeight\n };\n \n if (this.config.constrainToPlotArea && this.plotArea) {\n bounds = {\n top: Math.max(bounds.top, this.plotArea.y),\n left: Math.max(bounds.left, this.plotArea.x),\n right: Math.min(bounds.right, this.plotArea.x + this.plotArea.width),\n bottom: Math.min(bounds.bottom, this.plotArea.y + this.plotArea.height)\n };\n }\n \n return bounds;\n }\n\n /**\n * Calculate position for crosshair tooltip (follows cursor vertically)\n */\n calculateCrosshairPosition(\n cursorX: number,\n cursorY: number,\n measurement: TooltipMeasurement\n ): TooltipPosition {\n const { offset } = this.config;\n const bounds = this.getConstraintBounds();\n \n const totalWidth = measurement.width + measurement.padding.left + measurement.padding.right;\n const totalHeight = measurement.height + measurement.padding.top + measurement.padding.bottom;\n \n // Position to the right of cursor by default\n let x = cursorX + offset.x;\n let arrowPosition: ArrowPosition = 'left';\n \n // Flip to left if not enough space on right\n if (x + totalWidth > bounds.right - 4) {\n x = cursorX - totalWidth - offset.x;\n arrowPosition = 'right';\n }\n \n // Center vertically on cursor\n let y = cursorY - totalHeight / 2;\n \n // Constrain vertically\n y = Math.max(bounds.top + 4, Math.min(bounds.bottom - totalHeight - 4, y));\n \n // Calculate arrow offset (centered on cursor Y)\n const arrowOffset = cursorY - y;\n \n return {\n x,\n y,\n arrowPosition,\n arrowOffset: Math.max(8, Math.min(totalHeight - 8, arrowOffset)),\n wasFlipped: arrowPosition === 'right'\n };\n }\n}\n\n// Export singleton-like factory\nexport function createTooltipPositioner(\n config?: Partial<PositionerConfig>\n): TooltipPositioner {\n return new TooltipPositioner(config);\n}\n","/**\n * Tooltip Renderer - Canvas 2D tooltip rendering\n * \n * High-performance Canvas rendering for tooltips with:\n * - Glassmorphism effects\n * - Smooth gradients and shadows\n * - Arrow/pointer drawing\n * - Animation support\n * \n * @module tooltip/TooltipRenderer\n */\n\nimport type {\n TooltipData,\n TooltipPosition,\n TooltipTheme,\n TooltipTemplate,\n ArrowPosition\n} from './types';\n\n/**\n * TooltipRenderer handles all Canvas 2D rendering for tooltips\n */\nexport class TooltipRenderer {\n private ctx: CanvasRenderingContext2D;\n private theme: TooltipTheme;\n\n constructor(ctx: CanvasRenderingContext2D, theme: TooltipTheme) {\n this.ctx = ctx;\n this.theme = theme;\n }\n\n /**\n * Update the theme\n */\n setTheme(theme: TooltipTheme): void {\n this.theme = theme;\n }\n\n /**\n * Render a tooltip with the given template\n */\n render<T extends TooltipData>(\n data: T,\n position: TooltipPosition,\n template: TooltipTemplate<T>\n ): void {\n const measurement = template.measure(this.ctx, data, this.theme);\n const totalWidth = measurement.width + measurement.padding.left + measurement.padding.right;\n const totalHeight = measurement.height + measurement.padding.top + measurement.padding.bottom;\n\n this.ctx.save();\n\n // Draw background with effects\n this.drawBackground(position.x, position.y, totalWidth, totalHeight, position.arrowPosition || 'none');\n\n // Draw arrow if enabled\n if (position.arrowPosition && position.arrowPosition !== 'none') {\n this.drawArrow(\n position.x,\n position.y,\n totalWidth,\n totalHeight,\n position.arrowPosition,\n position.arrowOffset || 0\n );\n }\n\n // Let template render content\n template.render(this.ctx, data, position, measurement, this.theme);\n\n this.ctx.restore();\n }\n\n\n\n /**\n * Draw tooltip background with all effects\n */\n private drawBackground(\n x: number,\n y: number,\n width: number,\n height: number,\n _arrowPosition: ArrowPosition\n ): void {\n const { ctx, theme } = this;\n const r = theme.borderRadius;\n\n ctx.save();\n\n // Shadow\n if (theme.shadow.blur > 0) {\n ctx.shadowColor = theme.shadow.color;\n ctx.shadowOffsetX = theme.shadow.offsetX;\n ctx.shadowOffsetY = theme.shadow.offsetY;\n ctx.shadowBlur = theme.shadow.blur;\n }\n\n // Create rounded rect path\n ctx.beginPath();\n this.roundRect(x, y, width, height, r);\n\n // Fill with gradient or solid color\n if (theme.backgroundGradient) {\n const gradient = ctx.createLinearGradient(x, y, x, y + height);\n gradient.addColorStop(0, theme.backgroundColor);\n gradient.addColorStop(1, theme.backgroundGradient);\n ctx.fillStyle = gradient;\n } else {\n ctx.fillStyle = theme.backgroundColor;\n }\n ctx.fill();\n\n // Reset shadow for border\n ctx.shadowColor = 'transparent';\n\n // Border\n if (theme.borderWidth > 0) {\n ctx.strokeStyle = theme.borderColor;\n ctx.lineWidth = theme.borderWidth;\n ctx.stroke();\n }\n\n ctx.restore();\n }\n\n /**\n * Draw arrow pointing to target\n */\n private drawArrow(\n x: number,\n y: number,\n width: number,\n height: number,\n arrowPosition: ArrowPosition,\n arrowOffset: number\n ): void {\n const { ctx, theme } = this;\n const size = theme.arrowSize;\n\n if (size <= 0 || arrowPosition === 'none') return;\n\n ctx.save();\n ctx.fillStyle = theme.backgroundColor;\n ctx.strokeStyle = theme.borderColor;\n ctx.lineWidth = theme.borderWidth;\n\n ctx.beginPath();\n\n switch (arrowPosition) {\n case 'top':\n // Arrow pointing up (tooltip below target)\n const topX = x + arrowOffset;\n ctx.moveTo(topX - size, y);\n ctx.lineTo(topX, y - size);\n ctx.lineTo(topX + size, y);\n break;\n\n case 'bottom':\n // Arrow pointing down (tooltip above target)\n const bottomX = x + arrowOffset;\n const bottomY = y + height;\n ctx.moveTo(bottomX - size, bottomY);\n ctx.lineTo(bottomX, bottomY + size);\n ctx.lineTo(bottomX + size, bottomY);\n break;\n\n case 'left':\n // Arrow pointing left (tooltip right of target)\n const leftY = y + arrowOffset;\n ctx.moveTo(x, leftY - size);\n ctx.lineTo(x - size, leftY);\n ctx.lineTo(x, leftY + size);\n break;\n\n case 'right':\n // Arrow pointing right (tooltip left of target)\n const rightX = x + width;\n const rightY = y + arrowOffset;\n ctx.moveTo(rightX, rightY - size);\n ctx.lineTo(rightX + size, rightY);\n ctx.lineTo(rightX, rightY + size);\n break;\n }\n\n ctx.closePath();\n ctx.fill();\n\n if (theme.borderWidth > 0) {\n ctx.stroke();\n }\n\n ctx.restore();\n }\n\n /**\n * Draw a rounded rectangle path\n */\n private roundRect(x: number, y: number, width: number, height: number, radius: number): void {\n const { ctx } = this;\n const r = Math.min(radius, width / 2, height / 2);\n\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + width - r, y);\n ctx.arcTo(x + width, y, x + width, y + r, r);\n ctx.lineTo(x + width, y + height - r);\n ctx.arcTo(x + width, y + height, x + width - r, y + height, r);\n ctx.lineTo(x + r, y + height);\n ctx.arcTo(x, y + height, x, y + height - r, r);\n ctx.lineTo(x, y + r);\n ctx.arcTo(x, y, x + r, y, r);\n ctx.closePath();\n }\n\n /**\n * Draw a horizontal separator line\n */\n drawSeparator(x: number, y: number, width: number): void {\n const { ctx, theme } = this;\n\n if (!theme.showHeaderSeparator) return;\n\n ctx.save();\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + width, y);\n ctx.stroke();\n ctx.restore();\n }\n\n /**\n * Draw a series color indicator (small circle or square)\n */\n drawSeriesIndicator(x: number, y: number, color: string): void {\n const { ctx, theme } = this;\n\n if (!theme.showSeriesIndicator) return;\n\n const size = theme.seriesIndicatorSize;\n const radius = size / 2;\n\n ctx.save();\n ctx.fillStyle = color;\n ctx.beginPath();\n ctx.arc(x + radius, y, radius, 0, Math.PI * 2);\n ctx.fill();\n ctx.restore();\n }\n\n /**\n * Measure text width\n */\n measureText(text: string, fontSize: number, fontWeight: number | string = 400): number {\n const { ctx, theme } = this;\n ctx.font = `${fontWeight} ${fontSize}px ${theme.fontFamily}`;\n return ctx.measureText(text).width;\n }\n\n /**\n * Draw text with theme styling\n */\n drawText(\n text: string,\n x: number,\n y: number,\n options: {\n fontSize?: number;\n fontWeight?: number | string;\n color?: string;\n align?: CanvasTextAlign;\n baseline?: CanvasTextBaseline;\n } = {}\n ): void {\n const { ctx, theme } = this;\n const {\n fontSize = theme.contentFontSize,\n fontWeight = 400,\n color = theme.textColor,\n align = 'left',\n baseline = 'top'\n } = options;\n\n ctx.save();\n ctx.font = `${fontWeight} ${fontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = color;\n ctx.textAlign = align;\n ctx.textBaseline = baseline;\n ctx.fillText(text, x, y);\n ctx.restore();\n }\n\n /**\n * Draw a label-value pair\n */\n drawLabelValue(\n x: number,\n y: number,\n label: string,\n value: string,\n maxWidth: number\n ): void {\n const { theme } = this;\n\n // Draw label (secondary color)\n this.drawText(label, x, y, {\n color: theme.textSecondaryColor,\n fontSize: theme.contentFontSize\n });\n\n // Draw value (primary color, right-aligned)\n this.drawText(value, x + maxWidth, y, {\n color: theme.textColor,\n fontSize: theme.contentFontSize,\n align: 'right'\n });\n }\n\n /**\n * Get theme for external use\n */\n getTheme(): TooltipTheme {\n return this.theme;\n }\n}\n\n/**\n * Create a tooltip renderer\n */\nexport function createTooltipRenderer(\n ctx: CanvasRenderingContext2D,\n theme: TooltipTheme\n): TooltipRenderer {\n return new TooltipRenderer(ctx, theme);\n}\n","/**\n * Shared tooltip value formatting — delegates to axisFormat when axis context exists.\n */\nimport type { DataPointTooltip, CrosshairTooltip } from \"./types\";\nimport { formatTooltipX, formatTooltipY } from \"../../../core/format/axisFormat\";\n\nexport function formatDataPointX(data: DataPointTooltip): string {\n if (data.axisFormat) return formatTooltipX(data.dataX, data.axisFormat);\n return formatFallbackNumber(data.dataX);\n}\n\nexport function formatDataPointY(data: DataPointTooltip): string {\n if (data.axisFormat) return formatTooltipY(data.dataY, data.axisFormat);\n return formatFallbackNumber(data.dataY);\n}\n\nexport function formatCrosshairX(data: CrosshairTooltip): string {\n if (data.axisFormat) return formatTooltipX(data.dataX, data.axisFormat);\n return formatFallbackNumber(data.dataX);\n}\n\nexport function formatCrosshairY(value: number, data: CrosshairTooltip): string {\n if (data.axisFormat) return formatTooltipY(value, data.axisFormat);\n return formatFallbackNumber(value);\n}\n\nfunction formatFallbackNumber(value: number | null | undefined): string {\n if (value === null || value === undefined || isNaN(value)) return \"N/A\";\n const absVal = Math.abs(value);\n if (absVal === 0) return \"0\";\n if (absVal < 0.0001 || absVal >= 10000) return value.toExponential(2);\n if (absVal < 0.01) return value.toPrecision(4);\n if (absVal < 1) return value.toFixed(4);\n if (absVal < 100) return value.toFixed(3);\n return value.toFixed(1);\n}\n\nexport function formatCompactValue(data: DataPointTooltip, axis: \"x\" | \"y\"): string {\n const value = axis === \"x\" ? data.dataX : data.dataY;\n if (data.axisFormat) {\n return axis === \"x\"\n ? formatTooltipX(value, data.axisFormat)\n : formatTooltipY(value, data.axisFormat);\n }\n if (value === null || value === undefined || isNaN(value)) return \"N/A\";\n const absVal = Math.abs(value);\n if (absVal === 0) return \"0\";\n if (absVal >= 1e9) return (value / 1e9).toFixed(1) + \"G\";\n if (absVal >= 1e6) return (value / 1e6).toFixed(1) + \"M\";\n if (absVal >= 1e3) return (value / 1e3).toFixed(1) + \"k\";\n if (absVal >= 1) return value.toFixed(2);\n if (absVal >= 1e-3) return (value * 1e3).toFixed(1) + \"m\";\n if (absVal >= 1e-6) return (value * 1e6).toFixed(1) + \"µ\";\n if (absVal >= 1e-9) return (value * 1e9).toFixed(1) + \"n\";\n return value.toExponential(1);\n}\n","/**\n * Default Tooltip Template\n * \n * A clean, elegant template for data point tooltips with:\n * - Series color indicator\n * - Formatted X/Y values\n * - Optional error bars\n * - Cycle information\n * \n * @module tooltip/templates/DefaultTemplate\n */\n\nimport type {\n DataPointTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\nimport { formatDataPointX, formatDataPointY } from '../format';\n\nfunction formatValue(value: number | null | undefined, data?: DataPointTooltip, axis?: 'x' | 'y'): string {\n if (data && axis === 'x') return formatDataPointX(data);\n if (data && axis === 'y') return formatDataPointY(data);\n if (value === null || value === undefined || isNaN(value)) return \"N/A\";\n const absVal = Math.abs(value);\n if (absVal !== 0 && (absVal < 0.0001 || absVal >= 10000)) return value.toExponential(2);\n if (absVal < 0.01) return value.toPrecision(4);\n if (absVal < 1) return value.toFixed(4);\n if (absVal < 100) return value.toFixed(3);\n return value.toFixed(1);\n}\n\n/**\n * Default Data Point Template\n * \n * Visual layout:\n * ┌──────────────────────────┐\n * │ ● Series Name │\n * │ ─────────────────────── │\n * │ X: 0.500 │\n * │ Y: 1.234 │\n * │ ± Error: 0.05 │\n * └──────────────────────────┘\n */\nexport class DefaultTooltipTemplate implements TooltipTemplate<DataPointTooltip> {\n readonly id = 'default';\n readonly name = 'Default Data Point';\n readonly supportedTypes: TooltipType[] = ['datapoint'];\n\n // Cached measurements\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n // Create cache key\n const cacheKey = `${data.seriesId}-${data.dataIndex}-${data.dataX}-${data.dataY}`;\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Set up font for measurement\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n \n // Measure title (series name)\n const titleWidth = ctx.measureText(data.seriesName).width;\n \n // Set content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n // Format values\n const labelWidth = 35;\n const xValWidth = ctx.measureText(formatValue(data.dataX, data, 'x')).width;\n const yValWidth = ctx.measureText(formatValue(data.dataY, data, 'y')).width;\n \n // Measure content lines\n let contentWidth = labelWidth + Math.max(xValWidth, yValWidth);\n \n let contentHeight = theme.contentFontSize * theme.lineHeight * 2;\n \n // Add error info if present\n if (data.yError) {\n const errorText = `± ${formatValue(data.yError[0])} / ${formatValue(data.yError[1])}`;\n contentWidth = Math.max(contentWidth, ctx.measureText(errorText).width);\n contentHeight += theme.contentFontSize * theme.lineHeight;\n }\n \n // Add cycle info if present\n if (data.cycle !== undefined) {\n const cycleText = `Cycle: ${data.cycle}`;\n contentWidth = Math.max(contentWidth, ctx.measureText(cycleText).width);\n contentHeight += theme.contentFontSize * theme.lineHeight;\n }\n \n // Account for series indicator\n const indicatorWidth = theme.showSeriesIndicator \n ? theme.seriesIndicatorSize + 6 \n : 0;\n \n // Calculate total width\n const width = Math.max(titleWidth + indicatorWidth, contentWidth);\n \n // Calculate total height (title + separator + content)\n const height = theme.titleFontSize * theme.lineHeight + theme.headerGap + contentHeight;\n \n this.cachedMeasurement = {\n width: width + 2, // Tiny buffer\n height: height + 4,\n padding: theme.padding,\n arrow: theme.showArrow ? { width: theme.arrowSize * 2, height: theme.arrowSize } : undefined\n };\n this.cachedKey = cacheKey;\n \n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { x, y } = position;\n const { padding } = theme;\n \n // Start position for content\n let currentX = x + padding.left;\n let currentY = y + padding.top;\n \n // Explicitly set alignment to avoid inheritance issues\n ctx.save();\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n \n // Draw series indicator\n if (theme.showSeriesIndicator) {\n const indicatorY = currentY + theme.titleFontSize / 2;\n ctx.save();\n ctx.fillStyle = data.seriesColor;\n ctx.beginPath();\n ctx.arc(currentX + theme.seriesIndicatorSize / 2, indicatorY, theme.seriesIndicatorSize / 2, 0, Math.PI * 2);\n ctx.fill();\n ctx.restore();\n \n currentX += theme.seriesIndicatorSize + 6;\n }\n \n // Draw title (series name)\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n ctx.fillText(data.seriesName, currentX, currentY);\n \n currentY += theme.titleFontSize * theme.lineHeight + 2; // Extra space\n \n // Draw separator\n if (theme.showHeaderSeparator) {\n const separatorWidth = measurement.width;\n \n ctx.save();\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.globalAlpha = 0.4; // Softer separator\n ctx.beginPath();\n ctx.moveTo(x + padding.left, currentY + theme.headerGap / 2);\n ctx.lineTo(x + padding.left + separatorWidth, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.restore();\n }\n \n currentY += theme.headerGap + 2; // Better gap\n currentX = x + padding.left; // Reset X\n \n // Draw content\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n // X value\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('X:', currentX, currentY);\n ctx.fillStyle = theme.textColor;\n const labelWidth = 35; // Fixed label width for better alignment\n ctx.fillText(formatValue(data.dataX, data, 'x'), currentX + labelWidth, currentY);\n currentY += theme.contentFontSize * theme.lineHeight + 2;\n \n // Y value\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Y:', currentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.dataY, data, 'y'), currentX + labelWidth, currentY);\n currentY += theme.contentFontSize * theme.lineHeight + 2;\n \n // Error if present\n if (data.yError) {\n ctx.fillStyle = theme.textSecondaryColor;\n const errorText = `± ${formatValue(data.yError[0])} / +${formatValue(data.yError[1])}`;\n ctx.fillText(errorText, currentX, currentY);\n currentY += theme.contentFontSize * theme.lineHeight;\n }\n \n // Cycle if present\n if (data.cycle !== undefined) {\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Cycle:', currentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(String(data.cycle), currentX + 45, currentY);\n }\n \n ctx.restore();\n }\n}\n\n// Export singleton instance\nexport const defaultTooltipTemplate = new DefaultTooltipTemplate();\n","/**\n * Minimal Tooltip Template\n * \n * Ultra-compact template showing only essential values.\n * Perfect for dashboards with limited space.\n * \n * @module tooltip/templates/MinimalTemplate\n */\n\nimport type {\n DataPointTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\nimport { formatCompactValue } from '../format';\n\n/**\n * Minimal Template\n * \n * Visual layout:\n * ┌───────────────────╮\n * │ 0.500 ▪ 1.23µA │\n * ╰───────────────────╯\n */\nexport class MinimalTooltipTemplate implements TooltipTemplate<DataPointTooltip> {\n readonly id = 'minimal';\n readonly name = 'Minimal';\n readonly supportedTypes: TooltipType[] = ['datapoint'];\n\n // Cached measurements\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n // Cache key\n const cacheKey = `${data.seriesId}-${data.dataIndex}-${data.dataX}-${data.dataY}-${theme.fontFamily}`;\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Set font for measurement\n ctx.font = `${theme.contentFontSize}px ${theme.fontFamily}`;\n \n // Create compact text\n const text = `${formatCompactValue(data, 'x')} ▪ ${formatCompactValue(data, 'y')}`;\n const textWidth = ctx.measureText(text).width;\n \n this.cachedMeasurement = {\n width: textWidth,\n height: theme.contentFontSize * theme.lineHeight,\n padding: {\n top: 6,\n right: 8,\n bottom: 6,\n left: 8\n }\n };\n this.cachedKey = cacheKey;\n \n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { padding } = measurement;\n const x = position.x + padding.left;\n const y = position.y + padding.top;\n \n // Create compact text\n const xValue = formatCompactValue(data, 'x');\n const yValue = formatCompactValue(data, 'y');\n \n ctx.save();\n ctx.font = `${theme.contentFontSize}px ${theme.fontFamily}`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n \n // Draw X value\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText(xValue, x, y);\n \n // Draw separator\n const xWidth = ctx.measureText(xValue).width;\n ctx.fillStyle = data.seriesColor;\n ctx.fillText(' ▪ ', x + xWidth, y);\n \n // Draw Y value\n const sepWidth = ctx.measureText(' ▪ ').width;\n ctx.fillStyle = theme.textColor;\n ctx.fillText(yValue, x + xWidth + sepWidth, y);\n \n ctx.restore();\n }\n}\n\n// Export singleton instance\nexport const minimalTooltipTemplate = new MinimalTooltipTemplate();\n","/**\n * Crosshair Tooltip Template\n *\n * Multi-series template for crosshair tooltips showing\n * interpolated values for all visible series at cursor position.\n *\n * @module tooltip/templates/CrosshairTemplate\n */\n\nimport type {\n CrosshairTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType,\n} from \"../types\";\nimport { formatCrosshairX, formatCrosshairY } from \"../format\";\n\n// Constants for spacing and layout\nconst SPACING = {\n INDICATOR_MARGIN: 8,\n MIN_LABEL_WIDTH: 60,\n LINE_SPACING: 2,\n SAFETY_BUFFER: 4,\n HEADER_SPACING: 2,\n GAP_SPACING: 2,\n} as const;\n\n/**\n * Formatted series data for caching\n */\ninterface FormattedSeriesData {\n name: string;\n value: string;\n color: string;\n isInterpolated: boolean;\n}\n\n/**\n * Crosshair Multi-Series Template\n *\n * Visual layout:\n * ┌──────────────────────────────────╮\n * │ ⌖ X = 0.234 │\n * ├──────────────────────────────────┤\n * │ ● Forward: 45.67 µA │\n * │ ● Reverse: -32.10 µA │\n * │ ○ Baseline: 0.05 µA │\n * ╰──────────────────────────────────╯\n */\nexport class CrosshairTooltipTemplate implements TooltipTemplate<CrosshairTooltip> {\n readonly id = \"crosshair\";\n readonly name = \"Multi-Series Crosshair\";\n readonly supportedTypes: TooltipType[] = [\"crosshair\"];\n\n // Cached measurements\n private cachedKey: string = \"\";\n private cachedMeasurement: TooltipMeasurement | null = null;\n private formattedData: {\n header: string;\n series: FormattedSeriesData[];\n } | null = null;\n\n /**\n * Generate cache key from data and theme\n */\n private getCacheKey(data: CrosshairTooltip, theme: TooltipTheme): string {\n const seriesHash = data.interpolatedValues\n .map((s) => `${s.seriesName}-${s.y}`)\n .join(\"|\");\n \n return [\n data.dataX,\n seriesHash,\n theme.fontFamily,\n theme.titleFontSize,\n theme.contentFontSize,\n theme.showSeriesIndicator,\n theme.seriesIndicatorSize,\n `${theme.padding.top}-${theme.padding.right}-${theme.padding.bottom}-${theme.padding.left}`,\n ].join(\":\");\n }\n\n /**\n * Format data for rendering\n */\n private formatData(data: CrosshairTooltip): {\n header: string;\n series: FormattedSeriesData[];\n } {\n return {\n header: `⌖ X = ${formatCrosshairX(data)}`,\n series: data.interpolatedValues.map((s) => ({\n name: s.seriesName,\n value: formatCrosshairY(s.y, data),\n color: s.seriesColor,\n isInterpolated: s.isInterpolated,\n })),\n };\n }\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: CrosshairTooltip,\n theme: TooltipTheme,\n ): TooltipMeasurement {\n // Validate input\n if (!data.interpolatedValues || data.interpolatedValues.length === 0) {\n return {\n width: 100,\n height: theme.titleFontSize * theme.lineHeight,\n padding: theme.padding,\n };\n }\n\n // Check cache\n const cacheKey = this.getCacheKey(data, theme);\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Format data once\n this.formattedData = this.formatData(data);\n\n // Set title font\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n\n // Measure header\n let maxWidth = ctx.measureText(this.formattedData.header).width;\n\n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n\n // Measure each series line\n const indicatorWidth = theme.showSeriesIndicator\n ? theme.seriesIndicatorSize + SPACING.INDICATOR_MARGIN\n : 0;\n\n for (const series of this.formattedData.series) {\n const nameWidth = ctx.measureText(`${series.name}:`).width;\n const valWidth = ctx.measureText(series.value).width;\n const lineWidth =\n indicatorWidth + Math.max(nameWidth, SPACING.MIN_LABEL_WIDTH) + valWidth;\n maxWidth = Math.max(maxWidth, lineWidth);\n }\n\n // Calculate height\n const headerHeight = theme.titleFontSize * theme.lineHeight;\n const seriesCount = this.formattedData.series.length;\n const contentHeight =\n seriesCount * (theme.contentFontSize * theme.lineHeight + SPACING.LINE_SPACING);\n\n this.cachedMeasurement = {\n width: maxWidth + SPACING.SAFETY_BUFFER,\n height: headerHeight + theme.headerGap + contentHeight,\n padding: theme.padding,\n };\n this.cachedKey = cacheKey;\n\n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: CrosshairTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme,\n ): void {\n // Validate input\n if (!data.interpolatedValues || data.interpolatedValues.length === 0) {\n return;\n }\n\n // Use cached formatted data if available\n const formatted = this.formattedData || this.formatData(data);\n\n const { x, y } = position;\n const { padding } = theme;\n\n let currentY = y + padding.top;\n const contentX = x + padding.left;\n\n // Draw header: \"⌖ X = value\"\n ctx.save();\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"top\";\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n\n ctx.fillText(formatted.header, contentX, currentY);\n\n currentY += theme.titleFontSize * theme.lineHeight + SPACING.HEADER_SPACING;\n\n // Draw separator\n if (theme.showHeaderSeparator) {\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.globalAlpha = 0.4;\n ctx.beginPath();\n ctx.moveTo(contentX, currentY + theme.headerGap / 2);\n ctx.lineTo(contentX + measurement.width, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1.0;\n }\n\n currentY += theme.headerGap + SPACING.GAP_SPACING;\n\n // Draw each series\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n\n for (const series of formatted.series) {\n let itemX = contentX;\n\n // Series indicator\n if (theme.showSeriesIndicator && theme.seriesIndicatorSize > 0) {\n const indicatorY = currentY + theme.contentFontSize / 2;\n const radius = theme.seriesIndicatorSize / 2;\n\n ctx.save();\n ctx.beginPath();\n ctx.arc(itemX + radius, indicatorY, radius, 0, Math.PI * 2);\n\n if (series.isInterpolated) {\n ctx.strokeStyle = series.color;\n ctx.lineWidth = 1.5;\n ctx.stroke();\n } else {\n ctx.fillStyle = series.color;\n ctx.fill();\n }\n ctx.restore();\n\n itemX += theme.seriesIndicatorSize + SPACING.INDICATOR_MARGIN;\n }\n\n // Series name\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText(`${series.name}:`, itemX, currentY);\n\n const nameWidth = ctx.measureText(`${series.name}: `).width;\n const labelOffset = Math.max(nameWidth, SPACING.MIN_LABEL_WIDTH);\n\n // Series value\n ctx.fillStyle = theme.textColor;\n ctx.fillText(series.value, itemX + labelOffset, currentY);\n\n currentY += theme.contentFontSize * theme.lineHeight + SPACING.LINE_SPACING;\n }\n\n ctx.restore();\n }\n}\n\n// Export singleton instance\nexport const crosshairTooltipTemplate = new CrosshairTooltipTemplate();\n","/**\n * Heatmap Tooltip Template\n * \n * Specialized template for heatmap tooltips showing:\n * - Grid position\n * - Z value with color preview\n * - Scale information\n * \n * @module tooltip/templates/HeatmapTemplate\n */\n\nimport type {\n HeatmapTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\n\n/**\n * Format a number for display\n */\nfunction formatValue(value: number | null | undefined): string {\n if (value === null || value === undefined || isNaN(value)) {\n return \"N/A\";\n }\n\n const absVal = Math.abs(value);\n\n if (absVal === 0) return \"0\";\n if (absVal < 0.0001 || absVal >= 10000) {\n return value.toExponential(3);\n }\n if (absVal < 0.01) return value.toPrecision(4);\n if (absVal < 1) return value.toFixed(4);\n if (absVal < 100) return value.toFixed(3);\n return value.toFixed(2);\n}\n\n/**\n * Heatmap Template\n * \n * Visual layout:\n * ┌────────────────────────────╮\n * │ Grid [45, 128] │\n * │ ──────────────────────────│\n * │ ████ Value: 0.847 │\n * │ Min: 0.0 Max: 1.0 │\n * │ │\n * │ X: 100.0 Hz │\n * │ Y: 2.50 s │\n * ╰────────────────────────────╯\n */\nexport class HeatmapTooltipTemplate implements TooltipTemplate<HeatmapTooltip> {\n readonly id = 'heatmap';\n readonly name = 'Heatmap Value';\n readonly supportedTypes: TooltipType[] = ['heatmap'];\n\n // Color swatch dimensions\n private readonly swatchSize = 14;\n private readonly swatchGap = 8;\n\n // Cached measurements\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: HeatmapTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n // Cache key\n const cacheKey = `${data.seriesId}-${data.xIndex}-${data.yIndex}-${theme.fontFamily}-${theme.titleFontSize}`;\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Set title font\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n \n // Header: \"Grid [x, y]\"\n const headerText = `Grid [${data.xIndex}, ${data.yIndex}]`;\n let maxWidth = ctx.measureText(headerText).width;\n \n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n // Value line with color swatch (swatch + gap + text)\n const valueText = `Value: ${formatValue(data.zValue)}`;\n const valueWidth = this.swatchSize + this.swatchGap + ctx.measureText(valueText).width;\n maxWidth = Math.max(maxWidth, valueWidth);\n \n // Scale info\n if (data.colorScale) {\n const scaleText = `Min: ${formatValue(data.colorScale.min)} Max: ${formatValue(data.colorScale.max)}`;\n maxWidth = Math.max(maxWidth, this.swatchSize + this.swatchGap + ctx.measureText(scaleText).width);\n }\n \n // X/Y data values\n const xyLabelWidth = 25; // Adjusted to match fixed offset in render\n const dataXWidth = xyLabelWidth + ctx.measureText(formatValue(data.dataX)).width;\n const dataYWidth = xyLabelWidth + ctx.measureText(formatValue(data.dataY)).width;\n maxWidth = Math.max(maxWidth, dataXWidth, dataYWidth);\n \n // Calculate height\n const headerHeight = theme.titleFontSize * theme.lineHeight;\n const contentLines = data.colorScale ? 4 : 3; // value, (scale), X, Y\n const contentHeight = contentLines * theme.contentFontSize * theme.lineHeight;\n \n this.cachedMeasurement = {\n width: maxWidth + 4, // Small buffer\n height: headerHeight + theme.headerGap + contentHeight + theme.itemGap,\n padding: theme.padding\n };\n this.cachedKey = cacheKey;\n \n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: HeatmapTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { x, y } = position;\n const { padding } = theme;\n \n let currentY = y + padding.top;\n const contentX = x + padding.left;\n \n // Draw header: \"Grid [x, y]\"\n ctx.save();\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n \n const headerText = `Grid [${data.xIndex}, ${data.yIndex}]`;\n ctx.fillText(headerText, contentX, currentY);\n \n currentY += theme.titleFontSize * theme.lineHeight + 2;\n \n // Draw separator\n if (theme.showHeaderSeparator) {\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.globalAlpha = 0.4;\n ctx.beginPath();\n ctx.moveTo(contentX, currentY + theme.headerGap / 2);\n ctx.lineTo(contentX + measurement.width, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1.0;\n }\n \n currentY += theme.headerGap + 2;\n \n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n // Draw color swatch with value\n const swatchY = currentY + (theme.contentFontSize * theme.lineHeight - this.swatchSize) / 2;\n \n // Color swatch with border\n ctx.fillStyle = data.mappedColor || theme.textColor;\n ctx.fillRect(contentX, swatchY, this.swatchSize, this.swatchSize);\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.strokeRect(contentX, swatchY, this.swatchSize, this.swatchSize);\n \n // Value text\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Value:', contentX + this.swatchSize + this.swatchGap, currentY);\n ctx.fillStyle = theme.textColor;\n const labelWidth = ctx.measureText('Value: ').width;\n ctx.fillText(formatValue(data.zValue), contentX + this.swatchSize + this.swatchGap + labelWidth, currentY);\n \n currentY += theme.contentFontSize * theme.lineHeight;\n \n // Scale info (indented to align with value)\n if (data.colorScale) {\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.font = `400 ${theme.contentFontSize - 1}px ${theme.fontFamily}`;\n const scaleText = `Min: ${formatValue(data.colorScale.min)} Max: ${formatValue(data.colorScale.max)}`;\n ctx.fillText(scaleText, contentX + this.swatchSize + this.swatchGap, currentY);\n currentY += theme.contentFontSize * theme.lineHeight;\n }\n \n currentY += theme.itemGap + 2;\n \n // X value\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('X:', contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.dataX), contentX + 25, currentY);\n \n currentY += theme.contentFontSize * theme.lineHeight + 2;\n \n // Y value\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Y:', contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.dataY), contentX + 25, currentY);\n \n ctx.restore();\n }\n}\n\n// Export singleton instance\nexport const heatmapTooltipTemplate = new HeatmapTooltipTemplate();\n","/**\n * Scientific Tooltip Template\n * \n * Full precision scientific template with:\n * - Proper scientific notation with superscripts\n * - Units and prefixes\n * - Complete error values\n * - Extended metadata\n * \n * @module tooltip/templates/ScientificTemplate\n */\n\nimport type {\n DataPointTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\nimport { formatDataPointX, formatDataPointY } from '../format';\n\nfunction formatXValue(data: DataPointTooltip): string {\n if (data.axisFormat?.x?.type === 'time') return formatDataPointX(data);\n return toScientificUnicode(data.dataX);\n}\n\nfunction formatYValue(data: DataPointTooltip): string {\n if (data.axisFormat?.y?.scientific === false) return formatDataPointY(data);\n return toScientificUnicode(data.dataY);\n}\n\n/**\n * Convert number to scientific notation with Unicode superscripts\n */\nfunction toScientificUnicode(\n value: number | null | undefined,\n precision: number = 3\n): string {\n if (value === null || value === undefined || isNaN(value)) {\n return \"N/A\";\n }\n\n if (value === 0) return \"0\";\n\n const exp = Math.floor(Math.log10(Math.abs(value)));\n const mantissa = value / Math.pow(10, exp);\n\n if (Math.abs(exp) <= 2) {\n // Don't use scientific notation for small exponents\n return value.toPrecision(precision);\n }\n\n // Superscript map\n const superscripts: Record<string, string> = {\n \"0\": \"⁰\",\n \"1\": \"¹\",\n \"2\": \"²\",\n \"3\": \"³\",\n \"4\": \"⁴\",\n \"5\": \"⁵\",\n \"6\": \"⁶\",\n \"7\": \"⁷\",\n \"8\": \"⁸\",\n \"9\": \"⁹\",\n \"-\": \"⁻\",\n \"+\": \"⁺\",\n };\n\n // Convert exponent to superscript\n const expStr = exp.toString();\n let superExp = \"\";\n for (const char of expStr) {\n superExp += superscripts[char] || char;\n }\n\n return `${mantissa.toFixed(precision - 1)} × 10${superExp}`;\n}\n\n/**\n * Format with SI prefix (for future use)\n */\n// function formatWithPrefix(value: number, unit: string = ''): string {\n// const prefixes = [\n// { exp: 12, prefix: 'T' },\n// { exp: 9, prefix: 'G' },\n// { exp: 6, prefix: 'M' },\n// { exp: 3, prefix: 'k' },\n// { exp: 0, prefix: '' },\n// { exp: -3, prefix: 'm' },\n// { exp: -6, prefix: 'µ' },\n// { exp: -9, prefix: 'n' },\n// { exp: -12, prefix: 'p' }\n// ];\n// \n// if (value === 0) return `0 ${unit}`;\n// \n// const absVal = Math.abs(value);\n// \n// for (const { exp, prefix } of prefixes) {\n// if (absVal >= Math.pow(10, exp - 1)) {\n// const scaled = value / Math.pow(10, exp);\n// return `${scaled.toFixed(3)} ${prefix}${unit}`;\n// }\n// }\n// \n// return `${value.toExponential(3)} ${unit}`;\n// }\n\n/**\n * Scientific Template\n * \n * Visual layout:\n * ┌────────────────────────────────────────╮\n * │ 📍 Series Name │\n * │ ───────────────────────────────────── │\n * │ X: 1.234×10³ │\n * │ Y: 5.678×10⁻² ± 0.001 │\n * │ ───────────────────────────────────── │\n * │ Index: 1523 │ Cycle: 3 │\n * ╰────────────────────────────────────────╯\n */\nexport class ScientificTooltipTemplate implements TooltipTemplate<DataPointTooltip> {\n readonly id = 'scientific';\n readonly name = 'Scientific Notation';\n readonly supportedTypes: TooltipType[] = ['datapoint'];\n\n // Cached measurements\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n // Cache key\n const cacheKey = `${data.seriesId}-${data.dataIndex}-${data.dataX}-${data.dataY}-${theme.fontFamily}-${theme.titleFontSize}`;\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Title font\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n \n const titleWidth = ctx.measureText(data.seriesName).width + \n (theme.showSeriesIndicator ? theme.seriesIndicatorSize + 8 : 0);\n \n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n const labelWidth = 28; // Fixed width used in render\n \n // X value\n const xVal = formatXValue(data);\n let maxWidth = Math.max(titleWidth, labelWidth + ctx.measureText(xVal).width);\n \n // Y value with optional error\n const yVal = formatYValue(data);\n let yWidth = labelWidth + ctx.measureText(yVal).width;\n if (data.yError) {\n yWidth += ctx.measureText(` ± ${toScientificUnicode(data.yError[0])}`).width;\n }\n maxWidth = Math.max(maxWidth, yWidth);\n \n // Footer line\n let footerText = `Index: ${data.dataIndex}`;\n if (data.cycle !== undefined) {\n footerText += ` │ Cycle: ${data.cycle}`;\n }\n maxWidth = Math.max(maxWidth, ctx.measureText(footerText).width);\n \n // Height calculation\n let lineCount = 3; // title, X, Y\n if (data.cycle !== undefined || data.yError) {\n lineCount += 1; // footer\n }\n \n const headerHeight = theme.titleFontSize * theme.lineHeight + theme.headerGap;\n const contentHeight = (lineCount - 1) * theme.contentFontSize * theme.lineHeight;\n const extraGap = (data.cycle !== undefined) ? theme.itemGap : 0;\n \n this.cachedMeasurement = {\n width: maxWidth,\n height: headerHeight + contentHeight + extraGap,\n padding: theme.padding\n };\n this.cachedKey = cacheKey;\n \n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: DataPointTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { x, y } = position;\n const { padding } = theme;\n \n let currentY = y + padding.top;\n let currentX = x + padding.left;\n \n ctx.save();\n \n // Explicitly set alignment\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n \n // Draw series indicator\n if (theme.showSeriesIndicator) {\n const indicatorY = currentY + theme.titleFontSize / 2;\n ctx.fillStyle = data.seriesColor;\n ctx.beginPath();\n ctx.arc(currentX + theme.seriesIndicatorSize / 2, indicatorY, theme.seriesIndicatorSize / 2, 0, Math.PI * 2);\n ctx.fill();\n currentX += theme.seriesIndicatorSize + 8;\n }\n \n // Title\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n ctx.fillText(data.seriesName, currentX, currentY);\n \n currentY += theme.titleFontSize * theme.lineHeight + 2;\n currentX = x + padding.left;\n \n // Separator\n if (theme.showHeaderSeparator) {\n ctx.strokeStyle = theme.separatorColor;\n ctx.lineWidth = 1;\n ctx.globalAlpha = 0.4;\n ctx.beginPath();\n ctx.moveTo(currentX, currentY + theme.headerGap / 2);\n ctx.lineTo(currentX + measurement.width, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1.0;\n }\n \n currentY += theme.headerGap + 2;\n \n // Content\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n const labelWidth = 28;\n \n // X value\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('X:', currentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatXValue(data), currentX + labelWidth, currentY);\n currentY += theme.contentFontSize * theme.lineHeight + 2;\n \n // Y value with error\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Y:', currentX, currentY);\n ctx.fillStyle = theme.textColor;\n \n let yText = formatYValue(data);\n ctx.fillText(yText, currentX + labelWidth, currentY);\n \n if (data.yError) {\n const yWidth = ctx.measureText(yText).width;\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText(` ± ${toScientificUnicode(data.yError[0])}`, currentX + labelWidth + yWidth, currentY);\n }\n currentY += theme.contentFontSize * theme.lineHeight + 2;\n \n // Footer with index and cycle\n if (data.cycle !== undefined) {\n currentY += theme.itemGap;\n \n // Light separator\n ctx.strokeStyle = theme.separatorColor;\n ctx.globalAlpha = 0.3;\n ctx.beginPath();\n ctx.moveTo(currentX, currentY - theme.itemGap / 2);\n ctx.lineTo(currentX + measurement.width, currentY - theme.itemGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1;\n \n // Footer text\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.font = `400 ${theme.contentFontSize - 1}px ${theme.fontFamily}`;\n \n let footerText = `Index: ${data.dataIndex}`;\n if (data.cycle !== undefined) {\n footerText += ` │ Cycle: ${data.cycle}`;\n }\n ctx.fillText(footerText, currentX, currentY);\n }\n \n ctx.restore();\n }\n}\n\n// Export singleton instance\nexport const scientificTooltipTemplate = new ScientificTooltipTemplate();\n","/**\n * Annotation Tooltip Template\n * \n * Template for displaying information about chart annotations:\n * - Annotation type and ID\n * - Labeled values\n * - Custom metadata\n * \n * @module tooltip/templates/AnnotationTemplate\n */\n\nimport type {\n AnnotationTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\n\n/**\n * Format a number for display\n */\nfunction formatValue(value: number | null | undefined): string {\n if (value === null || value === undefined || isNaN(value)) {\n return \"N/A\";\n }\n\n const absVal = Math.abs(value);\n if (absVal === 0) return \"0\";\n if (absVal < 0.0001 || absVal >= 10000) return value.toExponential(2);\n if (absVal < 1) return value.toFixed(4);\n return value.toFixed(2);\n}\n\nexport class AnnotationTooltipTemplate implements TooltipTemplate<AnnotationTooltip> {\n readonly id = 'annotation';\n readonly name = 'Annotation Info';\n readonly supportedTypes: TooltipType[] = ['annotation'];\n\n // Cache\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: AnnotationTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n const cacheKey = `${data.annotationId}-${data.label}-${theme.fontFamily}-${theme.titleFontSize}`;\n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Header font\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n const headerText = data.label || `Annotation: ${data.annotationType}`;\n let maxWidth = ctx.measureText(headerText).width;\n\n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n let contentHeight = 0;\n const labelWidth = 50;\n\n // Value lines\n if (data.value !== undefined) {\n const valText = formatValue(data.value);\n maxWidth = Math.max(maxWidth, labelWidth + ctx.measureText(valText).width);\n contentHeight += theme.contentFontSize * theme.lineHeight;\n }\n if (data.valueX !== undefined && data.valueY !== undefined) {\n const xText = formatValue(data.valueX);\n const yText = formatValue(data.valueY);\n maxWidth = Math.max(maxWidth, labelWidth + ctx.measureText(xText).width, labelWidth + ctx.measureText(yText).width);\n contentHeight += (theme.contentFontSize * theme.lineHeight) * 2;\n }\n\n const headerHeight = theme.titleFontSize * theme.lineHeight + theme.headerGap;\n \n this.cachedMeasurement = {\n width: maxWidth + 10,\n height: headerHeight + contentHeight + 4,\n padding: theme.padding\n };\n this.cachedKey = cacheKey;\n\n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: AnnotationTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { x, y } = position;\n const { padding } = theme;\n \n let currentY = y + padding.top;\n const contentX = x + padding.left;\n\n ctx.save();\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n\n // Header\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n const headerText = data.label || `${data.annotationType.toUpperCase()}`;\n ctx.fillText(headerText, contentX, currentY);\n \n currentY += theme.titleFontSize * theme.lineHeight + 2;\n\n // Separator\n if (theme.showHeaderSeparator) {\n ctx.strokeStyle = theme.separatorColor;\n ctx.globalAlpha = 0.4;\n ctx.beginPath();\n ctx.moveTo(contentX, currentY + theme.headerGap / 2);\n ctx.lineTo(contentX + measurement.width, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1.0;\n }\n\n currentY += theme.headerGap + 2;\n\n // Content\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n const labelW = 50;\n\n if (data.value !== undefined) {\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Value:', contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.value), contentX + labelW, currentY);\n currentY += theme.contentFontSize * theme.lineHeight;\n }\n\n if (data.valueX !== undefined && data.valueY !== undefined) {\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('X:', contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.valueX), contentX + labelW, currentY);\n currentY += theme.contentFontSize * theme.lineHeight;\n\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText('Y:', contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(formatValue(data.valueY), contentX + labelW, currentY);\n }\n\n ctx.restore();\n }\n}\n\nexport const annotationTooltipTemplate = new AnnotationTooltipTemplate();\n","/**\n * Range Tooltip Template\n * \n * Displays statistical information for a selected range:\n * - Count of points\n * - Min/Max/Mean values\n * - Area and Peaks\n * \n * @module tooltip/templates/RangeTemplate\n */\n\nimport type {\n RangeTooltip,\n TooltipTemplate,\n TooltipMeasurement,\n TooltipPosition,\n TooltipTheme,\n TooltipType\n} from '../types';\n\n/**\n * Format a number for display\n */\nfunction formatValue(value: number | null | undefined): string {\n if (value === null || value === undefined || isNaN(value)) {\n return \"N/A\";\n }\n\n const absVal = Math.abs(value);\n if (absVal === 0) return \"0\";\n if (absVal < 0.0001 || absVal >= 10000) return value.toExponential(3);\n if (absVal < 1) return value.toFixed(4);\n return value.toFixed(3);\n}\n\nexport class RangeTooltipTemplate implements TooltipTemplate<RangeTooltip> {\n readonly id = 'range';\n readonly name = 'Range Statistics';\n readonly supportedTypes: TooltipType[] = ['range'];\n\n // Cache\n private cachedKey: string = '';\n private cachedMeasurement: TooltipMeasurement | null = null;\n\n /**\n * Measure tooltip dimensions\n */\n measure(\n ctx: CanvasRenderingContext2D,\n data: RangeTooltip,\n theme: TooltipTheme\n ): TooltipMeasurement {\n const stats = data.statistics;\n const cacheKey = `${data.xMin}-${data.xMax}-${stats.count}-${stats.mean}-${theme.fontFamily}`;\n \n if (cacheKey === this.cachedKey && this.cachedMeasurement) {\n return this.cachedMeasurement;\n }\n\n // Title font\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n const headerText = 'Range Statistics';\n let maxWidth = ctx.measureText(headerText).width;\n\n // Content font\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n \n let contentHeight = theme.contentFontSize * theme.lineHeight * 2; // Range and Count are always shown\n \n const lines = [\n `Range: ${formatValue(data.xMin)} to ${formatValue(data.xMax)}`,\n `Count: ${stats.count}`\n ];\n\n if (stats.min !== undefined) lines.push(`Min: ${formatValue(stats.min)}`);\n if (stats.max !== undefined) lines.push(`Max: ${formatValue(stats.max)}`);\n if (stats.mean !== undefined) lines.push(`Mean: ${formatValue(stats.mean)}`);\n if (stats.area !== undefined) lines.push(`Area: ${formatValue(stats.area)}`);\n\n for (const line of lines) {\n maxWidth = Math.max(maxWidth, ctx.measureText(line).width + 10);\n }\n \n contentHeight = lines.length * theme.contentFontSize * theme.lineHeight;\n\n const headerHeight = theme.titleFontSize * theme.lineHeight + theme.headerGap;\n \n this.cachedMeasurement = {\n width: Math.max(maxWidth, 140),\n height: headerHeight + contentHeight + 10,\n padding: theme.padding\n };\n this.cachedKey = cacheKey;\n\n return this.cachedMeasurement;\n }\n\n /**\n * Render the tooltip\n */\n render(\n ctx: CanvasRenderingContext2D,\n data: RangeTooltip,\n position: TooltipPosition,\n measurement: TooltipMeasurement,\n theme: TooltipTheme\n ): void {\n const { x, y } = position;\n const { padding } = theme;\n const stats = data.statistics;\n \n let currentY = y + padding.top;\n const contentX = x + padding.left;\n\n ctx.save();\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n\n // Title\n ctx.font = `${theme.titleFontWeight} ${theme.titleFontSize}px ${theme.fontFamily}`;\n ctx.fillStyle = theme.textColor;\n ctx.fillText('Range Statistics', contentX, currentY);\n \n currentY += theme.titleFontSize * theme.lineHeight + 2;\n\n // Header Separator\n if (theme.showHeaderSeparator) {\n ctx.strokeStyle = theme.separatorColor;\n ctx.globalAlpha = 0.4;\n ctx.beginPath();\n ctx.moveTo(contentX, currentY + theme.headerGap / 2);\n ctx.lineTo(contentX + measurement.width, currentY + theme.headerGap / 2);\n ctx.stroke();\n ctx.globalAlpha = 1.0;\n }\n\n currentY += theme.headerGap + 2;\n\n // Content\n ctx.font = `400 ${theme.contentFontSize}px ${theme.fontFamily}`;\n const labelW = 60;\n\n const renderLine = (label: string, value: string | number) => {\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.fillText(label, contentX, currentY);\n ctx.fillStyle = theme.textColor;\n ctx.fillText(String(value), contentX + labelW, currentY);\n currentY += theme.contentFontSize * theme.lineHeight;\n };\n\n renderLine('Points:', stats.count);\n if (stats.min !== undefined) renderLine('Min:', formatValue(stats.min));\n if (stats.max !== undefined) renderLine('Max:', formatValue(stats.max));\n if (stats.mean !== undefined) renderLine('Mean:', formatValue(stats.mean));\n if (stats.stdDev !== undefined) renderLine('StdDev:', formatValue(stats.stdDev));\n if (stats.area !== undefined) renderLine('Area:', formatValue(stats.area));\n \n if (stats.peakX !== undefined) {\n currentY += 4;\n ctx.fillStyle = theme.textSecondaryColor;\n ctx.font = `italic ${theme.contentFontSize - 1}px ${theme.fontFamily}`;\n ctx.fillText(`Peak: ${formatValue(stats.peakY ?? 0)} at X=${formatValue(stats.peakX)}`, contentX, currentY);\n }\n\n ctx.restore();\n }\n}\n\nexport const rangeTooltipTemplate = new RangeTooltipTemplate();\n","/**\n * Tooltip Templates - Barrel Export\n * \n * All available tooltip templates for different use cases.\n * \n * @module tooltip/templates\n */\n\n// Default template - Clean data point display\nexport { DefaultTooltipTemplate, defaultTooltipTemplate } from './DefaultTemplate';\n\n// Minimal template - Ultra-compact values\nexport { MinimalTooltipTemplate, minimalTooltipTemplate } from './MinimalTemplate';\n\n// Crosshair template - Multi-series at X position\nexport { CrosshairTooltipTemplate, crosshairTooltipTemplate } from './CrosshairTemplate';\n\n// Heatmap template - Z values with color preview\nexport { HeatmapTooltipTemplate, heatmapTooltipTemplate } from './HeatmapTemplate';\n\n// Scientific template - Full precision with notation\nexport { ScientificTooltipTemplate, scientificTooltipTemplate } from './ScientificTemplate';\n\n// Annotation template - Labels and values for markers/lines\nexport { AnnotationTooltipTemplate, annotationTooltipTemplate } from './AnnotationTemplate';\n\n// Range template - Statistics for data selections\nexport { RangeTooltipTemplate, rangeTooltipTemplate } from './RangeTemplate';\n\n// Template registry for easy lookup\nimport type { TooltipTemplate, TooltipData } from '../types';\nimport { defaultTooltipTemplate } from './DefaultTemplate';\nimport { minimalTooltipTemplate } from './MinimalTemplate';\nimport { crosshairTooltipTemplate } from './CrosshairTemplate';\nimport { heatmapTooltipTemplate } from './HeatmapTemplate';\nimport { scientificTooltipTemplate } from './ScientificTemplate';\nimport { annotationTooltipTemplate } from './AnnotationTemplate';\nimport { rangeTooltipTemplate } from './RangeTemplate';\n\n/** All built-in templates */\nexport const BUILTIN_TEMPLATES: TooltipTemplate<TooltipData>[] = [\n defaultTooltipTemplate as TooltipTemplate<TooltipData>,\n minimalTooltipTemplate as TooltipTemplate<TooltipData>,\n crosshairTooltipTemplate as TooltipTemplate<TooltipData>,\n heatmapTooltipTemplate as TooltipTemplate<TooltipData>,\n scientificTooltipTemplate as TooltipTemplate<TooltipData>,\n annotationTooltipTemplate as TooltipTemplate<TooltipData>,\n rangeTooltipTemplate as TooltipTemplate<TooltipData>\n];\n\n/** Template ID type */\nexport type BuiltinTemplateId = 'default' | 'minimal' | 'crosshair' | 'heatmap' | 'scientific' | 'annotation' | 'range';\n\n/**\n * Get a built-in template by ID\n */\nexport function getBuiltinTemplate(id: BuiltinTemplateId | string): TooltipTemplate<TooltipData> | undefined {\n return BUILTIN_TEMPLATES.find(t => t.id === id);\n}\n\n/**\n * Get template for a tooltip type\n */\nexport function getDefaultTemplateForType(type: string): TooltipTemplate<TooltipData> {\n switch (type) {\n case 'datapoint':\n return defaultTooltipTemplate as TooltipTemplate<TooltipData>;\n case 'crosshair':\n return crosshairTooltipTemplate as TooltipTemplate<TooltipData>;\n case 'heatmap':\n return heatmapTooltipTemplate as TooltipTemplate<TooltipData>;\n case 'annotation':\n return annotationTooltipTemplate as TooltipTemplate<TooltipData>;\n case 'range':\n return rangeTooltipTemplate as TooltipTemplate<TooltipData>;\n default:\n return defaultTooltipTemplate as TooltipTemplate<TooltipData>;\n }\n}\n","/**\n * TooltipManager - Coordinates the tooltip system\n *\n * This is the main entry point for the tooltip system, integrating:\n * - Template management\n * - Theme management\n * - Hit-testing for data points\n * - Tooltip positioning and rendering\n * - Event handling\n *\n * @module tooltip/TooltipManager\n */\n\nimport type { PlotArea, Bounds, AxisOptions } from \"../../../types\";\nimport type { Scale } from \"../../../scales\";\nimport type { Series } from \"../../../core/Series\";\nimport type { TooltipAxisFormat } from \"../../../core/format/axisFormat\";\nimport type {\n TooltipData,\n DataPointTooltip,\n CrosshairTooltip,\n TooltipOptions,\n TooltipTheme,\n TooltipTemplate,\n TooltipPosition,\n ShowTooltipOptions,\n TooltipEventMap,\n} from \"./types\";\nimport { EventEmitter } from \"../../../core/EventEmitter\";\nimport { TooltipPositioner } from \"./TooltipPositioner\";\nimport { TooltipRenderer } from \"./TooltipRenderer\";\nimport {\n DEFAULT_TOOLTIP_THEME,\n getTooltipThemeForChartTheme,\n createTooltipTheme,\n} from \"./themes\";\nimport {\n defaultTooltipTemplate,\n minimalTooltipTemplate,\n crosshairTooltipTemplate,\n heatmapTooltipTemplate,\n scientificTooltipTemplate,\n annotationTooltipTemplate,\n rangeTooltipTemplate,\n getBuiltinTemplate,\n getDefaultTemplateForType,\n} from \"./templates\";\nimport type { ChartTheme } from \"../../../theme\";\n\n// ============================================\n// Types for TooltipManager\n// ============================================\n\nexport interface TooltipManagerConfig {\n /** Canvas 2D context for rendering */\n overlayCtx: CanvasRenderingContext2D;\n /** Chart theme (for auto-selecting tooltip theme) */\n chartTheme: ChartTheme;\n /** Function to get current plot area */\n getPlotArea: () => PlotArea;\n /** Function to get all series */\n getSeries: () => Series[];\n /** Function to convert pixel X to data X */\n pixelToDataX: (px: number) => number;\n /** Function to convert pixel Y to data Y */\n pixelToDataY: (py: number) => number;\n /** Function to get X scale */\n getXScale: () => Scale;\n /** Function to get Y scales */\n getYScales: () => Map<string, Scale>;\n /** Function to get view bounds */\n getViewBounds: () => Bounds;\n /** Function to get X axis options */\n getXAxisOptions?: () => AxisOptions;\n /** Function to get Y axis options for a series axis id */\n getYAxisOptions?: (axisId?: string) => AxisOptions | undefined;\n /** Initial options */\n options?: TooltipOptions;\n}\n\ninterface ActiveTooltip {\n id: string;\n data: TooltipData;\n position: TooltipPosition;\n template: TooltipTemplate<TooltipData>;\n}\n\n/** Internal fully-populated options type */\ninterface FullTooltipOptions {\n enabled: boolean;\n showDelay: number;\n hideDelay: number;\n followCursor: boolean;\n offset: { x: number; y: number };\n dataPoint: {\n enabled: boolean;\n templateId: string;\n snapToPoint: boolean;\n hitRadius: number;\n };\n crosshair: {\n enabled: boolean;\n templateId: string;\n interpolate: boolean;\n visibleSeriesOnly: boolean;\n };\n range: {\n enabled: boolean;\n templateId: string;\n calculateStats: boolean;\n };\n annotation: {\n enabled: boolean;\n templateId: string;\n };\n heatmap: {\n enabled: boolean;\n templateId: string;\n showColorInfo: boolean;\n };\n positioning: \"auto\" | \"fixed\" | \"follow\";\n preferredPosition: \"top\" | \"bottom\" | \"left\" | \"right\" | \"auto\";\n constrainToPlotArea: boolean;\n constrainToContainer: boolean;\n autoFlip: boolean;\n theme?: string | Partial<TooltipTheme>;\n}\n\n// ============================================\n// TooltipManager Implementation\n// ============================================\n\nexport class TooltipManager {\n private ctx: CanvasRenderingContext2D;\n private getPlotArea: () => PlotArea;\n private getSeries: () => Series[];\n private pixelToDataX: (px: number) => number;\n private pixelToDataY: (py: number) => number;\n private getXScale: () => Scale;\n private getYScales: () => Map<string, Scale>;\n private getViewBounds: () => Bounds;\n private getXAxisOptions?: () => AxisOptions;\n private getYAxisOptions?: (axisId?: string) => AxisOptions | undefined;\n\n private options: FullTooltipOptions;\n private theme: TooltipTheme;\n private positioner: TooltipPositioner;\n private renderer: TooltipRenderer;\n private templates: Map<string, TooltipTemplate<TooltipData>> = new Map();\n private events = new EventEmitter<TooltipEventMap>();\n\n private activeTooltips: Map<string, ActiveTooltip> = new Map();\n private tooltipIdCounter = 0;\n private showTimeoutId: number | null = null;\n private hideTimeoutId: number | null = null;\n\n private lastCursorX: number | null = null;\n private lastCursorY: number | null = null;\n private hoveredSeriesId: string | null = null;\n private hoveredDataIndex: number | null = null;\n private cachedNearestResult: DataPointTooltip | null = null;\n\n // Large dataset optimizations\n private snapMode: \"nearest\" | \"x-only\" | \"auto\" = \"auto\";\n private largeDatasetThreshold = 50000;\n private lastKnownDataSize = 0;\n // Hysteresis factor: new point must be this much closer to switch (2 = 2x closer)\n private hysteresisRatio = 2.0;\n // Suspended state - used during drag operations to hide tooltip\n private suspended = false;\n\n constructor(config: TooltipManagerConfig) {\n this.ctx = config.overlayCtx;\n this.getPlotArea = config.getPlotArea;\n this.getSeries = config.getSeries;\n this.pixelToDataX = config.pixelToDataX;\n this.pixelToDataY = config.pixelToDataY;\n this.getXScale = config.getXScale;\n this.getYScales = config.getYScales;\n this.getViewBounds = config.getViewBounds;\n this.getXAxisOptions = config.getXAxisOptions;\n this.getYAxisOptions = config.getYAxisOptions;\n\n // Default options\n this.options = {\n enabled: true,\n showDelay: 50,\n hideDelay: 100,\n followCursor: false,\n offset: { x: 12, y: 12 },\n dataPoint: {\n enabled: true,\n templateId: \"default\",\n snapToPoint: true,\n hitRadius: 20,\n },\n crosshair: {\n enabled: false,\n templateId: \"crosshair\",\n interpolate: true,\n visibleSeriesOnly: true,\n },\n range: {\n enabled: false,\n templateId: \"default\",\n calculateStats: true,\n },\n annotation: {\n enabled: true,\n templateId: \"default\",\n },\n heatmap: {\n enabled: true,\n templateId: \"heatmap\",\n showColorInfo: true,\n },\n positioning: \"auto\",\n preferredPosition: \"auto\",\n constrainToPlotArea: true,\n constrainToContainer: true,\n autoFlip: true,\n };\n\n // Initialize theme first (needed for positioner)\n this.theme = config.options?.theme\n ? typeof config.options.theme === \"string\"\n ? getTooltipThemeForChartTheme(config.options.theme)\n : createTooltipTheme(DEFAULT_TOOLTIP_THEME, config.options.theme)\n : getTooltipThemeForChartTheme(config.chartTheme.name);\n\n // Initialize components before applying user options\n this.positioner = new TooltipPositioner({\n offset: this.options.offset,\n preferredPosition: this.options.preferredPosition,\n constrainToPlotArea: this.options.constrainToPlotArea,\n constrainToContainer: this.options.constrainToContainer,\n autoFlip: this.options.autoFlip,\n showArrow: this.theme.showArrow,\n arrowSize: this.theme.arrowSize,\n });\n\n this.renderer = new TooltipRenderer(this.ctx, this.theme);\n\n // Register built-in templates\n this.registerBuiltinTemplates();\n\n // Apply user options after components are initialized\n if (config.options) {\n this.configure(config.options);\n }\n }\n\n /**\n * Register built-in templates\n */\n private registerBuiltinTemplates(): void {\n this.templates.set(\n \"default\",\n defaultTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"minimal\",\n minimalTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"crosshair\",\n crosshairTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"heatmap\",\n heatmapTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"scientific\",\n scientificTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"annotation\",\n annotationTooltipTemplate as TooltipTemplate<TooltipData>\n );\n this.templates.set(\n \"range\",\n rangeTooltipTemplate as TooltipTemplate<TooltipData>\n );\n }\n\n /**\n * Configure tooltip options\n */\n configure(options: TooltipOptions): void {\n if (options.enabled !== undefined) this.options.enabled = options.enabled;\n if (options.showDelay !== undefined)\n this.options.showDelay = options.showDelay;\n if (options.hideDelay !== undefined)\n this.options.hideDelay = options.hideDelay;\n if (options.followCursor !== undefined)\n this.options.followCursor = options.followCursor;\n if (options.offset)\n this.options.offset = { ...this.options.offset, ...options.offset };\n\n if (options.dataPoint) {\n this.options.dataPoint = {\n ...this.options.dataPoint,\n ...options.dataPoint,\n };\n }\n if (options.crosshair) {\n this.options.crosshair = {\n ...this.options.crosshair,\n ...options.crosshair,\n };\n }\n if (options.heatmap) {\n this.options.heatmap = { ...this.options.heatmap, ...options.heatmap };\n }\n\n if (options.preferredPosition)\n this.options.preferredPosition = options.preferredPosition;\n if (options.constrainToPlotArea !== undefined)\n this.options.constrainToPlotArea = options.constrainToPlotArea;\n if (options.constrainToContainer !== undefined)\n this.options.constrainToContainer = options.constrainToContainer;\n if (options.autoFlip !== undefined)\n this.options.autoFlip = options.autoFlip;\n\n // Large dataset optimization options\n if (options.snapMode !== undefined) {\n this.snapMode = options.snapMode;\n }\n if (options.largeDatasetThreshold !== undefined) {\n this.largeDatasetThreshold = Math.max(\n 1000,\n options.largeDatasetThreshold\n );\n }\n\n // Update positioner\n this.positioner.configure({\n offset: this.options.offset,\n preferredPosition: this.options.preferredPosition,\n constrainToPlotArea: this.options.constrainToPlotArea,\n constrainToContainer: this.options.constrainToContainer,\n autoFlip: this.options.autoFlip,\n });\n }\n\n /**\n * Get current options\n */\n getOptions(): TooltipOptions {\n return { ...this.options };\n }\n\n /**\n * Enable/disable tooltips\n */\n setEnabled(enabled: boolean): void {\n this.options.enabled = enabled;\n if (!enabled) {\n this.hideAll();\n }\n }\n\n /**\n * Check if tooltips are enabled\n */\n isEnabled(): boolean {\n return this.options.enabled;\n }\n\n /**\n * Suspend tooltip display (used during drag operations)\n * When suspended, tooltips are immediately hidden and cursor movements are ignored\n */\n setSuspended(suspended: boolean): void {\n this.suspended = suspended;\n if (suspended) {\n this.hideAll();\n }\n }\n\n /**\n * Check if tooltips are suspended\n */\n isSuspended(): boolean {\n return this.suspended;\n }\n\n /**\n * Set tooltip theme\n */\n setTheme(theme: TooltipTheme | string): void {\n this.theme =\n typeof theme === \"string\" ? getTooltipThemeForChartTheme(theme) : theme;\n this.renderer.setTheme(this.theme);\n this.positioner.configure({\n showArrow: this.theme.showArrow,\n arrowSize: this.theme.arrowSize,\n });\n }\n\n /**\n * Update theme based on chart theme\n */\n updateChartTheme(chartTheme: ChartTheme): void {\n if (!this.options.theme) {\n // Only auto-update if user hasn't set a custom theme\n this.theme = getTooltipThemeForChartTheme(chartTheme.name);\n this.renderer.setTheme(this.theme);\n }\n }\n\n /**\n * Get current theme\n */\n getTheme(): TooltipTheme {\n return this.theme;\n }\n\n /**\n * Register a custom template\n */\n registerTemplate<T extends TooltipData>(template: TooltipTemplate<T>): void {\n this.templates.set(template.id, template as TooltipTemplate<TooltipData>);\n }\n\n /**\n * Get a template by ID\n */\n getTemplate(id: string): TooltipTemplate<TooltipData> | undefined {\n return this.templates.get(id) || getBuiltinTemplate(id);\n }\n\n /**\n * Handle cursor movement - main entry point for hover detection\n * Optimized with hysteresis to prevent jumping between nearby points\n */\n handleCursorMove(pixelX: number, pixelY: number): void {\n if (!this.options.enabled || this.suspended) return;\n\n this.lastCursorX = pixelX;\n this.lastCursorY = pixelY;\n\n const plotArea = this.getPlotArea();\n\n // Check if cursor is in plot area (fast path)\n const inPlotArea =\n pixelX >= plotArea.x &&\n pixelX <= plotArea.x + plotArea.width &&\n pixelY >= plotArea.y &&\n pixelY <= plotArea.y + plotArea.height;\n\n if (!inPlotArea) {\n this.cachedNearestResult = null;\n this.scheduleHide();\n return;\n }\n\n // Update positioner with current bounds\n this.positioner.setContainerSize(\n this.ctx.canvas.width / (window.devicePixelRatio || 1),\n this.ctx.canvas.height / (window.devicePixelRatio || 1)\n );\n this.positioner.setPlotArea(plotArea);\n\n // Track data size for auto mode\n this.lastKnownDataSize = this.getTotalDataPoints();\n\n // Find and show tooltip with hysteresis\n this.performTooltipUpdateWithHysteresis(pixelX, pixelY);\n }\n\n /**\n * Handle cursor leave\n */\n handleCursorLeave(): void {\n this.lastCursorX = null;\n this.lastCursorY = null;\n this.cachedNearestResult = null;\n this.scheduleHide();\n }\n\n /**\n * Get total number of data points across all visible series\n */\n private getTotalDataPoints(): number {\n let total = 0;\n const series = this.getSeries();\n for (const s of series) {\n if (!s.isVisible()) continue;\n const data = s.getData();\n if (data.x) total += data.x.length;\n }\n return total;\n }\n\n /**\n * Determine the effective snap mode based on configuration and data size\n */\n private getEffectiveSnapMode(): \"nearest\" | \"x-only\" {\n if (this.snapMode === \"x-only\") return \"x-only\";\n if (this.snapMode === \"nearest\") return \"nearest\";\n\n // Auto mode - use x-only for large datasets\n return this.lastKnownDataSize > this.largeDatasetThreshold\n ? \"x-only\"\n : \"nearest\";\n }\n\n /**\n * Perform tooltip update with hysteresis to prevent jumping.\n * The tooltip \"sticks\" to the current point unless the cursor is\n * significantly closer to a new point.\n */\n private performTooltipUpdateWithHysteresis(\n pixelX: number,\n pixelY: number\n ): void {\n // Try to find a data point\n if (!this.options.dataPoint?.enabled) {\n this.performFallbackTooltipUpdate(pixelX, pixelY);\n return;\n }\n\n const effectiveMode = this.getEffectiveSnapMode();\n const newResult =\n effectiveMode === \"x-only\"\n ? this.findDataPointByXOnly(pixelX)\n : this.findNearestDataPointOptimized(pixelX, pixelY);\n\n if (!newResult) {\n this.performFallbackTooltipUpdate(pixelX, pixelY);\n return;\n }\n\n // Hysteresis: If we already have a point, only switch if new point is MUCH closer\n if (this.cachedNearestResult && this.hoveredSeriesId !== null) {\n const currentPoint = this.cachedNearestResult;\n\n // Calculate distances to current and new points\n const currentDx = currentPoint.pixelX - pixelX;\n const currentDy = currentPoint.pixelY - pixelY;\n const currentDistSq = currentDx * currentDx + currentDy * currentDy;\n\n const newDx = newResult.pixelX - pixelX;\n const newDy = newResult.pixelY - pixelY;\n const newDistSq = newDx * newDx + newDy * newDy;\n\n // Only switch to new point if it's significantly closer\n if (newDistSq * this.hysteresisRatio >= currentDistSq) {\n // Stay with current point - just update position if needed\n this.updateTooltipPosition(this.cachedNearestResult);\n return;\n }\n }\n\n // Switch to new point\n this.cachedNearestResult = newResult;\n this.scheduleShow(newResult);\n }\n\n /**\n * Handle heatmap and crosshair tooltip types (fallback)\n */\n private performFallbackTooltipUpdate(pixelX: number, pixelY: number): void {\n // Try heatmap\n if (this.options.heatmap?.enabled) {\n const heatmapResult = this.findHeatmapCell(pixelX, pixelY);\n if (heatmapResult) {\n this.scheduleShow(heatmapResult);\n return;\n }\n }\n\n // Crosshair mode\n if (this.options.crosshair?.enabled) {\n const crosshairData = this.buildCrosshairTooltip(pixelX, pixelY);\n if (crosshairData) {\n this.scheduleShow(crosshairData);\n return;\n }\n }\n\n // No hit - hide tooltip\n this.cachedNearestResult = null;\n this.scheduleHide();\n }\n\n private buildAxisFormat(yAxisId?: string): TooltipAxisFormat | undefined {\n const bounds = this.getViewBounds();\n const xSpan = bounds.xMax - bounds.xMin;\n const x = this.getXAxisOptions?.();\n const y = this.getYAxisOptions?.(yAxisId);\n\n if (!x && !y && !Number.isFinite(xSpan)) {\n return undefined;\n }\n\n return {\n x,\n y,\n xSpan: Number.isFinite(xSpan) ? xSpan : undefined,\n };\n }\n\n /**\n * Find data point by X coordinate only (O(log n) - fastest method)\n * Best for very large datasets where precision is less important than speed\n */\n private findDataPointByXOnly(pixelX: number): DataPointTooltip | null {\n const series = this.getSeries().filter(\n (s) => s.isVisible() && s.getType() !== \"heatmap\"\n );\n if (series.length === 0) return null;\n\n const xScale = this.getXScale();\n const yScales = this.getYScales();\n const cursorDataX = this.pixelToDataX(pixelX);\n\n let bestResult: DataPointTooltip | null = null;\n let bestXDistance = Infinity;\n\n for (const s of series) {\n const data = s.getData();\n if (!data.x || data.x.length === 0) continue;\n\n const yScale =\n yScales.get(s.getYAxisId?.() || \"default\") ||\n yScales.values().next().value;\n if (!yScale) continue;\n\n // Pure binary search for closest X\n const idx = this.binarySearchClosest(data.x, cursorDataX);\n const xDistance = Math.abs(data.x[idx] - cursorDataX);\n\n if (xDistance < bestXDistance) {\n bestXDistance = xDistance;\n const style = s.getStyle();\n const px = xScale.transform(data.x[idx]);\n const py = yScale.transform(data.y[idx]);\n\n bestResult = {\n type: \"datapoint\",\n seriesId: s.getId(),\n seriesName: s.getId(),\n seriesColor: style.color || \"#ff0055\",\n dataIndex: idx,\n dataX: data.x[idx],\n dataY: data.y[idx],\n pixelX: px,\n pixelY: py,\n cycle: (s as any).getCycle?.(),\n axisFormat: this.buildAxisFormat(s.getYAxisId?.()),\n };\n\n const yError = s.getYError(idx);\n if (yError) bestResult.yError = yError;\n }\n }\n\n return bestResult;\n }\n\n /**\n * Optimized nearest data point finder\n */\n private findNearestDataPointOptimized(\n pixelX: number,\n pixelY: number\n ): DataPointTooltip | null {\n const series = this.getSeries().filter((s) => s.isVisible());\n const hitRadius = this.options.dataPoint?.hitRadius ?? 20;\n const xScale = this.getXScale();\n const yScales = this.getYScales();\n\n let nearestDistanceSq = hitRadius * hitRadius;\n let nearestResult: DataPointTooltip | null = null;\n\n const cursorDataX = this.pixelToDataX(pixelX);\n\n for (const s of series) {\n if (s.getType() === \"heatmap\") continue;\n\n const data = s.getData();\n const yScale =\n yScales.get(s.getYAxisId?.() || \"default\") ||\n yScales.values().next().value;\n\n if (!yScale || !data.x || data.x.length === 0) continue;\n\n const closestIdx = this.binarySearchClosest(data.x, cursorDataX);\n\n // Adaptive search range\n const dataLength = data.x.length;\n const searchRadius = dataLength > 100000 ? 2 : dataLength > 10000 ? 3 : 5;\n const checkStart = Math.max(0, closestIdx - searchRadius);\n const checkEnd = Math.min(dataLength, closestIdx + searchRadius + 1);\n\n for (let i = checkStart; i < checkEnd; i++) {\n const px = xScale.transform(data.x[i]);\n const py = yScale.transform(data.y[i]);\n\n const dx = px - pixelX;\n const dy = py - pixelY;\n const distSq = dx * dx + dy * dy;\n\n if (distSq < nearestDistanceSq) {\n nearestDistanceSq = distSq;\n const style = s.getStyle();\n\n nearestResult = {\n type: \"datapoint\",\n seriesId: s.getId(),\n seriesName: s.getId(),\n seriesColor: style.color || \"#ff0055\",\n dataIndex: i,\n dataX: data.x[i],\n dataY: data.y[i],\n pixelX: px,\n pixelY: py,\n cycle: (s as any).getCycle?.(),\n axisFormat: this.buildAxisFormat(s.getYAxisId?.()),\n };\n\n const yError = s.getYError(i);\n if (yError) nearestResult.yError = yError;\n }\n }\n }\n\n return nearestResult;\n }\n\n /**\n * Find heatmap cell under cursor\n */\n private findHeatmapCell(\n pixelX: number,\n pixelY: number\n ): import(\"./types\").HeatmapTooltip | null {\n const series = this.getSeries().filter(\n (s) => s.isVisible() && s.getType() === \"heatmap\"\n );\n if (series.length === 0) return null;\n\n const xScale = this.getXScale();\n const yScales = this.getYScales();\n const dataX = this.pixelToDataX(pixelX);\n const dataY = this.pixelToDataY(pixelY);\n\n for (const s of series) {\n const data = s.getHeatmapData();\n if (!data || !data.xValues || !data.yValues || !data.zValues) continue;\n\n const colIdx = this.binarySearchClosest(data.xValues as any, dataX);\n const rowIdx = this.binarySearchClosest(data.yValues as any, dataY);\n\n const xValue = data.xValues[colIdx];\n const yValue = data.yValues[rowIdx];\n\n const yScale =\n yScales.get(s.getYAxisId?.() || \"default\") ||\n yScales.values().next().value;\n if (!yScale) continue;\n\n const px = xScale.transform(xValue);\n const py = yScale.transform(yValue);\n\n const zValue = data.zValues[rowIdx * data.xValues.length + colIdx];\n const style = s.getHeatmapStyle?.() || {};\n\n return {\n type: \"heatmap\",\n seriesId: s.getId(),\n seriesName: s.getId(),\n xIndex: colIdx,\n yIndex: rowIdx,\n dataX: xValue,\n dataY: yValue,\n zValue,\n pixelX: px,\n pixelY: py,\n colorScale: style.colorScale as any,\n };\n }\n\n return null;\n }\n\n /**\n * Binary search for closest value\n */\n private binarySearchClosest(\n arr: Float32Array | Float64Array,\n target: number\n ): number {\n let left = 0;\n let right = arr.length - 1;\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n if (arr[mid] < target) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n\n if (\n left > 0 &&\n Math.abs(arr[left - 1] - target) < Math.abs(arr[left] - target)\n ) {\n return left - 1;\n }\n\n return left;\n }\n\n /**\n * Build crosshair tooltip data\n */\n private buildCrosshairTooltip(\n pixelX: number,\n pixelY: number\n ): CrosshairTooltip | null {\n const series = this.getSeries().filter(\n (s) => s.isVisible() && s.getType() !== \"heatmap\"\n );\n if (series.length === 0) return null;\n\n const dataX = this.pixelToDataX(pixelX);\n const yScales = this.getYScales();\n\n const interpolatedValues: CrosshairTooltip[\"interpolatedValues\"] = [];\n\n for (const s of series) {\n const data = s.getData();\n if (!data.x || data.x.length === 0) continue;\n\n const yScale =\n yScales.get(s.getYAxisId?.() || \"default\") ||\n yScales.values().next().value;\n if (!yScale) continue;\n\n const idx = this.binarySearchClosest(data.x, dataX);\n let y: number;\n let isInterpolated = false;\n\n if (idx === 0 || idx >= data.x.length - 1 || data.x[idx] === dataX) {\n y = data.y[idx];\n } else if (this.options.crosshair?.interpolate) {\n const x0 = data.x[idx - 1];\n const x1 = data.x[idx];\n const y0 = data.y[idx - 1];\n const y1 = data.y[idx];\n const t = (dataX - x0) / (x1 - x0);\n y = y0 + t * (y1 - y0);\n isInterpolated = true;\n } else {\n y = data.y[idx];\n }\n\n const style = s.getStyle();\n interpolatedValues.push({\n seriesId: s.getId(),\n seriesName: s.getId(),\n seriesColor: style.color || \"#ff0055\",\n x: dataX,\n y,\n isInterpolated,\n });\n }\n\n if (interpolatedValues.length === 0) return null;\n\n return {\n type: \"crosshair\",\n cursorX: pixelX,\n cursorY: pixelY,\n dataX,\n interpolatedValues,\n axisFormat: this.buildAxisFormat(),\n };\n }\n\n /**\n * Schedule showing a tooltip\n */\n private scheduleShow(data: TooltipData): void {\n this.clearHideTimeout();\n\n // If same data point, just update position\n if (data.type === \"datapoint\") {\n const dp = data as DataPointTooltip;\n if (\n this.hoveredSeriesId === dp.seriesId &&\n this.hoveredDataIndex === dp.dataIndex\n ) {\n this.updateTooltipPosition(data);\n return;\n }\n this.hoveredSeriesId = dp.seriesId;\n this.hoveredDataIndex = dp.dataIndex;\n }\n\n this.clearShowTimeout();\n\n // Use short or no delay when already showing a tooltip\n const effectiveDelay =\n this.activeTooltips.size > 0 ? 0 : this.options.showDelay;\n\n if (effectiveDelay > 0) {\n this.showTimeoutId = window.setTimeout(() => {\n this.showTooltip(data);\n }, effectiveDelay);\n } else {\n this.showTooltip(data);\n }\n }\n\n /**\n * Schedule hiding tooltips\n */\n private scheduleHide(): void {\n this.clearShowTimeout();\n this.hoveredSeriesId = null;\n this.hoveredDataIndex = null;\n\n if (this.options.hideDelay > 0) {\n this.hideTimeoutId = window.setTimeout(() => {\n this.hideAll();\n }, this.options.hideDelay);\n } else {\n this.hideAll();\n }\n }\n\n private clearShowTimeout(): void {\n if (this.showTimeoutId !== null) {\n clearTimeout(this.showTimeoutId);\n this.showTimeoutId = null;\n }\n }\n\n private clearHideTimeout(): void {\n if (this.hideTimeoutId !== null) {\n clearTimeout(this.hideTimeoutId);\n this.hideTimeoutId = null;\n }\n }\n\n /**\n * Show a tooltip with the given data\n */\n private showTooltip(data: TooltipData): void {\n const templateId = this.getTemplateIdForType(data.type);\n const template =\n this.templates.get(templateId) || getDefaultTemplateForType(data.type);\n\n const targetX = (data as any).pixelX ?? this.lastCursorX ?? 0;\n const targetY = (data as any).pixelY ?? this.lastCursorY ?? 0;\n\n const measurement = template.measure(this.ctx, data, this.theme);\n const position = this.positioner.calculatePosition(\n targetX,\n targetY,\n measurement\n );\n\n const tooltipId = \"main\";\n\n this.activeTooltips.set(tooltipId, {\n id: tooltipId,\n data,\n position,\n template,\n });\n }\n\n /**\n * Update tooltip position\n */\n private updateTooltipPosition(data: TooltipData | null): void {\n const tooltip = this.activeTooltips.get(\"main\");\n if (!tooltip) return;\n\n const tooltipData = data || tooltip.data;\n const targetX = (tooltipData as any).pixelX ?? this.lastCursorX ?? 0;\n const targetY = (tooltipData as any).pixelY ?? this.lastCursorY ?? 0;\n\n const measurement = tooltip.template.measure(\n this.ctx,\n tooltipData,\n this.theme\n );\n tooltip.position = this.positioner.calculatePosition(\n targetX,\n targetY,\n measurement\n );\n tooltip.data = tooltipData;\n }\n\n /**\n * Get template ID for a tooltip type\n */\n private getTemplateIdForType(type: string): string {\n switch (type) {\n case \"datapoint\":\n return this.options.dataPoint?.templateId || \"default\";\n case \"crosshair\":\n return this.options.crosshair?.templateId || \"crosshair\";\n case \"heatmap\":\n return this.options.heatmap?.templateId || \"heatmap\";\n default:\n return \"default\";\n }\n }\n\n /**\n * Show a tooltip programmatically\n */\n show(data: TooltipData, options?: ShowTooltipOptions): string {\n const tooltipId = `tooltip-${++this.tooltipIdCounter}`;\n const templateId =\n options?.templateId || this.getTemplateIdForType(data.type);\n const template =\n this.templates.get(templateId) || getDefaultTemplateForType(data.type);\n\n let position: TooltipPosition;\n\n if (options?.position) {\n const measurement = template.measure(this.ctx, data, this.theme);\n position = this.positioner.calculatePosition(\n options.position.x,\n options.position.y,\n measurement\n );\n } else {\n const targetX = (data as any).pixelX ?? 0;\n const targetY = (data as any).pixelY ?? 0;\n const measurement = template.measure(this.ctx, data, this.theme);\n position = this.positioner.calculatePosition(\n targetX,\n targetY,\n measurement\n );\n }\n\n this.activeTooltips.set(tooltipId, {\n id: tooltipId,\n data,\n position,\n template,\n });\n\n if (options?.duration && options.duration > 0) {\n setTimeout(() => this.hide(tooltipId), options.duration);\n }\n\n return tooltipId;\n }\n\n /**\n * Hide a specific tooltip\n */\n hide(tooltipId: string): void {\n this.activeTooltips.delete(tooltipId);\n }\n\n /**\n * Hide all tooltips immediately\n */\n hideAll(): void {\n this.activeTooltips.clear();\n this.hoveredSeriesId = null;\n this.hoveredDataIndex = null;\n }\n\n /**\n * Render all active tooltips\n */\n render(): void {\n if (!this.options.enabled || this.activeTooltips.size === 0) return;\n\n for (const tooltip of this.activeTooltips.values()) {\n this.renderer.render(tooltip.data, tooltip.position, tooltip.template);\n }\n }\n\n /**\n * Check if any tooltip is currently visible\n */\n hasActiveTooltip(): boolean {\n return this.activeTooltips.size > 0;\n }\n\n /**\n * Subscribe to tooltip events\n */\n on<K extends keyof TooltipEventMap>(\n event: K,\n handler: (data: TooltipEventMap[K]) => void\n ): void {\n this.events.on(event, handler);\n }\n\n /**\n * Unsubscribe from tooltip events\n */\n off<K extends keyof TooltipEventMap>(\n event: K,\n handler: (data: TooltipEventMap[K]) => void\n ): void {\n this.events.off(event, handler);\n }\n\n /**\n * Destroy the tooltip manager\n */\n destroy(): void {\n this.clearShowTimeout();\n this.clearHideTimeout();\n this.activeTooltips.clear();\n this.templates.clear();\n this.events.clear();\n }\n}\n\n/**\n * Create a tooltip manager\n */\nexport function createTooltipManager(\n config: TooltipManagerConfig\n): TooltipManager {\n return new TooltipManager(config);\n}\n","/**\n * SciPlot Engine - Interactive Tools Plugin\n * \n * Provides specialized interaction tools:\n * - Delta Tool: Measurement between two points\n * - Peak Tool: Peak detection and area under curve\n * - Enhanced Tooltips: Point and crosshair tooltips\n * \n * @module plugins/tools\n */\n\nimport { DeltaTool } from \"./delta-tool\";\nimport { PeakTool } from \"./peak-tool\";\nimport { TooltipManager } from \"./tooltip\";\nimport type { PluginManifest, ChartPlugin, PluginContext } from \"../types\";\n\nexport interface PluginToolsConfig {\n /** Enable Delta measurement tool */\n enableDeltaTool?: boolean;\n /** Enable Peak detection tool */\n enablePeakTool?: boolean;\n /** Use advanced tooltip manager */\n useEnhancedTooltips?: boolean;\n}\n\nconst manifestTools: PluginManifest = {\n name: \"velo-plot-tools\",\n version: \"1.0.0\",\n description: \"Advanced interaction and measurement tools for velo-plot\",\n provides: [\"interaction\"],\n tags: [\"delta-tool\", \"peak-tool\", \"tooltip\"],\n};\n\n/**\n * SciPlot Tools Plugin\n * \n * Adds specialized tools for scientific data analysis and interaction.\n */\nexport function PluginTools(_config: PluginToolsConfig = {}): ChartPlugin<PluginToolsConfig> {\n let deltaTool: DeltaTool | null = null;\n let peakTool: PeakTool | null = null;\n let tooltipManager: TooltipManager | null = null;\n\n return {\n manifest: manifestTools,\n\n onInit(ctx: PluginContext) {\n\n // Bridge between PluginContext and DeltaTool/PeakTool context\n const toolContext = {\n container: ctx.ui.container,\n getPlotArea: () => ctx.render.plotArea,\n getViewBounds: () => ctx.data.getViewBounds(),\n getYBounds: (id?: string) => ctx.data.getYAxisBounds(id),\n requestRender: () => ctx.requestRender(),\n getSeries: () => {\n // Transform Series objects to the format expected by DeltaTool/PeakTool\n return ctx.data.getAllSeries().map((s: any) => {\n const data = s.getData();\n return {\n id: s.getId(),\n x: data.x,\n y: data.y,\n yAxisId: s.getYAxisId?.() || undefined\n };\n });\n },\n onMeasure: (m: any) => ctx.events.emit('measure', m)\n };\n\n if (_config.enableDeltaTool ?? true) {\n deltaTool = new DeltaTool(toolContext);\n }\n if (_config.enablePeakTool ?? true) {\n peakTool = new PeakTool(toolContext);\n }\n if (_config.useEnhancedTooltips ?? true) {\n // Safely access internal properties for bridge\n const chart = ctx.chart as any;\n \n // Debug logging\n ctx.log.debug(\"TooltipManager init - checking deps:\", {\n hasCtx2d: !!ctx.render.ctx2d,\n hasXScale: !!chart.xScale,\n hasYScales: !!chart.yScales,\n seriesCount: ctx.data.getAllSeries().length\n });\n \n if (!ctx.render.ctx2d) {\n ctx.log.warn(\"TooltipManager: No 2D context available, tooltips disabled\");\n } else {\n tooltipManager = new TooltipManager({\n overlayCtx: ctx.render.ctx2d,\n chartTheme: ctx.ui.theme,\n getPlotArea: () => ctx.render.plotArea,\n getSeries: () => ctx.data.getAllSeries() as any,\n pixelToDataX: (px) => ctx.coords.pixelToDataX(px),\n pixelToDataY: (py) => ctx.coords.pixelToDataY(py),\n getXScale: () => chart.xScale,\n getYScales: () => chart.yScales,\n getViewBounds: () => ctx.data.getViewBounds(),\n getXAxisOptions: () => ctx.chart.getXAxis(),\n getYAxisOptions: (id) => ctx.chart.getYAxis(id || ctx.chart.getPrimaryYAxisId()),\n options: chart.initialOptions?.tooltip,\n });\n }\n }\n },\n\n onRenderOverlay(_ctx) {\n tooltipManager?.render();\n deltaTool?.renderOverlay();\n peakTool?.renderOverlay();\n },\n\n onDestroy(_ctx: PluginContext) {\n deltaTool?.destroy();\n peakTool?.destroy();\n tooltipManager?.destroy();\n deltaTool = null;\n peakTool = null;\n tooltipManager = null;\n },\n\n api: {\n setMode(mode: 'delta' | 'peak' | 'none') {\n deltaTool?.disable();\n peakTool?.disable();\n\n if (mode === 'delta') deltaTool?.enable();\n if (mode === 'peak') peakTool?.enable();\n },\n getDeltaTool: () => deltaTool,\n getPeakTool: () => peakTool,\n getTooltipManager: () => tooltipManager\n }\n };\n}\n\nexport { DeltaTool, PeakTool, TooltipManager };\nexport default PluginTools;\n"],"names":["DeltaTool","context","options","__publicField","seriesList","updatePoint","p","s","ser","plotArea","bounds","yBounds","p1Valid","p2Valid","rect","dpr","e","pixelX","pixelY","nearestPoint","_a","measurement","series","minDistance","xData","yData","len","i","dataX","dataY","px","py","distance","p1","p2","deltaX","deltaY","slope","opts","ctx","cx","cy","hp","point","label","text","metrics","padding","boxWidth","boxHeight","boxX","boxY","x","y","color","pillWidth","pillHeight","m","midX","midY","lines","lineHeight","container","line","statusText","statusColor","w","h","r","val","abs","PeakTool","seriesFilter","seriesIdFilter","idx1","idx2","win","baselinePointsX","baselinePointsY","n","sumX","sumY","sumXY","sumXX","baselineSlope","baselineIntercept","area","integral","peakHeight","peakX","peakY","x_a","y_a","x_b","y_b","dx","avgY","bl_a","bl_b","avgBL","h_a","seriesYBounds","peakYBounds","peakPX","peakPY","baselineAtPeak","basePY","DEFAULT_PADDING","TOOLTIP_DARK_THEME","TOOLTIP_LIGHT_THEME","TOOLTIP_GLASS_THEME","TOOLTIP_MIDNIGHT_THEME","TOOLTIP_ELECTROCHEM_THEME","TOOLTIP_NEON_THEME","TOOLTIP_MINIMAL_THEME","TOOLTIP_THEMES","getTooltipTheme","name","theme","createTooltipTheme","base","overrides","baseTheme","getTooltipThemeForChartTheme","chartThemeName","DEFAULT_TOOLTIP_THEME","DEFAULT_POSITIONER_CONFIG","TooltipPositioner","config","width","height","targetX","targetY","offset","preferredPosition","autoFlip","showArrow","arrowSize","totalWidth","totalHeight","position","arrowPosition","wasFlipped","flippedPosition","flipped","constrained","arrowOffset","idealArrowX","idealArrowY","preferred","spaceTop","spaceBottom","spaceLeft","spaceRight","canFitTop","canFitBottom","canFitRight","canFitLeft","a","b","margin","constrainedX","constrainedY","cursorX","cursorY","TooltipRenderer","data","template","_arrowPosition","gradient","size","topX","bottomX","bottomY","leftY","rightX","rightY","radius","fontSize","fontWeight","align","baseline","value","maxWidth","formatDataPointX","formatTooltipX","formatFallbackNumber","formatDataPointY","formatTooltipY","formatCrosshairX","formatCrosshairY","absVal","formatCompactValue","axis","formatValue","DefaultTooltipTemplate","cacheKey","titleWidth","labelWidth","xValWidth","yValWidth","contentWidth","contentHeight","errorText","cycleText","indicatorWidth","currentX","currentY","indicatorY","separatorWidth","defaultTooltipTemplate","MinimalTooltipTemplate","textWidth","xValue","yValue","xWidth","sepWidth","minimalTooltipTemplate","SPACING","CrosshairTooltipTemplate","seriesHash","nameWidth","valWidth","lineWidth","headerHeight","formatted","contentX","itemX","labelOffset","crosshairTooltipTemplate","HeatmapTooltipTemplate","headerText","valueText","valueWidth","scaleText","xyLabelWidth","dataXWidth","dataYWidth","swatchY","heatmapTooltipTemplate","formatXValue","_b","toScientificUnicode","formatYValue","precision","exp","mantissa","superscripts","expStr","superExp","char","ScientificTooltipTemplate","xVal","yVal","yWidth","footerText","lineCount","extraGap","yText","scientificTooltipTemplate","AnnotationTooltipTemplate","valText","xText","labelW","annotationTooltipTemplate","RangeTooltipTemplate","stats","renderLine","rangeTooltipTemplate","BUILTIN_TEMPLATES","getBuiltinTemplate","id","getDefaultTemplateForType","type","TooltipManager","EventEmitter","enabled","suspended","chartTheme","total","newResult","currentPoint","currentDx","currentDy","currentDistSq","newDx","newDy","heatmapResult","crosshairData","yAxisId","xSpan","xScale","yScales","cursorDataX","bestResult","bestXDistance","yScale","idx","xDistance","style","_c","yError","hitRadius","nearestDistanceSq","nearestResult","closestIdx","dataLength","searchRadius","checkStart","checkEnd","dy","distSq","_d","colIdx","rowIdx","zValue","arr","target","left","right","mid","interpolatedValues","isInterpolated","x0","x1","y0","y1","t","dp","effectiveDelay","templateId","tooltipId","tooltip","tooltipData","event","handler","manifestTools","PluginTools","_config","deltaTool","peakTool","tooltipManager","toolContext","chart","_ctx","mode"],"mappings":"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"}
|