velo-plot 3.1.0 → 4.0.0-alpha.1

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.
Files changed (116) hide show
  1. package/dist/{ChartCore-AnR_3Xkb.js → ChartCore-KYG2HTcK.js} +1349 -1213
  2. package/dist/ChartCore-KYG2HTcK.js.map +1 -0
  3. package/dist/{PluginRegistry-CzMHebYP.js → PluginRegistry-CDf_jcnp.js} +2 -2
  4. package/dist/{PluginRegistry-CzMHebYP.js.map → PluginRegistry-CDf_jcnp.js.map} +1 -1
  5. package/dist/SVGDocumentBuilder-C-uLkcFW.js +83 -0
  6. package/dist/SVGDocumentBuilder-C-uLkcFW.js.map +1 -0
  7. package/dist/angular-hooks.js +1 -1
  8. package/dist/angular.js +4 -4
  9. package/dist/{chartSyncBridge-D_rCtbFq.js → chartSyncBridge-C1uRy0ZS.js} +3 -3
  10. package/dist/{chartSyncBridge-D_rCtbFq.js.map → chartSyncBridge-C1uRy0ZS.js.map} +1 -1
  11. package/dist/core/chart/ChartCore.d.ts +7 -3
  12. package/dist/core/chart/ChartRenderLoop.d.ts +5 -0
  13. package/dist/core/chart/ChartRenderer.d.ts +9 -0
  14. package/dist/core/chart/ChartSetup.d.ts +1 -0
  15. package/dist/core/chart/exporter/SVGExporter.d.ts +9 -7
  16. package/dist/core/chart/exporter/svg/SVGDocumentBuilder.d.ts +27 -0
  17. package/dist/core/chart/exporter/svg/SVGExportContext.d.ts +147 -0
  18. package/dist/core/chart/exporter/svg/SVGOrchestrator.d.ts +3 -0
  19. package/dist/core/chart/exporter/svg/SVGThemeAdapter.d.ts +22 -0
  20. package/dist/core/chart/exporter/svg/__tests__/testFixtures.d.ts +46 -0
  21. package/dist/core/chart/exporter/svg/__tests__/visualTestUtils.d.ts +12 -0
  22. package/dist/core/chart/exporter/svg/overlay/axes.d.ts +4 -0
  23. package/dist/core/chart/exporter/svg/overlay/border.d.ts +4 -0
  24. package/dist/core/chart/exporter/svg/overlay/errorBars.d.ts +7 -0
  25. package/dist/core/chart/exporter/svg/overlay/grid.d.ts +4 -0
  26. package/dist/core/chart/exporter/svg/overlay/index.d.ts +12 -0
  27. package/dist/core/chart/exporter/svg/overlay/legend.d.ts +4 -0
  28. package/dist/core/chart/exporter/svg/overlay/pluginCharts.d.ts +6 -0
  29. package/dist/core/chart/exporter/svg/overlay/polarGrid.d.ts +4 -0
  30. package/dist/core/chart/exporter/svg/overlay/specialChart.d.ts +15 -0
  31. package/dist/core/chart/exporter/svg/overlay/title.d.ts +4 -0
  32. package/dist/core/chart/exporter/svg/plugins/annotations.d.ts +5 -0
  33. package/dist/core/chart/exporter/svg/plugins/brokenAxis.d.ts +20 -0
  34. package/dist/core/chart/exporter/svg/plugins/latex.d.ts +9 -0
  35. package/dist/core/chart/exporter/svg/plugins/register.d.ts +8 -0
  36. package/dist/core/chart/exporter/svg/plugins/regression.d.ts +33 -0
  37. package/dist/core/chart/exporter/svg/plugins/roi.d.ts +12 -0
  38. package/dist/core/chart/exporter/svg/plugins/tradeMarkers.d.ts +3 -0
  39. package/dist/core/chart/exporter/svg/plugins/types.d.ts +28 -0
  40. package/dist/core/chart/exporter/svg/plugins/watermark.d.ts +13 -0
  41. package/dist/core/chart/exporter/svg/series/band.d.ts +6 -0
  42. package/dist/core/chart/exporter/svg/series/bar.d.ts +6 -0
  43. package/dist/core/chart/exporter/svg/series/boxplot.d.ts +6 -0
  44. package/dist/core/chart/exporter/svg/series/candlestick.d.ts +6 -0
  45. package/dist/core/chart/exporter/svg/series/finitePoints.d.ts +6 -0
  46. package/dist/core/chart/exporter/svg/series/gauge.d.ts +5 -0
  47. package/dist/core/chart/exporter/svg/series/heatmap.d.ts +6 -0
  48. package/dist/core/chart/exporter/svg/series/indicator.d.ts +6 -0
  49. package/dist/core/chart/exporter/svg/series/line.d.ts +12 -0
  50. package/dist/core/chart/exporter/svg/series/polar.d.ts +6 -0
  51. package/dist/core/chart/exporter/svg/series/radar.d.ts +5 -0
  52. package/dist/core/chart/exporter/svg/series/registry.d.ts +10 -0
  53. package/dist/core/chart/exporter/svg/series/sankey.d.ts +5 -0
  54. package/dist/core/chart/exporter/svg/series/scatter.d.ts +1 -0
  55. package/dist/core/chart/exporter/svg/series/ternary.d.ts +7 -0
  56. package/dist/core/chart/exporter/svg/series/waterfall.d.ts +6 -0
  57. package/dist/core/chart/exporter/svg/seriesAtTimestamp.d.ts +4 -0
  58. package/dist/core/chart/exporter/svg/seriesUtils.d.ts +3 -0
  59. package/dist/core/chart/exporter/svg/symbols.d.ts +5 -0
  60. package/dist/core/chart/exporter/svg/tickUtils.d.ts +9 -0
  61. package/dist/core/chart/mountSVGString.d.ts +5 -0
  62. package/dist/core/chart/types.d.ts +2 -2
  63. package/dist/core/stacked/StackSVGComposer.d.ts +14 -0
  64. package/dist/core/stacked/index.d.ts +3 -2
  65. package/dist/core/stacked/types.d.ts +12 -4
  66. package/dist/createStackedChart-DjA3aJAu.js +2761 -0
  67. package/dist/createStackedChart-DjA3aJAu.js.map +1 -0
  68. package/dist/{hooks-DH-3bewj.js → hooks-4wQH27r9.js} +3 -3
  69. package/dist/{hooks-DH-3bewj.js.map → hooks-4wQH27r9.js.map} +1 -1
  70. package/dist/index-Bj-xyXY6.js +582 -0
  71. package/dist/index-Bj-xyXY6.js.map +1 -0
  72. package/dist/plugins/PluginManager.d.ts +5 -0
  73. package/dist/plugins/annotations.js +8 -7
  74. package/dist/plugins/annotations.js.map +1 -1
  75. package/dist/plugins/broken-axis.js +198 -152
  76. package/dist/plugins/broken-axis.js.map +1 -1
  77. package/dist/plugins/forecasting.js +273 -258
  78. package/dist/plugins/forecasting.js.map +1 -1
  79. package/dist/plugins/ml-integration.js +107 -93
  80. package/dist/plugins/ml-integration.js.map +1 -1
  81. package/dist/plugins/radar/types.d.ts +11 -0
  82. package/dist/plugins/radar.js +64 -53
  83. package/dist/plugins/radar.js.map +1 -1
  84. package/dist/plugins/roi/index.d.ts +2 -0
  85. package/dist/plugins/roi.js +184 -145
  86. package/dist/plugins/roi.js.map +1 -1
  87. package/dist/plugins/snapshot.js +20 -15
  88. package/dist/plugins/snapshot.js.map +1 -1
  89. package/dist/plugins/types.d.ts +4 -0
  90. package/dist/react.js +2 -2
  91. package/dist/regression-HNdyk1Dm.js +28 -0
  92. package/dist/regression-HNdyk1Dm.js.map +1 -0
  93. package/dist/renderer/ChartSeriesRenderer.d.ts +3 -2
  94. package/dist/renderer/SVGChartRenderer.d.ts +15 -0
  95. package/dist/renderer/SankeyRenderer.d.ts +1 -0
  96. package/dist/renderer/registerSVG.d.ts +5 -0
  97. package/dist/renderer/sankeyLayout.d.ts +29 -0
  98. package/dist/scientific.js +2 -2
  99. package/dist/solid.js +2 -2
  100. package/dist/svelte.js +2 -2
  101. package/dist/tickUtils-B_X-ha13.js +41 -0
  102. package/dist/tickUtils-B_X-ha13.js.map +1 -0
  103. package/dist/trading.js +3 -3
  104. package/dist/types.d.ts +2 -1
  105. package/dist/velo-plot.full.js +1107 -1292
  106. package/dist/velo-plot.full.js.map +1 -1
  107. package/dist/velo-plot.js +2 -2
  108. package/dist/vue/VeloPlot.vue.d.ts +1 -1
  109. package/dist/vue/index.d.ts +33 -33
  110. package/dist/vue.js +2 -2
  111. package/package.json +6 -1
  112. package/dist/ChartCore-AnR_3Xkb.js.map +0 -1
  113. package/dist/createStackedChart-DqcLCFGS.js +0 -1338
  114. package/dist/createStackedChart-DqcLCFGS.js.map +0 -1
  115. package/dist/index-Cv6ZDLWf.js +0 -521
  116. package/dist/index-Cv6ZDLWf.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-Bj-xyXY6.js","sources":["../src/core/chart/heikinAshi.ts","../src/trading/datafeed.ts","../src/trading/mockDatafeed.ts","../src/plugins/drawing-tools/snapToCandle.ts","../src/plugins/drawing-tools/measure.ts","../src/plugins/drawing-tools/index.ts","../src/plugins/replay/index.ts"],"sourcesContent":["/**\n * Heikin-Ashi OHLC transform (Stage 2.20).\n */\n\nexport interface OhlcArrays {\n open: Float32Array | Float64Array;\n high: Float32Array | Float64Array;\n low: Float32Array | Float64Array;\n close: Float32Array | Float64Array;\n}\n\nexport function computeHeikinAshi(ohlc: OhlcArrays): OhlcArrays {\n const n = ohlc.close.length;\n const haOpen = new Float32Array(n);\n const haHigh = new Float32Array(n);\n const haLow = new Float32Array(n);\n const haClose = new Float32Array(n);\n\n for (let i = 0; i < n; i++) {\n const o = ohlc.open[i];\n const h = ohlc.high[i];\n const l = ohlc.low[i];\n const c = ohlc.close[i];\n\n haClose[i] = (o + h + l + c) / 4;\n haOpen[i] = i === 0 ? (o + c) / 2 : (haOpen[i - 1] + haClose[i - 1]) / 2;\n haHigh[i] = Math.max(h, haOpen[i], haClose[i]);\n haLow[i] = Math.min(l, haOpen[i], haClose[i]);\n }\n\n return { open: haOpen, high: haHigh, low: haLow, close: haClose };\n}\n","/**\n * UDF-inspired datafeed contract for trading charts (Stage 2.24).\n */\n\nexport interface SymbolInfo {\n symbol: string;\n name: string;\n description?: string;\n timezone?: string;\n session?: string;\n pricescale?: number;\n minmov?: number;\n}\n\nexport interface Bar {\n time: number;\n open: number;\n high: number;\n low: number;\n close: number;\n volume?: number;\n}\n\nexport interface HistoryRequest {\n symbol: string;\n resolution: string;\n from: number;\n to: number;\n}\n\nexport interface SubscribeBarsRequest {\n symbol: string;\n resolution: string;\n onBar: (bar: Bar) => void;\n}\n\n/**\n * TradingView UDF-style adapter surface.\n */\nexport interface DatafeedAdapter {\n resolveSymbol(symbol: string): Promise<SymbolInfo>;\n getBars(request: HistoryRequest): Promise<Bar[]>;\n subscribeBars(request: SubscribeBarsRequest): () => void;\n}\n\n/** Convert bars to typed OHLC arrays for velo-plot series. */\nexport function barsToOhlc(bars: Bar[]): {\n x: Float64Array;\n open: Float32Array;\n high: Float32Array;\n low: Float32Array;\n close: Float32Array;\n volume: Float32Array;\n} {\n const n = bars.length;\n const x = new Float64Array(n);\n const open = new Float32Array(n);\n const high = new Float32Array(n);\n const low = new Float32Array(n);\n const close = new Float32Array(n);\n const volume = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const b = bars[i];\n x[i] = b.time;\n open[i] = b.open;\n high[i] = b.high;\n low[i] = b.low;\n close[i] = b.close;\n volume[i] = b.volume ?? 0;\n }\n return { x, open, high, low, close, volume };\n}\n","/**\n * Mock datafeed for demos and tests (Stage 2.25).\n */\n\nimport type {\n Bar,\n DatafeedAdapter,\n HistoryRequest,\n SubscribeBarsRequest,\n SymbolInfo,\n} from \"./datafeed\";\n\nexport interface MockDatafeedOptions {\n symbol?: string;\n barMs?: number;\n basePrice?: number;\n seed?: number;\n}\n\nfunction pseudoRandom(seed: number): () => number {\n let s = seed;\n return () => {\n s = (s * 16807) % 2147483647;\n return (s - 1) / 2147483646;\n };\n}\n\nfunction generateBars(from: number, to: number, barMs: number, base: number, rand: () => number): Bar[] {\n const bars: Bar[] = [];\n let price = base;\n for (let t = from; t <= to; t += barMs) {\n const open = price;\n const delta = (rand() - 0.48) * 2;\n const close = Math.max(1, open + delta);\n const high = Math.max(open, close) + rand() * 1.5;\n const low = Math.min(open, close) - rand() * 1.5;\n bars.push({\n time: t,\n open,\n high,\n low,\n close,\n volume: 1000 + rand() * 5000,\n });\n price = close;\n }\n return bars;\n}\n\nexport function createMockDatafeed(options: MockDatafeedOptions = {}): DatafeedAdapter {\n const barMs = options.barMs ?? 60_000;\n const basePrice = options.basePrice ?? 100;\n const rand = pseudoRandom(options.seed ?? 42);\n const cache = new Map<string, Bar[]>();\n\n return {\n async resolveSymbol(sym: string): Promise<SymbolInfo> {\n return {\n symbol: sym,\n name: sym,\n description: `Mock symbol ${sym}`,\n timezone: \"UTC\",\n session: \"24x7\",\n pricescale: 100,\n };\n },\n\n async getBars(request: HistoryRequest): Promise<Bar[]> {\n const key = `${request.symbol}:${request.from}:${request.to}`;\n if (!cache.has(key)) {\n cache.set(\n key,\n generateBars(request.from, request.to, barMs, basePrice, rand),\n );\n }\n return cache.get(key)!;\n },\n\n subscribeBars(request: SubscribeBarsRequest): () => void {\n let last = basePrice + rand() * 5;\n const timer = setInterval(() => {\n const open = last;\n const close = Math.max(1, open + (rand() - 0.5) * 2);\n const high = Math.max(open, close) + rand();\n const low = Math.min(open, close) - rand();\n request.onBar({\n time: Date.now(),\n open,\n high,\n low,\n close,\n volume: 1000 + rand() * 3000,\n });\n last = close;\n }, barMs);\n return () => clearInterval(timer);\n },\n };\n}\n","/**\n * Snap drawing points to nearest candlestick O/H/L/C (TradingView-style magnet).\n */\n\nexport interface CandleSnapInput {\n x: number;\n y: number;\n barX: Float32Array | Float64Array;\n open: Float32Array | Float64Array;\n high: Float32Array | Float64Array;\n low: Float32Array | Float64Array;\n close: Float32Array | Float64Array;\n dataToPixelX: (x: number) => number;\n dataToPixelY: (y: number) => number;\n pixelThreshold?: number;\n enabled?: boolean;\n}\n\nexport function findNearestBarIndex(\n barX: Float32Array | Float64Array,\n x: number,\n): number {\n if (barX.length === 0) return -1;\n let bestIdx = 0;\n let bestDist = Math.abs(barX[0] - x);\n for (let i = 1; i < barX.length; i++) {\n const d = Math.abs(barX[i] - x);\n if (d < bestDist) {\n bestDist = d;\n bestIdx = i;\n }\n }\n return bestIdx;\n}\n\nexport function snapToCandle(input: CandleSnapInput): { x: number; y: number } {\n if (input.enabled === false || input.barX.length === 0) {\n return { x: input.x, y: input.y };\n }\n\n const idx = findNearestBarIndex(input.barX, input.x);\n if (idx < 0) return { x: input.x, y: input.y };\n\n const barX = input.barX[idx];\n const candidates = [\n input.open[idx],\n input.high[idx],\n input.low[idx],\n input.close[idx],\n ];\n\n const clickPy = input.dataToPixelY(input.y);\n const threshold = input.pixelThreshold ?? 12;\n let bestY = input.y;\n let bestPyDist = Infinity;\n\n for (const cy of candidates) {\n const py = input.dataToPixelY(cy);\n const dist = Math.abs(py - clickPy);\n if (dist < bestPyDist && dist <= threshold) {\n bestPyDist = dist;\n bestY = cy;\n }\n }\n\n return { x: barX, y: bestY };\n}\n","/**\n * Measurement helper for the price-range / measure tool (TradingView-style).\n */\n\nexport interface MeasurePoint {\n x: number;\n y: number;\n}\n\nexport interface Measurement {\n /** Absolute price change (end - start) */\n change: number;\n /** Percentage change relative to the start price */\n percent: number;\n /** Number of bars spanned (rounded X distance) */\n bars: number;\n /** True when the range moves up (change >= 0) */\n up: boolean;\n}\n\nexport function computeMeasurement(a: MeasurePoint, b: MeasurePoint): Measurement {\n const change = b.y - a.y;\n const denom = Math.abs(a.y);\n const percent = denom > 0 ? (change / denom) * 100 : 0;\n const bars = Math.round(Math.abs(b.x - a.x));\n return { change, percent, bars, up: change >= 0 };\n}\n\nexport function formatMeasurement(m: Measurement): string {\n const sign = m.change >= 0 ? \"+\" : \"\";\n return `${sign}${m.change.toFixed(2)} (${sign}${m.percent.toFixed(2)}%) · ${m.bars} bars`;\n}\n\n/** Compact price formatting used for level labels. */\nexport function formatPrice(value: number): string {\n const abs = Math.abs(value);\n const decimals = abs >= 1000 ? 0 : abs >= 1 ? 2 : 4;\n return value.toLocaleString(\"en-US\", {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n });\n}\n","/**\n * PluginDrawingTools — interactive drawing on chart (Stage 2.9).\n * TradingView-style live preview, drag-to-draw, optional candle magnet.\n */\n\nimport type { ChartPlugin, InteractionEvent, PluginContext, PluginManifest } from \"../types\";\nimport type { Annotation } from \"../../core/annotations/types\";\nimport type { Series } from \"../../core/Series\";\nimport type { SVGExportPluginContext } from \"../../core/chart/exporter/svg/plugins/types\";\nimport { fmt } from \"../../core/chart/exporter/svg/SVGDocumentBuilder\";\nimport { primaryYScale } from \"../../core/chart/exporter/svg/tickUtils\";\nimport { snapToCandle } from \"./snapToCandle\";\nimport { computeMeasurement, formatMeasurement, formatPrice } from \"./measure\";\n\nexport type DrawingMode =\n | \"none\"\n | \"pan\"\n | \"trendline\"\n | \"horizontal\"\n | \"vertical\"\n | \"rectangle\"\n | \"fibonacci\"\n | \"measure\";\n\nconst FIB_LEVELS = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1];\nconst DRAG_THRESHOLD_PX = 4;\nconst DEFAULT_MEASURE_UP = \"#26a69a\";\nconst DEFAULT_MEASURE_DOWN = \"#ef5350\";\n\nexport interface PluginDrawingToolsConfig {\n /** Default stroke color */\n color?: string;\n /** Enable candle magnet by default */\n magnet?: boolean;\n /** Return to pan mode after each completed stroke (default true) */\n autoDeselect?: boolean;\n /** Notified when drawing mode changes (including auto-deselect to none) */\n onModeChange?: (mode: DrawingMode) => void;\n /** Color for upward measurements (default green) */\n measureUpColor?: string;\n /** Color for downward measurements (default red) */\n measureDownColor?: string;\n}\n\nfunction withAlpha(color: string, alpha: string): string {\n return color.startsWith(\"#\") && color.length === 7 ? color + alpha : color;\n}\n\nexport interface DrawingToolsAPI {\n setMode(mode: DrawingMode): void;\n getMode(): DrawingMode;\n setMagnet(enabled: boolean): void;\n isMagnet(): boolean;\n undo(): boolean;\n redo(): boolean;\n clear(): void;\n}\n\nconst manifest: PluginManifest = {\n name: \"velo-plot-drawing-tools\",\n version: \"1.0.0\",\n description: \"Interactive trendline, horizontal, vertical, rectangle, and fibonacci drawing\",\n provides: [\"drawing\"],\n tags: [\"drawing\", \"annotations\", \"trading\"],\n};\n\ninterface DrawPoint {\n x: number;\n y: number;\n}\n\ninterface DrawState {\n mode: DrawingMode;\n pending: DrawPoint | null;\n start: DrawPoint | null;\n dragging: boolean;\n dragMoved: boolean;\n dragStartPixel: { x: number; y: number } | null;\n cursor: DrawPoint | null;\n magnet: boolean;\n undoStack: Annotation[][];\n redoStack: Annotation[][];\n}\n\nfunction isDrawingMode(mode: DrawingMode): boolean {\n return mode !== \"none\" && mode !== \"pan\";\n}\n\nfunction findCandlestickSeries(ctx: PluginContext): Series | undefined {\n for (const s of ctx.data.getAllSeries()) {\n if (s.getType() === \"candlestick\") return s;\n }\n return undefined;\n}\n\nexport function PluginDrawingTools(\n config: PluginDrawingToolsConfig = {},\n): ChartPlugin<PluginDrawingToolsConfig> {\n let ctx: PluginContext | null = null;\n const autoDeselect = config.autoDeselect !== false;\n const state: DrawState = {\n mode: \"none\",\n pending: null,\n start: null,\n dragging: false,\n dragMoved: false,\n dragStartPixel: null,\n cursor: null,\n magnet: config.magnet ?? false,\n undoStack: [],\n redoStack: [],\n };\n\n const stroke = config.color ?? \"#38bdf8\";\n const measureUp = config.measureUpColor ?? DEFAULT_MEASURE_UP;\n const measureDown = config.measureDownColor ?? DEFAULT_MEASURE_DOWN;\n\n function snapshot(): Annotation[] {\n return ctx?.chart.getAnnotations?.() ?? [];\n }\n\n function pushUndo(): void {\n state.undoStack.push(snapshot());\n state.redoStack = [];\n }\n\n function resetInteractionState(): void {\n state.pending = null;\n state.start = null;\n state.dragging = false;\n state.dragMoved = false;\n state.dragStartPixel = null;\n }\n\n function setModeInternal(mode: DrawingMode): void {\n state.mode = mode;\n resetInteractionState();\n config.onModeChange?.(mode);\n ctx?.requestRender?.();\n }\n\n function finishStroke(): void {\n resetInteractionState();\n if (autoDeselect) {\n setModeInternal(\"none\");\n } else {\n ctx?.requestRender?.();\n }\n }\n\n function resolvePoint(x: number, y: number): DrawPoint {\n if (!ctx || !state.magnet) return { x, y };\n const series = findCandlestickSeries(ctx);\n if (!series) return { x, y };\n const d = series.getData();\n if (!d.open || !d.high || !d.low || !d.close) return { x, y };\n return snapToCandle({\n x,\n y,\n barX: d.x,\n open: d.open,\n high: d.high,\n low: d.low,\n close: d.close,\n dataToPixelX: ctx.coords.dataToPixelX,\n dataToPixelY: (dy) => ctx!.coords.dataToPixelY(dy),\n enabled: true,\n });\n }\n\n function pointFromEvent(pluginCtx: PluginContext, event: InteractionEvent): DrawPoint {\n return resolvePoint(\n pluginCtx.coords.pixelToDataX(event.pixelX),\n pluginCtx.coords.pixelToDataY(event.pixelY),\n );\n }\n\n function commitHorizontal(y: number): void {\n if (!ctx) return;\n pushUndo();\n ctx.chart.addAnnotation({\n type: \"horizontal-line\",\n y,\n color: stroke,\n interactive: true,\n });\n }\n\n function commitVertical(x: number): void {\n if (!ctx) return;\n pushUndo();\n ctx.chart.addAnnotation({\n type: \"vertical-line\",\n x,\n color: stroke,\n interactive: true,\n });\n }\n\n function commitMeasure(p0: DrawPoint, p1: DrawPoint): void {\n if (!ctx) return;\n pushUndo();\n\n const m = computeMeasurement(p0, p1);\n const color = m.up ? measureUp : measureDown;\n const midX = (p0.x + p1.x) / 2;\n ctx.chart.addAnnotation({\n type: \"rectangle\",\n xMin: Math.min(p0.x, p1.x),\n xMax: Math.max(p0.x, p1.x),\n yMin: Math.min(p0.y, p1.y),\n yMax: Math.max(p0.y, p1.y),\n strokeColor: color,\n fillColor: withAlpha(color, \"33\"),\n interactive: true,\n });\n ctx.chart.addAnnotation({\n type: \"arrow\",\n x1: midX,\n y1: p0.y,\n x2: midX,\n y2: p1.y,\n color,\n headStyle: \"filled\",\n interactive: true,\n });\n ctx.chart.addAnnotation({\n type: \"text\",\n x: midX,\n y: p1.y,\n text: formatMeasurement(m),\n color: \"#ffffff\",\n backgroundColor: color,\n padding: 4,\n fontWeight: \"bold\",\n anchor: m.up ? \"bottom-center\" : \"top-center\",\n interactive: true,\n });\n }\n\n function commitTwoPoint(p0: DrawPoint, p1: DrawPoint): void {\n if (!ctx) return;\n\n if (state.mode === \"measure\") {\n commitMeasure(p0, p1);\n return;\n }\n\n pushUndo();\n\n if (state.mode === \"trendline\") {\n ctx.chart.addAnnotation({\n type: \"arrow\",\n x1: p0.x,\n y1: p0.y,\n x2: p1.x,\n y2: p1.y,\n color: stroke,\n interactive: true,\n });\n } else if (state.mode === \"rectangle\") {\n ctx.chart.addAnnotation({\n type: \"rectangle\",\n xMin: Math.min(p0.x, p1.x),\n xMax: Math.max(p0.x, p1.x),\n yMin: Math.min(p0.y, p1.y),\n yMax: Math.max(p0.y, p1.y),\n strokeColor: stroke,\n fillColor: stroke + \"22\",\n interactive: true,\n });\n } else if (state.mode === \"fibonacci\") {\n const yMin = Math.min(p0.y, p1.y);\n const yMax = Math.max(p0.y, p1.y);\n for (const level of FIB_LEVELS) {\n const fy = yMax - (yMax - yMin) * level;\n ctx.chart.addAnnotation({\n type: \"horizontal-line\",\n y: fy,\n color: stroke,\n lineDash: level === 0 || level === 1 ? undefined : [4, 4],\n label: `${(level * 100).toFixed(1)}% ${formatPrice(fy)}`,\n labelPosition: \"right\",\n interactive: true,\n });\n }\n }\n }\n\n function drawPreview(\n c2d: CanvasRenderingContext2D,\n plotArea: { x: number; y: number; width: number; height: number },\n coords: PluginContext[\"coords\"],\n ): void {\n const mode = state.mode;\n if (!isDrawingMode(mode) || !state.cursor) return;\n\n const cursor = state.cursor;\n const anchor = state.pending ?? state.start;\n\n c2d.save();\n c2d.strokeStyle = stroke;\n c2d.lineWidth = 1.5;\n c2d.setLineDash([6, 4]);\n c2d.globalAlpha = 0.85;\n\n const toPx = (x: number, y: number) => ({\n px: coords.dataToPixelX(x),\n py: coords.dataToPixelY(y),\n });\n\n if (mode === \"horizontal\") {\n const { py } = toPx(0, cursor.y);\n c2d.beginPath();\n c2d.moveTo(plotArea.x, py);\n c2d.lineTo(plotArea.x + plotArea.width, py);\n c2d.stroke();\n } else if (mode === \"vertical\") {\n const { px } = toPx(cursor.x, 0);\n c2d.beginPath();\n c2d.moveTo(px, plotArea.y);\n c2d.lineTo(px, plotArea.y + plotArea.height);\n c2d.stroke();\n } else if (anchor) {\n const a = toPx(anchor.x, anchor.y);\n const b = toPx(cursor.x, cursor.y);\n\n if (mode === \"trendline\") {\n c2d.beginPath();\n c2d.moveTo(a.px, a.py);\n c2d.lineTo(b.px, b.py);\n c2d.stroke();\n } else if (mode === \"rectangle\") {\n const x = Math.min(a.px, b.px);\n const y = Math.min(a.py, b.py);\n const w = Math.abs(b.px - a.px);\n const h = Math.abs(b.py - a.py);\n c2d.strokeRect(x, y, w, h);\n c2d.fillStyle = stroke + \"22\";\n c2d.fillRect(x, y, w, h);\n } else if (mode === \"fibonacci\") {\n const yMin = Math.min(anchor.y, cursor.y);\n const yMax = Math.max(anchor.y, cursor.y);\n c2d.font = \"11px sans-serif\";\n c2d.textAlign = \"left\";\n c2d.textBaseline = \"bottom\";\n for (const level of FIB_LEVELS) {\n const fy = yMax - (yMax - yMin) * level;\n const { py } = toPx(0, fy);\n c2d.beginPath();\n c2d.moveTo(plotArea.x, py);\n c2d.lineTo(plotArea.x + plotArea.width, py);\n c2d.stroke();\n c2d.save();\n c2d.setLineDash([]);\n c2d.globalAlpha = 1;\n c2d.fillStyle = stroke;\n c2d.fillText(\n `${(level * 100).toFixed(1)}% ${formatPrice(fy)}`,\n plotArea.x + 4,\n py - 2,\n );\n c2d.restore();\n }\n } else if (mode === \"measure\") {\n drawMeasurePreview(c2d, a, b, anchor, cursor);\n }\n }\n\n c2d.restore();\n }\n\n function drawMeasurePreview(\n c2d: CanvasRenderingContext2D,\n a: { px: number; py: number },\n b: { px: number; py: number },\n anchor: DrawPoint,\n cursor: DrawPoint,\n ): void {\n const m = computeMeasurement(anchor, cursor);\n const color = m.up ? measureUp : measureDown;\n const x = Math.min(a.px, b.px);\n const y = Math.min(a.py, b.py);\n const w = Math.abs(b.px - a.px);\n const h = Math.abs(b.py - a.py);\n\n c2d.setLineDash([]);\n c2d.globalAlpha = 0.9;\n c2d.fillStyle = withAlpha(color, \"33\");\n c2d.fillRect(x, y, w, h);\n c2d.strokeStyle = color;\n c2d.lineWidth = 1.5;\n c2d.strokeRect(x, y, w, h);\n\n // Vertical direction arrow at the horizontal center.\n const midX = (a.px + b.px) / 2;\n c2d.beginPath();\n c2d.moveTo(midX, a.py);\n c2d.lineTo(midX, b.py);\n c2d.stroke();\n const headLen = 7;\n const dir = b.py >= a.py ? 1 : -1;\n c2d.beginPath();\n c2d.moveTo(midX, b.py);\n c2d.lineTo(midX - 4, b.py - dir * headLen);\n c2d.lineTo(midX + 4, b.py - dir * headLen);\n c2d.closePath();\n c2d.fillStyle = color;\n c2d.fill();\n\n // Label with change / percent / bars.\n const label = formatMeasurement(m);\n c2d.font = \"12px sans-serif\";\n const textW = c2d.measureText(label).width;\n const padX = 6;\n const boxW = textW + padX * 2;\n const boxH = 20;\n const boxX = midX - boxW / 2;\n const boxY = m.up ? b.py - boxH - 8 : b.py + 8;\n c2d.globalAlpha = 1;\n c2d.fillStyle = color;\n c2d.fillRect(boxX, boxY, boxW, boxH);\n c2d.fillStyle = \"#ffffff\";\n c2d.textAlign = \"center\";\n c2d.textBaseline = \"middle\";\n c2d.fillText(label, midX, boxY + boxH / 2);\n }\n\n /**\n * SVG mirror of {@link drawPreview}. Emits the in-progress stroke only —\n * committed annotations are owned/exported by the annotations plugin, so\n * re-exporting them here would double-render in live SVG snapshots.\n */\n function previewToSVG(svgCtx: SVGExportPluginContext): string[] {\n const mode = state.mode;\n if (!isDrawingMode(mode) || !state.cursor) return [];\n\n const yScale =\n primaryYScale(svgCtx.yScales) ?? [...svgCtx.yScales.values()][0];\n if (!yScale) return [];\n\n const plotArea = svgCtx.plotArea;\n const cursor = state.cursor;\n const anchor = state.pending ?? state.start;\n const toPx = (x: number, y: number) => ({\n px: svgCtx.xScale.transform(x),\n py: yScale.transform(y),\n });\n const dash = `stroke-dasharray=\"6,4\"`;\n const els: string[] = [];\n\n if (mode === \"horizontal\") {\n const { py } = toPx(0, cursor.y);\n els.push(\n `<line x1=\"${fmt(plotArea.x)}\" y1=\"${fmt(py)}\" x2=\"${fmt(plotArea.x + plotArea.width)}\" y2=\"${fmt(py)}\" stroke=\"${stroke}\" stroke-width=\"1.5\" ${dash}/>`,\n );\n } else if (mode === \"vertical\") {\n const { px } = toPx(cursor.x, 0);\n els.push(\n `<line x1=\"${fmt(px)}\" y1=\"${fmt(plotArea.y)}\" x2=\"${fmt(px)}\" y2=\"${fmt(plotArea.y + plotArea.height)}\" stroke=\"${stroke}\" stroke-width=\"1.5\" ${dash}/>`,\n );\n } else if (anchor) {\n const a = toPx(anchor.x, anchor.y);\n const b = toPx(cursor.x, cursor.y);\n\n if (mode === \"trendline\") {\n els.push(\n `<line x1=\"${fmt(a.px)}\" y1=\"${fmt(a.py)}\" x2=\"${fmt(b.px)}\" y2=\"${fmt(b.py)}\" stroke=\"${stroke}\" stroke-width=\"1.5\" ${dash}/>`,\n );\n } else if (mode === \"rectangle\") {\n const x = Math.min(a.px, b.px);\n const y = Math.min(a.py, b.py);\n const w = Math.abs(b.px - a.px);\n const h = Math.abs(b.py - a.py);\n els.push(\n `<rect x=\"${fmt(x)}\" y=\"${fmt(y)}\" width=\"${fmt(w)}\" height=\"${fmt(h)}\" fill=\"${stroke}22\" stroke=\"${stroke}\" stroke-width=\"1.5\" ${dash}/>`,\n );\n } else if (mode === \"fibonacci\") {\n const yMin = Math.min(anchor.y, cursor.y);\n const yMax = Math.max(anchor.y, cursor.y);\n for (const level of FIB_LEVELS) {\n const fy = yMax - (yMax - yMin) * level;\n const { py } = toPx(0, fy);\n els.push(\n `<line x1=\"${fmt(plotArea.x)}\" y1=\"${fmt(py)}\" x2=\"${fmt(plotArea.x + plotArea.width)}\" y2=\"${fmt(py)}\" stroke=\"${stroke}\" stroke-width=\"1.5\" ${dash}/>`,\n );\n els.push(\n `<text x=\"${fmt(plotArea.x + 4)}\" y=\"${fmt(py - 2)}\" fill=\"${stroke}\" font-size=\"11\" font-family=\"sans-serif\">${(level * 100).toFixed(1)}% ${formatPrice(fy)}</text>`,\n );\n }\n } else if (mode === \"measure\") {\n const m = computeMeasurement(anchor, cursor);\n const color = m.up ? measureUp : measureDown;\n const x = Math.min(a.px, b.px);\n const y = Math.min(a.py, b.py);\n const w = Math.abs(b.px - a.px);\n const h = Math.abs(b.py - a.py);\n const midX = (a.px + b.px) / 2;\n els.push(\n `<rect x=\"${fmt(x)}\" y=\"${fmt(y)}\" width=\"${fmt(w)}\" height=\"${fmt(h)}\" fill=\"${withAlpha(color, \"33\")}\" stroke=\"${color}\" stroke-width=\"1.5\"/>`,\n );\n els.push(\n `<line x1=\"${fmt(midX)}\" y1=\"${fmt(a.py)}\" x2=\"${fmt(midX)}\" y2=\"${fmt(b.py)}\" stroke=\"${color}\" stroke-width=\"1.5\"/>`,\n );\n els.push(\n `<text x=\"${fmt(midX)}\" y=\"${fmt(m.up ? b.py - 12 : b.py + 16)}\" fill=\"${color}\" font-size=\"12\" font-family=\"sans-serif\" text-anchor=\"middle\">${formatMeasurement(m)}</text>`,\n );\n }\n }\n\n return els;\n }\n\n function handleMouseDown(pluginCtx: PluginContext, event: InteractionEvent): void {\n if (!event.inPlotArea) return;\n\n event.preventDefault();\n const point = pointFromEvent(pluginCtx, event);\n\n if (state.mode === \"horizontal\") {\n commitHorizontal(point.y);\n finishStroke();\n return;\n }\n\n if (state.mode === \"vertical\") {\n commitVertical(point.x);\n finishStroke();\n return;\n }\n\n if (state.pending) {\n commitTwoPoint(state.pending, point);\n finishStroke();\n return;\n }\n\n state.start = point;\n state.dragging = true;\n state.dragMoved = false;\n state.dragStartPixel = { x: event.pixelX, y: event.pixelY };\n state.cursor = point;\n pluginCtx.requestRender?.();\n }\n\n function handleMouseMove(pluginCtx: PluginContext, event: InteractionEvent): void {\n const point = pointFromEvent(pluginCtx, event);\n state.cursor = point;\n\n if (state.dragging && state.dragStartPixel) {\n const dx = event.pixelX - state.dragStartPixel.x;\n const dy = event.pixelY - state.dragStartPixel.y;\n if (Math.hypot(dx, dy) >= DRAG_THRESHOLD_PX) {\n state.dragMoved = true;\n }\n }\n\n event.preventDefault();\n pluginCtx.requestRender?.();\n }\n\n function handleMouseUp(pluginCtx: PluginContext, event: InteractionEvent): void {\n if (!state.dragging || !state.start) return;\n\n const point = pointFromEvent(pluginCtx, event);\n const start = state.start;\n state.dragging = false;\n state.dragStartPixel = null;\n\n if (state.dragMoved) {\n commitTwoPoint(start, point);\n finishStroke();\n return;\n }\n\n state.pending = start;\n state.start = null;\n state.cursor = point;\n pluginCtx.requestRender?.();\n }\n\n const api: DrawingToolsAPI & Record<string, unknown> = {\n setMode(mode) {\n setModeInternal(mode);\n },\n getMode() {\n return state.mode;\n },\n setMagnet(enabled) {\n state.magnet = enabled;\n },\n isMagnet() {\n return state.magnet;\n },\n undo() {\n if (!ctx || state.undoStack.length === 0) return false;\n state.redoStack.push(snapshot());\n const prev = state.undoStack.pop()!;\n const current = snapshot();\n for (const a of current) ctx.chart.removeAnnotation(a.id!);\n for (const a of prev) ctx.chart.addAnnotation(a);\n return true;\n },\n redo() {\n if (!ctx || state.redoStack.length === 0) return false;\n state.undoStack.push(snapshot());\n const next = state.redoStack.pop()!;\n const current = snapshot();\n for (const a of current) ctx.chart.removeAnnotation(a.id!);\n for (const a of next) ctx.chart.addAnnotation(a);\n return true;\n },\n clear() {\n if (!ctx) return;\n pushUndo();\n for (const a of snapshot()) ctx.chart.removeAnnotation(a.id!);\n },\n };\n\n return {\n manifest,\n api,\n onInit(pluginCtx) {\n ctx = pluginCtx;\n },\n onDestroy() {\n ctx = null;\n },\n onInteraction(pluginCtx, event) {\n if (!isDrawingMode(state.mode)) return;\n\n if (event.type === \"mousedown\") {\n handleMouseDown(pluginCtx, event);\n return;\n }\n\n if (event.type === \"mousemove\") {\n handleMouseMove(pluginCtx, event);\n return;\n }\n\n if (event.type === \"mouseup\") {\n handleMouseUp(pluginCtx, event);\n }\n },\n onRenderOverlay(pluginCtx) {\n const c2d = pluginCtx.render.ctx2d;\n if (!c2d) return;\n drawPreview(c2d, pluginCtx.render.plotArea, pluginCtx.coords);\n },\n onExportSVG(svgCtx) {\n if (!svgCtx.builder) return;\n if (svgCtx.exportContext?.options.includeOverlays === false) return;\n for (const el of previewToSVG(svgCtx)) {\n svgCtx.builder.push(\"plugins\", el);\n }\n },\n };\n}\n\nexport { snapToCandle, findNearestBarIndex } from \"./snapToCandle\";\nexport default PluginDrawingTools;\n","/**\n * PluginReplay — bar-by-bar playback (Stage 2.17 MVP).\n */\n\nimport type { ChartPlugin, PluginContext, PluginManifest } from \"../types\";\n\nexport interface PluginReplayConfig {\n /** Series id to replay */\n seriesId: string;\n /** Milliseconds between frames at 1x speed */\n frameMs?: number;\n}\n\nexport interface ReplayAPI {\n play(speed?: number): void;\n pause(): void;\n step(count?: number): void;\n seek(index: number): void;\n getIndex(): number;\n getLength(): number;\n isPlaying(): boolean;\n}\n\nconst manifest: PluginManifest = {\n name: \"velo-plot-replay\",\n version: \"1.0.0\",\n description: \"Bar-by-bar chart replay with speed control\",\n provides: [\"replay\"],\n tags: [\"replay\", \"trading\"],\n};\n\ninterface ReplayBuffer {\n x: Float32Array;\n open?: Float32Array;\n high?: Float32Array;\n low?: Float32Array;\n close?: Float32Array;\n y?: Float32Array;\n}\n\nexport function PluginReplay(config: PluginReplayConfig): ChartPlugin<PluginReplayConfig> {\n let ctx: PluginContext | null = null;\n let buffer: ReplayBuffer | null = null;\n let index = 0;\n let timer: ReturnType<typeof setInterval> | null = null;\n let speed = 1;\n const frameMs = config.frameMs ?? 250;\n\n function applyWindow(end: number): void {\n const c = ctx!;\n const buf = buffer!;\n const n = Math.min(end + 1, buf.x.length);\n const slice = (arr?: Float32Array) => (arr ? arr.subarray(0, n) : undefined);\n c.chart.updateSeries(config.seriesId, {\n x: slice(buf.x)!,\n y: slice(buf.y),\n open: slice(buf.open),\n high: slice(buf.high),\n low: slice(buf.low),\n close: slice(buf.close),\n });\n }\n\n const api: ReplayAPI & Record<string, unknown> = {\n play(s = 1) {\n if (!buffer) return;\n speed = Math.max(0.1, s);\n if (timer) clearInterval(timer);\n timer = setInterval(() => {\n if (!ctx || !buffer) {\n api.pause();\n return;\n }\n if (index >= buffer.x.length - 1) {\n api.pause();\n return;\n }\n index++;\n applyWindow(index);\n }, frameMs / speed);\n },\n pause() {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n },\n step(count = 1) {\n if (!buffer) return;\n index = Math.min(buffer.x.length - 1, index + count);\n applyWindow(index);\n },\n seek(i) {\n if (!buffer) return;\n index = Math.max(0, Math.min(buffer.x.length - 1, i));\n applyWindow(index);\n },\n getIndex() {\n return index;\n },\n getLength() {\n return buffer?.x.length ?? 0;\n },\n isPlaying() {\n return timer != null;\n },\n };\n\n return {\n manifest,\n api,\n onInit(pluginCtx) {\n ctx = pluginCtx;\n const series = ctx.chart.getSeries(config.seriesId);\n if (!series) {\n console.warn(`[PluginReplay] Series \"${config.seriesId}\" not found`);\n return;\n }\n const d = series.getData();\n buffer = {\n x: Float32Array.from(d.x),\n y: d.y ? Float32Array.from(d.y) : undefined,\n open: d.open ? Float32Array.from(d.open) : undefined,\n high: d.high ? Float32Array.from(d.high) : undefined,\n low: d.low ? Float32Array.from(d.low) : undefined,\n close: d.close ? Float32Array.from(d.close) : undefined,\n };\n index = Math.max(0, buffer.x.length - 1);\n },\n onDestroy() {\n api.pause();\n ctx = null;\n buffer = null;\n },\n };\n}\n\nexport default PluginReplay;\n"],"names":["computeHeikinAshi","ohlc","n","haOpen","haHigh","haLow","haClose","i","o","h","l","c","barsToOhlc","bars","x","open","high","low","close","volume","b","pseudoRandom","seed","s","generateBars","from","to","barMs","base","rand","price","t","delta","createMockDatafeed","options","basePrice","cache","sym","request","key","last","timer","findNearestBarIndex","barX","bestIdx","bestDist","d","snapToCandle","input","idx","candidates","clickPy","threshold","bestY","bestPyDist","cy","py","dist","computeMeasurement","a","change","denom","percent","formatMeasurement","m","sign","formatPrice","value","abs","decimals","FIB_LEVELS","DRAG_THRESHOLD_PX","DEFAULT_MEASURE_UP","DEFAULT_MEASURE_DOWN","withAlpha","color","alpha","manifest","isDrawingMode","mode","findCandlestickSeries","ctx","PluginDrawingTools","config","autoDeselect","state","stroke","measureUp","measureDown","snapshot","_b","_a","pushUndo","resetInteractionState","setModeInternal","finishStroke","resolvePoint","y","series","dy","pointFromEvent","pluginCtx","event","commitHorizontal","commitVertical","commitMeasure","p0","p1","midX","commitTwoPoint","yMin","yMax","level","fy","drawPreview","c2d","plotArea","coords","cursor","anchor","toPx","px","w","drawMeasurePreview","headLen","dir","label","boxW","boxH","boxX","boxY","previewToSVG","svgCtx","yScale","primaryYScale","dash","els","fmt","handleMouseDown","point","handleMouseMove","dx","handleMouseUp","start","enabled","prev","current","next","el","PluginReplay","buffer","index","speed","frameMs","applyWindow","end","buf","slice","arr","api","count"],"mappings":"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"}
@@ -10,6 +10,7 @@ export declare class PluginManagerImpl implements PluginManager {
10
10
  private hooksAfterRender;
11
11
  private hooksRenderWebGL;
12
12
  private hooksRenderOverlay;
13
+ private hooksExportSVG;
13
14
  private hooksInteraction;
14
15
  private hooksViewChange;
15
16
  private hooksDataUpdate;
@@ -70,6 +71,10 @@ export declare class PluginManagerImpl implements PluginManager {
70
71
  * Notify overlay render hooks
71
72
  */
72
73
  notifyRenderOverlay(event: AfterRenderEvent): void;
74
+ /**
75
+ * Notify SVG export hooks
76
+ */
77
+ notifyExportSVG(ctx: import('../core/chart/exporter/svg/plugins/types').SVGExportPluginContext): void;
73
78
  /**
74
79
  * Notify interaction hooks
75
80
  * Returns false if any plugin prevents default
@@ -1,6 +1,6 @@
1
1
  var u = Object.defineProperty;
2
- var L = (P, e, i) => e in P ? u(P, e, { enumerable: !0, configurable: !0, writable: !0, value: i }) : P[e] = i;
3
- var k = (P, e, i) => L(P, typeof e != "symbol" ? e + "" : e, i);
2
+ var L = (v, e, i) => e in v ? u(v, e, { enumerable: !0, configurable: !0, writable: !0, value: i }) : v[e] = i;
3
+ var k = (v, e, i) => L(v, typeof e != "symbol" ? e + "" : e, i);
4
4
  const f = {
5
5
  line: {
6
6
  color: "rgba(255, 255, 255, 0.7)",
@@ -240,8 +240,8 @@ class W {
240
240
  const g = i.text.split(`
241
241
  `), y = i.padding ?? f.text.padding;
242
242
  let c = 0;
243
- for (const v of g)
244
- c = Math.max(c, e.measureText(v).width);
243
+ for (const P of g)
244
+ c = Math.max(c, e.measureText(P).width);
245
245
  const M = c + y * 2, m = g.length * o - (o - h) + y * 2;
246
246
  let b = r, T = a;
247
247
  switch (i.anchor) {
@@ -278,8 +278,8 @@ class W {
278
278
  4
279
279
  ), e.fill());
280
280
  const S = i.color ?? f.text.color, w = T - m / 2 + y + h / 2;
281
- g.forEach((v, z) => {
282
- this.drawLatexOrText(e, v, b, w + z * o, {
281
+ g.forEach((P, z) => {
282
+ this.drawLatexOrText(e, P, b, w + z * o, {
283
283
  fontSize: h,
284
284
  fontFamily: n,
285
285
  fontWeight: d,
@@ -386,7 +386,7 @@ const x = {
386
386
  provides: ["annotation"],
387
387
  tags: ["annotation", "overlay", "label"]
388
388
  };
389
- function C(P = {}) {
389
+ function C(v = {}) {
390
390
  let e;
391
391
  return {
392
392
  manifest: x,
@@ -394,6 +394,7 @@ function C(P = {}) {
394
394
  e = new W(), i.storage.set("manager", e);
395
395
  },
396
396
  onRenderOverlay(i) {
397
+ if (i.chart.getActiveRenderer() === "svg") return;
397
398
  const l = i.render.plotArea, t = i.data.getViewBounds(), s = i.getPlugin("velo-plot-latex"), r = s == null ? void 0 : s.api;
398
399
  e.render(
399
400
  i.render.ctx2d,
@@ -1 +1 @@
1
- {"version":3,"file":"annotations.js","sources":["../../src/core/annotations/AnnotationManager.ts","../../src/plugins/annotations/index.ts"],"sourcesContent":["/**\n * AnnotationManager - Manages chart annotations\n * \n * Handles creation, update, removal, and rendering of all annotation types.\n */\n\nimport type { Bounds } from '../../types';\nimport type {\n Annotation,\n HorizontalLineAnnotation,\n VerticalLineAnnotation,\n RectangleAnnotation,\n BandAnnotation,\n TextAnnotation,\n ArrowAnnotation,\n} from './types';\n\n// ============================================\n// Default Styles\n// ============================================\n\nconst DEFAULT_STYLES = {\n line: {\n color: 'rgba(255, 255, 255, 0.7)',\n lineWidth: 1,\n lineDash: [] as number[],\n },\n rectangle: {\n fillColor: 'rgba(100, 100, 255, 0.2)',\n strokeColor: 'rgba(100, 100, 255, 0.5)',\n strokeWidth: 1,\n },\n text: {\n fontSize: 12,\n fontFamily: 'Inter, system-ui, sans-serif',\n color: '#ffffff',\n backgroundColor: 'rgba(0, 0, 0, 0.7)',\n padding: 4,\n },\n arrow: {\n color: 'rgba(255, 255, 255, 0.7)',\n lineWidth: 2,\n headSize: 10,\n },\n};\n\n// ============================================\n// Plot Area Type\n// ============================================\n\nexport interface PlotArea {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n// ============================================\n// AnnotationManager Class\n// ============================================\n\nexport class AnnotationManager {\n private annotations: Map<string, Annotation> = new Map();\n private idCounter = 0;\n\n // ----------------------------------------\n // CRUD Operations\n // ----------------------------------------\n\n /**\n * Add a new annotation\n * @returns The annotation ID\n */\n add(annotation: Annotation): string {\n const id = annotation.id ?? `annotation-${++this.idCounter}`;\n const resolved: Annotation = {\n ...annotation,\n id,\n visible: annotation.visible ?? true,\n interactive: annotation.interactive ?? false,\n zIndex: annotation.zIndex ?? 0,\n };\n\n this.annotations.set(id, resolved);\n return id;\n }\n\n /**\n * Remove an annotation by ID\n */\n remove(id: string): boolean {\n return this.annotations.delete(id);\n }\n\n /**\n * Update an annotation\n */\n update(id: string, updates: Partial<Annotation>): void {\n const existing = this.annotations.get(id);\n if (existing) {\n this.annotations.set(id, { ...existing, ...updates } as Annotation);\n }\n }\n\n /**\n * Get an annotation by ID\n */\n get(id: string): Annotation | undefined {\n return this.annotations.get(id);\n }\n\n /**\n * Get all annotations\n */\n getAll(): Annotation[] {\n return Array.from(this.annotations.values());\n }\n\n /**\n * Clear all annotations\n */\n clear(): void {\n this.annotations.clear();\n }\n\n /**\n * Get count of annotations\n */\n get count(): number {\n return this.annotations.size;\n }\n\n // ----------------------------------------\n // Rendering\n // ----------------------------------------\n\n /**\n * Render all annotations\n */\n render(\n ctx: CanvasRenderingContext2D,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n // Sort by zIndex\n const sorted = this.getAll()\n .filter(a => a.visible !== false)\n .sort((a, b) => (a.zIndex ?? 0) - (b.zIndex ?? 0));\n\n ctx.save();\n\n // Clip to plot area\n ctx.beginPath();\n ctx.rect(plotArea.x, plotArea.y, plotArea.width, plotArea.height);\n ctx.clip();\n\n for (const annotation of sorted) {\n this.renderAnnotation(ctx, annotation, plotArea, bounds, latexAPI);\n }\n\n ctx.restore();\n }\n\n /**\n * Helper to draw text or LaTeX\n */\n private drawLatexOrText(\n ctx: CanvasRenderingContext2D,\n text: string,\n x: number,\n y: number,\n options: {\n fontSize: number;\n fontFamily: string;\n fontWeight?: string | number;\n color: string;\n align?: CanvasTextAlign;\n baseline?: CanvasTextBaseline;\n rotation?: number;\n latex?: boolean;\n },\n latexAPI?: any\n ): void {\n const isLatex = (options.latex || text.includes('\\\\') || text.includes('^') || text.includes('_') || (text.includes('{') && text.includes('}'))) &&\n !!latexAPI && (typeof latexAPI.render === 'function');\n\n if (isLatex) {\n ctx.save();\n ctx.translate(x, y);\n if (options.rotation) ctx.rotate((options.rotation * Math.PI) / 180);\n\n const dims = latexAPI.measure(text, {\n fontSize: options.fontSize,\n fontFamily: options.fontFamily,\n color: options.color\n });\n\n let lx = 0;\n let ly = 0;\n\n // Handle Horizontal Alignment\n const align = options.align ?? \"left\";\n if (align === \"center\") lx = -dims.width / 2;\n else if (align === \"right\") lx = -dims.width;\n\n // Handle Vertical Alignment based on alphabetic baseline of the plugin\n // The plugin draws with textBaseline = 'alphabetic' at the provided y\n const baseline = options.baseline ?? \"alphabetic\";\n if (baseline === \"middle\") {\n ly = -dims.height / 2 + dims.baseline;\n } else if (baseline === \"top\" || baseline === \"hanging\") {\n ly = dims.baseline;\n } else if (baseline === \"bottom\" || baseline === \"ideographic\") {\n ly = -(dims.height - dims.baseline);\n } else {\n // 'alphabetic' or default\n ly = 0;\n }\n\n latexAPI.render(text, ctx, lx, ly, {\n fontSize: options.fontSize,\n fontFamily: options.fontFamily,\n color: options.color\n });\n ctx.restore();\n } else {\n ctx.save();\n ctx.font = `${options.fontWeight ?? ''} ${options.fontSize}px ${options.fontFamily}`;\n ctx.fillStyle = options.color;\n ctx.textAlign = options.align ?? \"left\";\n ctx.textBaseline = options.baseline ?? \"alphabetic\";\n ctx.translate(x, y);\n if (options.rotation) ctx.rotate((options.rotation * Math.PI) / 180);\n ctx.fillText(text, 0, 0);\n ctx.restore();\n }\n }\n\n private renderAnnotation(\n ctx: CanvasRenderingContext2D,\n annotation: Annotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n switch (annotation.type) {\n case 'horizontal-line':\n this.renderHorizontalLine(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n case 'vertical-line':\n this.renderVerticalLine(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n case 'rectangle':\n this.renderRectangle(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n case 'band':\n this.renderBand(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n case 'text':\n this.renderText(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n case 'arrow':\n this.renderArrow(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n }\n }\n\n // ----------------------------------------\n // Coordinate Conversion\n // ----------------------------------------\n\n private dataToPixelX(value: number, bounds: Bounds, plotArea: PlotArea): number {\n const normalized = (value - bounds.xMin) / (bounds.xMax - bounds.xMin);\n return plotArea.x + normalized * plotArea.width;\n }\n\n private dataToPixelY(value: number, bounds: Bounds, plotArea: PlotArea): number {\n const normalized = (value - bounds.yMin) / (bounds.yMax - bounds.yMin);\n return plotArea.y + plotArea.height * (1 - normalized);\n }\n\n // ----------------------------------------\n // Render: Horizontal Line\n // ----------------------------------------\n\n private renderHorizontalLine(\n ctx: CanvasRenderingContext2D,\n annotation: HorizontalLineAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n const y = this.dataToPixelY(annotation.y, bounds, plotArea);\n\n // Skip if outside visible area\n if (y < plotArea.y || y > plotArea.y + plotArea.height) return;\n\n const xStart = annotation.xMin !== undefined\n ? Math.max(this.dataToPixelX(annotation.xMin, bounds, plotArea), plotArea.x)\n : plotArea.x;\n const xEnd = annotation.xMax !== undefined\n ? Math.min(this.dataToPixelX(annotation.xMax, bounds, plotArea), plotArea.x + plotArea.width)\n : plotArea.x + plotArea.width;\n\n ctx.save();\n ctx.strokeStyle = annotation.color ?? DEFAULT_STYLES.line.color;\n ctx.lineWidth = annotation.lineWidth ?? DEFAULT_STYLES.line.lineWidth;\n ctx.setLineDash(annotation.lineDash ?? DEFAULT_STYLES.line.lineDash);\n\n ctx.beginPath();\n ctx.moveTo(xStart, y);\n ctx.lineTo(xEnd, y);\n ctx.stroke();\n\n // Render label if present\n if (annotation.label) {\n this.renderLineLabel(\n ctx,\n annotation.label,\n xStart, xEnd, y,\n annotation.labelPosition ?? 'right',\n 'horizontal',\n annotation.labelBackground,\n latexAPI\n );\n }\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Render: Vertical Line\n // ----------------------------------------\n\n private renderVerticalLine(\n ctx: CanvasRenderingContext2D,\n annotation: VerticalLineAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n const x = this.dataToPixelX(annotation.x, bounds, plotArea);\n\n // Skip if outside visible area\n if (x < plotArea.x || x > plotArea.x + plotArea.width) return;\n\n const yStart = annotation.yMin !== undefined\n ? Math.min(this.dataToPixelY(annotation.yMin, bounds, plotArea), plotArea.y + plotArea.height)\n : plotArea.y;\n const yEnd = annotation.yMax !== undefined\n ? Math.max(this.dataToPixelY(annotation.yMax, bounds, plotArea), plotArea.y)\n : plotArea.y + plotArea.height;\n\n ctx.save();\n ctx.strokeStyle = annotation.color ?? DEFAULT_STYLES.line.color;\n ctx.lineWidth = annotation.lineWidth ?? DEFAULT_STYLES.line.lineWidth;\n ctx.setLineDash(annotation.lineDash ?? DEFAULT_STYLES.line.lineDash);\n\n ctx.beginPath();\n ctx.moveTo(x, yStart);\n ctx.lineTo(x, yEnd);\n ctx.stroke();\n\n // Render label if present\n if (annotation.label) {\n this.renderLineLabel(\n ctx,\n annotation.label,\n yStart, yEnd, x,\n annotation.labelPosition ?? 'top',\n 'vertical',\n annotation.labelBackground,\n latexAPI\n );\n }\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Render: Rectangle\n // ----------------------------------------\n\n private renderRectangle(\n ctx: CanvasRenderingContext2D,\n annotation: RectangleAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n const x1 = this.dataToPixelX(annotation.xMin, bounds, plotArea);\n const x2 = this.dataToPixelX(annotation.xMax, bounds, plotArea);\n const y1 = this.dataToPixelY(annotation.yMax, bounds, plotArea); // Note: Y is inverted\n const y2 = this.dataToPixelY(annotation.yMin, bounds, plotArea);\n\n const x = Math.min(x1, x2);\n const y = Math.min(y1, y2);\n const width = Math.abs(x2 - x1);\n const height = Math.abs(y2 - y1);\n\n ctx.save();\n\n // Fill\n if (annotation.fillColor) {\n ctx.fillStyle = annotation.fillColor;\n ctx.fillRect(x, y, width, height);\n }\n\n // Stroke\n if (annotation.strokeColor) {\n ctx.strokeStyle = annotation.strokeColor;\n ctx.lineWidth = annotation.strokeWidth ?? DEFAULT_STYLES.rectangle.strokeWidth;\n ctx.setLineDash(annotation.strokeDash ?? []);\n ctx.strokeRect(x, y, width, height);\n }\n\n // Label\n if (annotation.label) {\n this.renderCenteredLabel(ctx, annotation.label, x + width / 2, y + height / 2, latexAPI);\n }\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Render: Band\n // ----------------------------------------\n\n private renderBand(\n ctx: CanvasRenderingContext2D,\n annotation: BandAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n // Determine band type and calculate bounds\n let x: number, y: number, width: number, height: number;\n\n if (annotation.xMin !== undefined && annotation.xMax !== undefined) {\n // Vertical band (spans full Y)\n const x1 = this.dataToPixelX(annotation.xMin, bounds, plotArea);\n const x2 = this.dataToPixelX(annotation.xMax, bounds, plotArea);\n x = Math.min(x1, x2);\n width = Math.abs(x2 - x1);\n y = plotArea.y;\n height = plotArea.height;\n\n if (annotation.yMin !== undefined) {\n const yPixel = this.dataToPixelY(annotation.yMin, bounds, plotArea);\n height = yPixel - y;\n }\n if (annotation.yMax !== undefined) {\n const yPixel = this.dataToPixelY(annotation.yMax, bounds, plotArea);\n y = yPixel;\n height = plotArea.y + plotArea.height - y;\n }\n } else if (annotation.yMin !== undefined && annotation.yMax !== undefined) {\n // Horizontal band (spans full X)\n const y1 = this.dataToPixelY(annotation.yMax, bounds, plotArea);\n const y2 = this.dataToPixelY(annotation.yMin, bounds, plotArea);\n y = Math.min(y1, y2);\n height = Math.abs(y2 - y1);\n x = plotArea.x;\n width = plotArea.width;\n } else {\n // Invalid band configuration\n return;\n }\n\n ctx.save();\n\n // Fill\n ctx.fillStyle = annotation.fillColor ?? DEFAULT_STYLES.rectangle.fillColor;\n ctx.fillRect(x, y, width, height);\n\n // Stroke\n if (annotation.strokeColor) {\n ctx.strokeStyle = annotation.strokeColor;\n ctx.lineWidth = annotation.strokeWidth ?? 1;\n ctx.strokeRect(x, y, width, height);\n }\n\n // Label\n if (annotation.label) {\n let labelX = x + width / 2;\n let labelY = y + height / 2;\n\n switch (annotation.labelPosition) {\n case 'top':\n labelY = y + 15;\n break;\n case 'bottom':\n labelY = y + height - 5;\n break;\n case 'left':\n labelX = x + 10;\n break;\n case 'right':\n labelX = x + width - 10;\n break;\n }\n\n this.renderCenteredLabel(ctx, annotation.label, labelX, labelY, latexAPI);\n }\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Render: Text\n // ----------------------------------------\n\n private renderText(\n ctx: CanvasRenderingContext2D,\n annotation: TextAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n const x = this.dataToPixelX(annotation.x, bounds, plotArea);\n const y = this.dataToPixelY(annotation.y, bounds, plotArea);\n\n ctx.save();\n\n // Apply rotation if specified\n if (annotation.rotation) {\n ctx.translate(x, y);\n ctx.rotate((annotation.rotation * Math.PI) / 180);\n ctx.translate(-x, -y);\n }\n\n const fontSize = annotation.fontSize ?? DEFAULT_STYLES.text.fontSize;\n const fontFamily = annotation.fontFamily ?? DEFAULT_STYLES.text.fontFamily;\n const fontWeight = annotation.fontWeight ?? 'normal';\n const lineHeight = fontSize * 1.2;\n\n ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n\n // Support multi-line text\n const lines = annotation.text.split('\\n');\n const padding = annotation.padding ?? DEFAULT_STYLES.text.padding;\n\n // Measure all lines to find max width\n let maxWidth = 0;\n for (const line of lines) {\n maxWidth = Math.max(maxWidth, ctx.measureText(line).width);\n }\n\n const textWidth = maxWidth + padding * 2;\n const textHeight = (lines.length * lineHeight) - (lineHeight - fontSize) + padding * 2;\n\n // Calculate position based on anchor\n let drawX = x;\n let drawY = y;\n\n switch (annotation.anchor) {\n case 'top-left':\n drawX += textWidth / 2;\n drawY += textHeight / 2;\n break;\n case 'top-right':\n drawX -= textWidth / 2;\n drawY += textHeight / 2;\n break;\n case 'bottom-left':\n drawX += textWidth / 2;\n drawY -= textHeight / 2;\n break;\n case 'bottom-right':\n drawX -= textWidth / 2;\n drawY -= textHeight / 2;\n break;\n case 'top-center':\n drawY += textHeight / 2;\n break;\n case 'bottom-center':\n drawY -= textHeight / 2;\n break;\n case 'left-center':\n drawX += textWidth / 2;\n break;\n case 'right-center':\n drawX -= textWidth / 2;\n break;\n }\n\n // Draw background\n if (annotation.backgroundColor) {\n ctx.fillStyle = annotation.backgroundColor;\n ctx.beginPath();\n ctx.roundRect(\n drawX - textWidth / 2,\n drawY - textHeight / 2,\n textWidth,\n textHeight,\n 4\n );\n ctx.fill();\n }\n\n // Draw text lines\n const color = annotation.color ?? DEFAULT_STYLES.text.color;\n const startY = drawY - (textHeight / 2) + padding + (fontSize / 2);\n\n lines.forEach((line, i) => {\n this.drawLatexOrText(ctx, line, drawX, startY + i * lineHeight, {\n fontSize,\n fontFamily,\n fontWeight,\n color,\n align: 'center',\n baseline: 'middle',\n latex: annotation.latex\n }, latexAPI);\n });\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Render: Arrow\n // ----------------------------------------\n\n private renderArrow(\n ctx: CanvasRenderingContext2D,\n annotation: ArrowAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n const x1 = this.dataToPixelX(annotation.x1, bounds, plotArea);\n const y1 = this.dataToPixelY(annotation.y1, bounds, plotArea);\n const x2 = this.dataToPixelX(annotation.x2, bounds, plotArea);\n const y2 = this.dataToPixelY(annotation.y2, bounds, plotArea);\n\n ctx.save();\n ctx.strokeStyle = annotation.color ?? DEFAULT_STYLES.arrow.color;\n ctx.fillStyle = annotation.color ?? DEFAULT_STYLES.arrow.color;\n ctx.lineWidth = annotation.lineWidth ?? DEFAULT_STYLES.arrow.lineWidth;\n\n // Draw line\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n\n // Draw arrow head\n const headSize = annotation.headSize ?? DEFAULT_STYLES.arrow.headSize;\n const angle = Math.atan2(y2 - y1, x2 - x1);\n\n const headStyle = annotation.headStyle ?? 'filled';\n\n if (headStyle !== 'none') {\n ctx.beginPath();\n ctx.moveTo(x2, y2);\n ctx.lineTo(\n x2 - headSize * Math.cos(angle - Math.PI / 6),\n y2 - headSize * Math.sin(angle - Math.PI / 6)\n );\n\n if (headStyle === 'filled') {\n ctx.lineTo(\n x2 - headSize * Math.cos(angle + Math.PI / 6),\n y2 - headSize * Math.sin(angle + Math.PI / 6)\n );\n ctx.closePath();\n ctx.fill();\n } else {\n ctx.moveTo(x2, y2);\n ctx.lineTo(\n x2 - headSize * Math.cos(angle + Math.PI / 6),\n y2 - headSize * Math.sin(angle + Math.PI / 6)\n );\n ctx.stroke();\n }\n }\n\n // Draw tail arrow if specified\n if (annotation.showTail) {\n const tailAngle = angle + Math.PI;\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(\n x1 - headSize * Math.cos(tailAngle - Math.PI / 6),\n y1 - headSize * Math.sin(tailAngle - Math.PI / 6)\n );\n ctx.lineTo(\n x1 - headSize * Math.cos(tailAngle + Math.PI / 6),\n y1 - headSize * Math.sin(tailAngle + Math.PI / 6)\n );\n ctx.closePath();\n ctx.fill();\n }\n\n // Draw label if present\n if (annotation.label) {\n const midX = (x1 + x2) / 2;\n const midY = (y1 + y2) / 2;\n this.renderCenteredLabel(ctx, annotation.label, midX, midY - 10, latexAPI);\n }\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Helper: Render Labels\n // ----------------------------------------\n\n private renderLineLabel(\n ctx: CanvasRenderingContext2D,\n label: string,\n start: number,\n end: number,\n cross: number,\n position: string,\n orientation: 'horizontal' | 'vertical',\n backgroundColor?: string,\n latexAPI?: any\n ): void {\n ctx.save();\n\n ctx.font = `${DEFAULT_STYLES.text.fontSize}px ${DEFAULT_STYLES.text.fontFamily}`;\n const metrics = ctx.measureText(label);\n const padding = 4;\n const textWidth = metrics.width + padding * 2;\n const textHeight = DEFAULT_STYLES.text.fontSize + padding * 2;\n\n let x: number, y: number;\n\n if (orientation === 'horizontal') {\n y = cross;\n\n switch (position) {\n case 'left':\n x = start + 5;\n ctx.textAlign = 'left';\n break;\n case 'right':\n x = end - 5;\n ctx.textAlign = 'right';\n break;\n default:\n x = (start + end) / 2;\n ctx.textAlign = 'center';\n }\n\n ctx.textBaseline = 'bottom';\n y -= 4;\n } else {\n x = cross;\n\n switch (position) {\n case 'top':\n y = start + textHeight;\n break;\n case 'bottom':\n y = end - 5;\n break;\n default:\n y = (start + end) / 2;\n }\n\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n }\n\n // Background\n if (backgroundColor ?? true) {\n ctx.fillStyle = backgroundColor ?? 'rgba(0, 0, 0, 0.7)';\n const bgX = ctx.textAlign === 'left' ? x - padding\n : ctx.textAlign === 'right' ? x - textWidth + padding\n : x - textWidth / 2;\n ctx.fillRect(bgX, y - textHeight + padding, textWidth, textHeight);\n }\n\n // Text\n this.drawLatexOrText(ctx, label, x, y, {\n fontSize: DEFAULT_STYLES.text.fontSize,\n fontFamily: DEFAULT_STYLES.text.fontFamily,\n color: DEFAULT_STYLES.text.color,\n align: ctx.textAlign,\n baseline: ctx.textBaseline,\n }, latexAPI);\n\n ctx.restore();\n }\n\n private renderCenteredLabel(\n ctx: CanvasRenderingContext2D,\n label: string,\n x: number,\n y: number,\n latexAPI?: any\n ): void {\n ctx.save();\n\n ctx.font = `${DEFAULT_STYLES.text.fontSize}px ${DEFAULT_STYLES.text.fontFamily}`;\n const metrics = ctx.measureText(label);\n const padding = 4;\n const textWidth = metrics.width + padding * 2;\n const textHeight = DEFAULT_STYLES.text.fontSize + padding * 2;\n\n // Background\n ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';\n ctx.beginPath();\n ctx.roundRect(x - textWidth / 2, y - textHeight / 2, textWidth, textHeight, 3);\n ctx.fill();\n\n // Text\n this.drawLatexOrText(ctx, label, x, y, {\n fontSize: DEFAULT_STYLES.text.fontSize,\n fontFamily: DEFAULT_STYLES.text.fontFamily,\n color: DEFAULT_STYLES.text.color,\n align: 'center',\n baseline: 'middle',\n }, latexAPI);\n\n ctx.restore();\n }\n}\n","/**\n * Velo Plot - Annotations Plugin\n * \n * Provides annotation capabilities including:\n * - Line, Rectangle, Band, Text, Arrow annotations\n * - Annotation management and rendering\n * \n * @module plugins/annotations\n */\n\nimport { AnnotationManager } from \"../../core/annotations\";\nimport type { Annotation, AnnotationType } from \"../../core/annotations\";\nimport type { PluginManifest, ChartPlugin, PluginContext } from \"../types\";\n\nexport interface PluginAnnotationsConfig {\n /** Default styles for annotations */\n defaultStyles?: Record<string, any>;\n}\n\nconst manifestAnnotations: PluginManifest = {\n name: \"velo-plot-annotations\",\n version: \"1.0.0\",\n description: \"Annotation support for velo-plot\",\n provides: [\"annotation\"],\n tags: [\"annotation\", \"overlay\", \"label\"],\n};\n\n/**\n * VeloPlot Annotations Plugin\n * \n * Adds support for drawing lines, shapes, and labels on the chart.\n */\nexport function PluginAnnotations(_config: PluginAnnotationsConfig = {}): ChartPlugin<PluginAnnotationsConfig> {\n let annotationManager: AnnotationManager;\n\n return {\n manifest: manifestAnnotations,\n\n onInit(ctx: PluginContext) {\n annotationManager = new AnnotationManager();\n\n // In a real implementation, we would register this manager in the context\n // so the chart can delegate annotation calls to it.\n // For now, we store it in storage for retrieval.\n ctx.storage.set(\"manager\", annotationManager);\n },\n\n onRenderOverlay(ctx) {\n const plotArea = ctx.render.plotArea;\n const viewBounds = ctx.data.getViewBounds();\n\n // Get LaTeX API if plugin is available\n const latexPlugin = ctx.getPlugin<any>(\"velo-plot-latex\");\n const latexAPI = latexPlugin?.api;\n\n // Render all annotations using the manager and provided contexts\n annotationManager.render(\n ctx.render.ctx2d!,\n plotArea,\n viewBounds,\n latexAPI\n );\n },\n\n onDestroy(_ctx: PluginContext) {\n annotationManager.clear();\n },\n\n api: {\n getManager() {\n return annotationManager;\n },\n add(annotation: Annotation) {\n return annotationManager.add(annotation);\n },\n remove(id: string) {\n return annotationManager.remove(id);\n },\n update(id: string, updates: Partial<Annotation>) {\n return annotationManager.update(id, updates);\n },\n get(id: string) {\n return annotationManager.get(id);\n },\n getAll() {\n return annotationManager.getAll();\n },\n clear() {\n annotationManager.clear();\n }\n }\n };\n}\n\nexport { AnnotationManager };\nexport type { Annotation, AnnotationType };\nexport default PluginAnnotations;\n"],"names":["DEFAULT_STYLES","AnnotationManager","__publicField","annotation","id","resolved","updates","existing","ctx","plotArea","bounds","latexAPI","sorted","a","b","text","x","y","options","dims","lx","ly","align","baseline","value","normalized","xStart","xEnd","yStart","yEnd","x1","x2","y1","y2","width","height","labelX","labelY","fontSize","fontFamily","fontWeight","lineHeight","lines","padding","maxWidth","line","textWidth","textHeight","drawX","drawY","color","startY","i","headSize","angle","headStyle","tailAngle","midX","midY","label","start","end","cross","position","orientation","backgroundColor","metrics","bgX","manifestAnnotations","PluginAnnotations","_config","annotationManager","viewBounds","latexPlugin","_ctx"],"mappings":";;;AAqBA,MAAMA,IAAiB;AAAA,EACrB,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,WAAW;AAAA,IACX,UAAU,CAAA;AAAA,EAAC;AAAA,EAEb,WAAW;AAAA,IACT,WAAW;AAAA,IAEX,aAAa;AAAA,EAAA;AAAA,EAEf,MAAM;AAAA,IACJ,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,OAAO;AAAA,IAEP,SAAS;AAAA,EAAA;AAAA,EAEX,OAAO;AAAA,IACL,OAAO;AAAA,IACP,WAAW;AAAA,IACX,UAAU;AAAA,EAAA;AAEd;AAiBO,MAAMC,EAAkB;AAAA,EAAxB;AACG,IAAAC,EAAA,yCAA2C,IAAA;AAC3C,IAAAA,EAAA,mBAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUpB,IAAIC,GAAgC;AAClC,UAAMC,IAAKD,EAAW,MAAM,cAAc,EAAE,KAAK,SAAS,IACpDE,IAAuB;AAAA,MAC3B,GAAGF;AAAA,MACH,IAAAC;AAAA,MACA,SAASD,EAAW,WAAW;AAAA,MAC/B,aAAaA,EAAW,eAAe;AAAA,MACvC,QAAQA,EAAW,UAAU;AAAA,IAAA;AAG/B,gBAAK,YAAY,IAAIC,GAAIC,CAAQ,GAC1BD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAOA,GAAqB;AAC1B,WAAO,KAAK,YAAY,OAAOA,CAAE;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAOA,GAAYE,GAAoC;AACrD,UAAMC,IAAW,KAAK,YAAY,IAAIH,CAAE;AACxC,IAAIG,KACF,KAAK,YAAY,IAAIH,GAAI,EAAE,GAAGG,GAAU,GAAGD,GAAuB;AAAA,EAEtE;AAAA;AAAA;AAAA;AAAA,EAKA,IAAIF,GAAoC;AACtC,WAAO,KAAK,YAAY,IAAIA,CAAE;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAuB;AACrB,WAAO,MAAM,KAAK,KAAK,YAAY,QAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,YAAY,MAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAAgB;AAClB,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OACEI,GACAC,GACAC,GACAC,GACM;AAEN,UAAMC,IAAS,KAAK,SACjB,OAAO,CAAAC,MAAKA,EAAE,YAAY,EAAK,EAC/B,KAAK,CAACA,GAAGC,OAAOD,EAAE,UAAU,MAAMC,EAAE,UAAU,EAAE;AAEnD,IAAAN,EAAI,KAAA,GAGJA,EAAI,UAAA,GACJA,EAAI,KAAKC,EAAS,GAAGA,EAAS,GAAGA,EAAS,OAAOA,EAAS,MAAM,GAChED,EAAI,KAAA;AAEJ,eAAWL,KAAcS;AACvB,WAAK,iBAAiBJ,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AAGnE,IAAAH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAKQ,gBACNA,GACAO,GACAC,GACAC,GACAC,GAUAP,GACM;AAIN,SAHiBO,EAAQ,SAASH,EAAK,SAAS,IAAI,KAAKA,EAAK,SAAS,GAAG,KAAKA,EAAK,SAAS,GAAG,KAAMA,EAAK,SAAS,GAAG,KAAKA,EAAK,SAAS,GAAG,MAC3I,CAAC,CAACJ,KAAa,OAAOA,EAAS,UAAW,YAE/B;AACX,MAAAH,EAAI,KAAA,GACJA,EAAI,UAAUQ,GAAGC,CAAC,GACdC,EAAQ,YAAUV,EAAI,OAAQU,EAAQ,WAAW,KAAK,KAAM,GAAG;AAEnE,YAAMC,IAAOR,EAAS,QAAQI,GAAM;AAAA,QAClC,UAAUG,EAAQ;AAAA,QAClB,YAAYA,EAAQ;AAAA,QACpB,OAAOA,EAAQ;AAAA,MAAA,CAChB;AAED,UAAIE,IAAK,GACLC,IAAK;AAGT,YAAMC,IAAQJ,EAAQ,SAAS;AAC/B,MAAII,MAAU,WAAUF,IAAK,CAACD,EAAK,QAAQ,IAClCG,MAAU,YAASF,IAAK,CAACD,EAAK;AAIvC,YAAMI,IAAWL,EAAQ,YAAY;AACrC,MAAIK,MAAa,WACfF,IAAK,CAACF,EAAK,SAAS,IAAIA,EAAK,WACpBI,MAAa,SAASA,MAAa,YAC5CF,IAAKF,EAAK,WACDI,MAAa,YAAYA,MAAa,gBAC/CF,IAAK,EAAEF,EAAK,SAASA,EAAK,YAG1BE,IAAK,GAGPV,EAAS,OAAOI,GAAMP,GAAKY,GAAIC,GAAI;AAAA,QACjC,UAAUH,EAAQ;AAAA,QAClB,YAAYA,EAAQ;AAAA,QACpB,OAAOA,EAAQ;AAAA,MAAA,CAChB,GACDV,EAAI,QAAA;AAAA,IACN;AACE,MAAAA,EAAI,KAAA,GACJA,EAAI,OAAO,GAAGU,EAAQ,cAAc,EAAE,IAAIA,EAAQ,QAAQ,MAAMA,EAAQ,UAAU,IAClFV,EAAI,YAAYU,EAAQ,OACxBV,EAAI,YAAYU,EAAQ,SAAS,QACjCV,EAAI,eAAeU,EAAQ,YAAY,cACvCV,EAAI,UAAUQ,GAAGC,CAAC,GACdC,EAAQ,YAAUV,EAAI,OAAQU,EAAQ,WAAW,KAAK,KAAM,GAAG,GACnEV,EAAI,SAASO,GAAM,GAAG,CAAC,GACvBP,EAAI,QAAA;AAAA,EAER;AAAA,EAEQ,iBACNA,GACAL,GACAM,GACAC,GACAC,GACM;AACN,YAAQR,EAAW,MAAA;AAAA,MACjB,KAAK;AACH,aAAK,qBAAqBK,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AACrE;AAAA,MACF,KAAK;AACH,aAAK,mBAAmBH,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AACnE;AAAA,MACF,KAAK;AACH,aAAK,gBAAgBH,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AAChE;AAAA,MACF,KAAK;AACH,aAAK,WAAWH,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AAC3D;AAAA,MACF,KAAK;AACH,aAAK,WAAWH,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AAC3D;AAAA,MACF,KAAK;AACH,aAAK,YAAYH,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AAC5D;AAAA,IAAA;AAAA,EAEN;AAAA;AAAA;AAAA;AAAA,EAMQ,aAAaa,GAAed,GAAgBD,GAA4B;AAC9E,UAAMgB,KAAcD,IAAQd,EAAO,SAASA,EAAO,OAAOA,EAAO;AACjE,WAAOD,EAAS,IAAIgB,IAAahB,EAAS;AAAA,EAC5C;AAAA,EAEQ,aAAae,GAAed,GAAgBD,GAA4B;AAC9E,UAAMgB,KAAcD,IAAQd,EAAO,SAASA,EAAO,OAAOA,EAAO;AACjE,WAAOD,EAAS,IAAIA,EAAS,UAAU,IAAIgB;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAMQ,qBACNjB,GACAL,GACAM,GACAC,GACAC,GACM;AACN,UAAMM,IAAI,KAAK,aAAad,EAAW,GAAGO,GAAQD,CAAQ;AAG1D,QAAIQ,IAAIR,EAAS,KAAKQ,IAAIR,EAAS,IAAIA,EAAS,OAAQ;AAExD,UAAMiB,IAASvB,EAAW,SAAS,SAC/B,KAAK,IAAI,KAAK,aAAaA,EAAW,MAAMO,GAAQD,CAAQ,GAAGA,EAAS,CAAC,IACzEA,EAAS,GACPkB,IAAOxB,EAAW,SAAS,SAC7B,KAAK,IAAI,KAAK,aAAaA,EAAW,MAAMO,GAAQD,CAAQ,GAAGA,EAAS,IAAIA,EAAS,KAAK,IAC1FA,EAAS,IAAIA,EAAS;AAE1B,IAAAD,EAAI,KAAA,GACJA,EAAI,cAAcL,EAAW,SAASH,EAAe,KAAK,OAC1DQ,EAAI,YAAYL,EAAW,aAAaH,EAAe,KAAK,WAC5DQ,EAAI,YAAYL,EAAW,YAAYH,EAAe,KAAK,QAAQ,GAEnEQ,EAAI,UAAA,GACJA,EAAI,OAAOkB,GAAQT,CAAC,GACpBT,EAAI,OAAOmB,GAAMV,CAAC,GAClBT,EAAI,OAAA,GAGAL,EAAW,SACb,KAAK;AAAA,MACHK;AAAA,MACAL,EAAW;AAAA,MACXuB;AAAA,MAAQC;AAAA,MAAMV;AAAA,MACdd,EAAW,iBAAiB;AAAA,MAC5B;AAAA,MACAA,EAAW;AAAA,MACXQ;AAAA,IAAA,GAIJH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,mBACNA,GACAL,GACAM,GACAC,GACAC,GACM;AACN,UAAMK,IAAI,KAAK,aAAab,EAAW,GAAGO,GAAQD,CAAQ;AAG1D,QAAIO,IAAIP,EAAS,KAAKO,IAAIP,EAAS,IAAIA,EAAS,MAAO;AAEvD,UAAMmB,IAASzB,EAAW,SAAS,SAC/B,KAAK,IAAI,KAAK,aAAaA,EAAW,MAAMO,GAAQD,CAAQ,GAAGA,EAAS,IAAIA,EAAS,MAAM,IAC3FA,EAAS,GACPoB,IAAO1B,EAAW,SAAS,SAC7B,KAAK,IAAI,KAAK,aAAaA,EAAW,MAAMO,GAAQD,CAAQ,GAAGA,EAAS,CAAC,IACzEA,EAAS,IAAIA,EAAS;AAE1B,IAAAD,EAAI,KAAA,GACJA,EAAI,cAAcL,EAAW,SAASH,EAAe,KAAK,OAC1DQ,EAAI,YAAYL,EAAW,aAAaH,EAAe,KAAK,WAC5DQ,EAAI,YAAYL,EAAW,YAAYH,EAAe,KAAK,QAAQ,GAEnEQ,EAAI,UAAA,GACJA,EAAI,OAAOQ,GAAGY,CAAM,GACpBpB,EAAI,OAAOQ,GAAGa,CAAI,GAClBrB,EAAI,OAAA,GAGAL,EAAW,SACb,KAAK;AAAA,MACHK;AAAA,MACAL,EAAW;AAAA,MACXyB;AAAA,MAAQC;AAAA,MAAMb;AAAA,MACdb,EAAW,iBAAiB;AAAA,MAC5B;AAAA,MACAA,EAAW;AAAA,MACXQ;AAAA,IAAA,GAIJH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,gBACNA,GACAL,GACAM,GACAC,GACAC,GACM;AACN,UAAMmB,IAAK,KAAK,aAAa3B,EAAW,MAAMO,GAAQD,CAAQ,GACxDsB,IAAK,KAAK,aAAa5B,EAAW,MAAMO,GAAQD,CAAQ,GACxDuB,IAAK,KAAK,aAAa7B,EAAW,MAAMO,GAAQD,CAAQ,GACxDwB,IAAK,KAAK,aAAa9B,EAAW,MAAMO,GAAQD,CAAQ,GAExDO,IAAI,KAAK,IAAIc,GAAIC,CAAE,GACnBd,IAAI,KAAK,IAAIe,GAAIC,CAAE,GACnBC,IAAQ,KAAK,IAAIH,IAAKD,CAAE,GACxBK,IAAS,KAAK,IAAIF,IAAKD,CAAE;AAE/B,IAAAxB,EAAI,KAAA,GAGAL,EAAW,cACbK,EAAI,YAAYL,EAAW,WAC3BK,EAAI,SAASQ,GAAGC,GAAGiB,GAAOC,CAAM,IAI9BhC,EAAW,gBACbK,EAAI,cAAcL,EAAW,aAC7BK,EAAI,YAAYL,EAAW,eAAeH,EAAe,UAAU,aACnEQ,EAAI,YAAYL,EAAW,cAAc,CAAA,CAAE,GAC3CK,EAAI,WAAWQ,GAAGC,GAAGiB,GAAOC,CAAM,IAIhChC,EAAW,SACb,KAAK,oBAAoBK,GAAKL,EAAW,OAAOa,IAAIkB,IAAQ,GAAGjB,IAAIkB,IAAS,GAAGxB,CAAQ,GAGzFH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,WACNA,GACAL,GACAM,GACAC,GACAC,GACM;AAEN,QAAIK,GAAWC,GAAWiB,GAAeC;AAEzC,QAAIhC,EAAW,SAAS,UAAaA,EAAW,SAAS,QAAW;AAElE,YAAM2B,IAAK,KAAK,aAAa3B,EAAW,MAAMO,GAAQD,CAAQ,GACxDsB,IAAK,KAAK,aAAa5B,EAAW,MAAMO,GAAQD,CAAQ;AAC9D,MAAAO,IAAI,KAAK,IAAIc,GAAIC,CAAE,GACnBG,IAAQ,KAAK,IAAIH,IAAKD,CAAE,GACxBb,IAAIR,EAAS,GACb0B,IAAS1B,EAAS,QAEdN,EAAW,SAAS,WAEtBgC,IADe,KAAK,aAAahC,EAAW,MAAMO,GAAQD,CAAQ,IAChDQ,IAEhBd,EAAW,SAAS,WAEtBc,IADe,KAAK,aAAad,EAAW,MAAMO,GAAQD,CAAQ,GAElE0B,IAAS1B,EAAS,IAAIA,EAAS,SAASQ;AAAA,IAE5C,WAAWd,EAAW,SAAS,UAAaA,EAAW,SAAS,QAAW;AAEzE,YAAM6B,IAAK,KAAK,aAAa7B,EAAW,MAAMO,GAAQD,CAAQ,GACxDwB,IAAK,KAAK,aAAa9B,EAAW,MAAMO,GAAQD,CAAQ;AAC9D,MAAAQ,IAAI,KAAK,IAAIe,GAAIC,CAAE,GACnBE,IAAS,KAAK,IAAIF,IAAKD,CAAE,GACzBhB,IAAIP,EAAS,GACbyB,IAAQzB,EAAS;AAAA,IACnB;AAEE;AAiBF,QAdAD,EAAI,KAAA,GAGJA,EAAI,YAAYL,EAAW,aAAaH,EAAe,UAAU,WACjEQ,EAAI,SAASQ,GAAGC,GAAGiB,GAAOC,CAAM,GAG5BhC,EAAW,gBACbK,EAAI,cAAcL,EAAW,aAC7BK,EAAI,YAAYL,EAAW,eAAe,GAC1CK,EAAI,WAAWQ,GAAGC,GAAGiB,GAAOC,CAAM,IAIhChC,EAAW,OAAO;AACpB,UAAIiC,IAASpB,IAAIkB,IAAQ,GACrBG,IAASpB,IAAIkB,IAAS;AAE1B,cAAQhC,EAAW,eAAA;AAAA,QACjB,KAAK;AACH,UAAAkC,IAASpB,IAAI;AACb;AAAA,QACF,KAAK;AACH,UAAAoB,IAASpB,IAAIkB,IAAS;AACtB;AAAA,QACF,KAAK;AACH,UAAAC,IAASpB,IAAI;AACb;AAAA,QACF,KAAK;AACH,UAAAoB,IAASpB,IAAIkB,IAAQ;AACrB;AAAA,MAAA;AAGJ,WAAK,oBAAoB1B,GAAKL,EAAW,OAAOiC,GAAQC,GAAQ1B,CAAQ;AAAA,IAC1E;AAEA,IAAAH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,WACNA,GACAL,GACAM,GACAC,GACAC,GACM;AACN,UAAMK,IAAI,KAAK,aAAab,EAAW,GAAGO,GAAQD,CAAQ,GACpDQ,IAAI,KAAK,aAAad,EAAW,GAAGO,GAAQD,CAAQ;AAE1D,IAAAD,EAAI,KAAA,GAGAL,EAAW,aACbK,EAAI,UAAUQ,GAAGC,CAAC,GAClBT,EAAI,OAAQL,EAAW,WAAW,KAAK,KAAM,GAAG,GAChDK,EAAI,UAAU,CAACQ,GAAG,CAACC,CAAC;AAGtB,UAAMqB,IAAWnC,EAAW,YAAYH,EAAe,KAAK,UACtDuC,IAAapC,EAAW,cAAcH,EAAe,KAAK,YAC1DwC,IAAarC,EAAW,cAAc,UACtCsC,IAAaH,IAAW;AAE9B,IAAA9B,EAAI,OAAO,GAAGgC,CAAU,IAAIF,CAAQ,MAAMC,CAAU,IACpD/B,EAAI,YAAY,UAChBA,EAAI,eAAe;AAGnB,UAAMkC,IAAQvC,EAAW,KAAK,MAAM;AAAA,CAAI,GAClCwC,IAAUxC,EAAW,WAAWH,EAAe,KAAK;AAG1D,QAAI4C,IAAW;AACf,eAAWC,KAAQH;AACjB,MAAAE,IAAW,KAAK,IAAIA,GAAUpC,EAAI,YAAYqC,CAAI,EAAE,KAAK;AAG3D,UAAMC,IAAYF,IAAWD,IAAU,GACjCI,IAAcL,EAAM,SAASD,KAAeA,IAAaH,KAAYK,IAAU;AAGrF,QAAIK,IAAQhC,GACRiC,IAAQhC;AAEZ,YAAQd,EAAW,QAAA;AAAA,MACjB,KAAK;AACH,QAAA6C,KAASF,IAAY,GACrBG,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAC,KAASF,IAAY,GACrBG,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAC,KAASF,IAAY,GACrBG,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAC,KAASF,IAAY,GACrBG,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAE,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAE,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAC,KAASF,IAAY;AACrB;AAAA,MACF,KAAK;AACH,QAAAE,KAASF,IAAY;AACrB;AAAA,IAAA;AAIJ,IAAI3C,EAAW,oBACbK,EAAI,YAAYL,EAAW,iBAC3BK,EAAI,UAAA,GACJA,EAAI;AAAA,MACFwC,IAAQF,IAAY;AAAA,MACpBG,IAAQF,IAAa;AAAA,MACrBD;AAAA,MACAC;AAAA,MACA;AAAA,IAAA,GAEFvC,EAAI,KAAA;AAIN,UAAM0C,IAAQ/C,EAAW,SAASH,EAAe,KAAK,OAChDmD,IAASF,IAASF,IAAa,IAAKJ,IAAWL,IAAW;AAEhE,IAAAI,EAAM,QAAQ,CAACG,GAAMO,MAAM;AACzB,WAAK,gBAAgB5C,GAAKqC,GAAMG,GAAOG,IAASC,IAAIX,GAAY;AAAA,QAC9D,UAAAH;AAAA,QACA,YAAAC;AAAA,QACA,YAAAC;AAAA,QACA,OAAAU;AAAA,QACA,OAAO;AAAA,QACP,UAAU;AAAA,QACV,OAAO/C,EAAW;AAAA,MAAA,GACjBQ,CAAQ;AAAA,IACb,CAAC,GAEDH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,YACNA,GACAL,GACAM,GACAC,GACAC,GACM;AACN,UAAMmB,IAAK,KAAK,aAAa3B,EAAW,IAAIO,GAAQD,CAAQ,GACtDuB,IAAK,KAAK,aAAa7B,EAAW,IAAIO,GAAQD,CAAQ,GACtDsB,IAAK,KAAK,aAAa5B,EAAW,IAAIO,GAAQD,CAAQ,GACtDwB,IAAK,KAAK,aAAa9B,EAAW,IAAIO,GAAQD,CAAQ;AAE5D,IAAAD,EAAI,KAAA,GACJA,EAAI,cAAcL,EAAW,SAASH,EAAe,MAAM,OAC3DQ,EAAI,YAAYL,EAAW,SAASH,EAAe,MAAM,OACzDQ,EAAI,YAAYL,EAAW,aAAaH,EAAe,MAAM,WAG7DQ,EAAI,UAAA,GACJA,EAAI,OAAOsB,GAAIE,CAAE,GACjBxB,EAAI,OAAOuB,GAAIE,CAAE,GACjBzB,EAAI,OAAA;AAGJ,UAAM6C,IAAWlD,EAAW,YAAYH,EAAe,MAAM,UACvDsD,IAAQ,KAAK,MAAMrB,IAAKD,GAAID,IAAKD,CAAE,GAEnCyB,IAAYpD,EAAW,aAAa;AA4B1C,QA1BIoD,MAAc,WAChB/C,EAAI,UAAA,GACJA,EAAI,OAAOuB,GAAIE,CAAE,GACjBzB,EAAI;AAAA,MACFuB,IAAKsB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,MAC5CrB,IAAKoB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,IAAA,GAG1CC,MAAc,YAChB/C,EAAI;AAAA,MACFuB,IAAKsB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,MAC5CrB,IAAKoB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,IAAA,GAE9C9C,EAAI,UAAA,GACJA,EAAI,KAAA,MAEJA,EAAI,OAAOuB,GAAIE,CAAE,GACjBzB,EAAI;AAAA,MACFuB,IAAKsB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,MAC5CrB,IAAKoB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,IAAA,GAE9C9C,EAAI,OAAA,KAKJL,EAAW,UAAU;AACvB,YAAMqD,IAAYF,IAAQ,KAAK;AAC/B,MAAA9C,EAAI,UAAA,GACJA,EAAI,OAAOsB,GAAIE,CAAE,GACjBxB,EAAI;AAAA,QACFsB,IAAKuB,IAAW,KAAK,IAAIG,IAAY,KAAK,KAAK,CAAC;AAAA,QAChDxB,IAAKqB,IAAW,KAAK,IAAIG,IAAY,KAAK,KAAK,CAAC;AAAA,MAAA,GAElDhD,EAAI;AAAA,QACFsB,IAAKuB,IAAW,KAAK,IAAIG,IAAY,KAAK,KAAK,CAAC;AAAA,QAChDxB,IAAKqB,IAAW,KAAK,IAAIG,IAAY,KAAK,KAAK,CAAC;AAAA,MAAA,GAElDhD,EAAI,UAAA,GACJA,EAAI,KAAA;AAAA,IACN;AAGA,QAAIL,EAAW,OAAO;AACpB,YAAMsD,KAAQ3B,IAAKC,KAAM,GACnB2B,KAAQ1B,IAAKC,KAAM;AACzB,WAAK,oBAAoBzB,GAAKL,EAAW,OAAOsD,GAAMC,IAAO,IAAI/C,CAAQ;AAAA,IAC3E;AAEA,IAAAH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,gBACNA,GACAmD,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAtD,GACM;AACN,IAAAH,EAAI,KAAA,GAEJA,EAAI,OAAO,GAAGR,EAAe,KAAK,QAAQ,MAAMA,EAAe,KAAK,UAAU;AAC9E,UAAMkE,IAAU1D,EAAI,YAAYmD,CAAK,GAC/BhB,IAAU,GACVG,IAAYoB,EAAQ,QAAQvB,IAAU,GACtCI,IAAa/C,EAAe,KAAK,WAAW2C,IAAU;AAE5D,QAAI3B,GAAWC;AAEf,QAAI+C,MAAgB,cAAc;AAGhC,cAFA/C,IAAI6C,GAEIC,GAAA;AAAA,QACN,KAAK;AACH,UAAA/C,IAAI4C,IAAQ,GACZpD,EAAI,YAAY;AAChB;AAAA,QACF,KAAK;AACH,UAAAQ,IAAI6C,IAAM,GACVrD,EAAI,YAAY;AAChB;AAAA,QACF;AACE,UAAAQ,KAAK4C,IAAQC,KAAO,GACpBrD,EAAI,YAAY;AAAA,MAAA;AAGpB,MAAAA,EAAI,eAAe,UACnBS,KAAK;AAAA,IACP,OAAO;AAGL,cAFAD,IAAI8C,GAEIC,GAAA;AAAA,QACN,KAAK;AACH,UAAA9C,IAAI2C,IAAQb;AACZ;AAAA,QACF,KAAK;AACH,UAAA9B,IAAI4C,IAAM;AACV;AAAA,QACF;AACE,UAAA5C,KAAK2C,IAAQC,KAAO;AAAA,MAAA;AAGxB,MAAArD,EAAI,YAAY,UAChBA,EAAI,eAAe;AAAA,IACrB;AAGA,QAAIyD,KAAmB,IAAM;AAC3B,MAAAzD,EAAI,YAAYyD,KAAmB;AACnC,YAAME,IAAM3D,EAAI,cAAc,SAASQ,IAAI2B,IACvCnC,EAAI,cAAc,UAAUQ,IAAI8B,IAAYH,IAC1C3B,IAAI8B,IAAY;AACtB,MAAAtC,EAAI,SAAS2D,GAAKlD,IAAI8B,IAAaJ,GAASG,GAAWC,CAAU;AAAA,IACnE;AAGA,SAAK,gBAAgBvC,GAAKmD,GAAO3C,GAAGC,GAAG;AAAA,MACrC,UAAUjB,EAAe,KAAK;AAAA,MAC9B,YAAYA,EAAe,KAAK;AAAA,MAChC,OAAOA,EAAe,KAAK;AAAA,MAC3B,OAAOQ,EAAI;AAAA,MACX,UAAUA,EAAI;AAAA,IAAA,GACbG,CAAQ,GAEXH,EAAI,QAAA;AAAA,EACN;AAAA,EAEQ,oBACNA,GACAmD,GACA3C,GACAC,GACAN,GACM;AACN,IAAAH,EAAI,KAAA,GAEJA,EAAI,OAAO,GAAGR,EAAe,KAAK,QAAQ,MAAMA,EAAe,KAAK,UAAU;AAC9E,UAAMkE,IAAU1D,EAAI,YAAYmD,CAAK,GAC/BhB,IAAU,GACVG,IAAYoB,EAAQ,QAAQvB,IAAU,GACtCI,IAAa/C,EAAe,KAAK,WAAW2C,IAAU;AAG5D,IAAAnC,EAAI,YAAY,sBAChBA,EAAI,UAAA,GACJA,EAAI,UAAUQ,IAAI8B,IAAY,GAAG7B,IAAI8B,IAAa,GAAGD,GAAWC,GAAY,CAAC,GAC7EvC,EAAI,KAAA,GAGJ,KAAK,gBAAgBA,GAAKmD,GAAO3C,GAAGC,GAAG;AAAA,MACrC,UAAUjB,EAAe,KAAK;AAAA,MAC9B,YAAYA,EAAe,KAAK;AAAA,MAChC,OAAOA,EAAe,KAAK;AAAA,MAC3B,OAAO;AAAA,MACP,UAAU;AAAA,IAAA,GACTW,CAAQ,GAEXH,EAAI,QAAA;AAAA,EACN;AACF;ACnyBA,MAAM4D,IAAsC;AAAA,EACxC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU,CAAC,YAAY;AAAA,EACvB,MAAM,CAAC,cAAc,WAAW,OAAO;AAC3C;AAOO,SAASC,EAAkBC,IAAmC,IAA0C;AAC3G,MAAIC;AAEJ,SAAO;AAAA,IACH,UAAUH;AAAA,IAEV,OAAO5D,GAAoB;AACvB,MAAA+D,IAAoB,IAAItE,EAAA,GAKxBO,EAAI,QAAQ,IAAI,WAAW+D,CAAiB;AAAA,IAChD;AAAA,IAEA,gBAAgB/D,GAAK;AACjB,YAAMC,IAAWD,EAAI,OAAO,UACtBgE,IAAahE,EAAI,KAAK,cAAA,GAGtBiE,IAAcjE,EAAI,UAAe,iBAAiB,GAClDG,IAAW8D,KAAA,gBAAAA,EAAa;AAG9B,MAAAF,EAAkB;AAAA,QACd/D,EAAI,OAAO;AAAA,QACXC;AAAA,QACA+D;AAAA,QACA7D;AAAA,MAAA;AAAA,IAER;AAAA,IAEA,UAAU+D,GAAqB;AAC3B,MAAAH,EAAkB,MAAA;AAAA,IACtB;AAAA,IAEA,KAAK;AAAA,MACD,aAAa;AACT,eAAOA;AAAA,MACX;AAAA,MACA,IAAIpE,GAAwB;AACxB,eAAOoE,EAAkB,IAAIpE,CAAU;AAAA,MAC3C;AAAA,MACA,OAAOC,GAAY;AACf,eAAOmE,EAAkB,OAAOnE,CAAE;AAAA,MACtC;AAAA,MACA,OAAOA,GAAYE,GAA8B;AAC7C,eAAOiE,EAAkB,OAAOnE,GAAIE,CAAO;AAAA,MAC/C;AAAA,MACA,IAAIF,GAAY;AACZ,eAAOmE,EAAkB,IAAInE,CAAE;AAAA,MACnC;AAAA,MACA,SAAS;AACL,eAAOmE,EAAkB,OAAA;AAAA,MAC7B;AAAA,MACA,QAAQ;AACJ,QAAAA,EAAkB,MAAA;AAAA,MACtB;AAAA,IAAA;AAAA,EACJ;AAER;"}
1
+ {"version":3,"file":"annotations.js","sources":["../../src/core/annotations/AnnotationManager.ts","../../src/plugins/annotations/index.ts"],"sourcesContent":["/**\n * AnnotationManager - Manages chart annotations\n * \n * Handles creation, update, removal, and rendering of all annotation types.\n */\n\nimport type { Bounds } from '../../types';\nimport type {\n Annotation,\n HorizontalLineAnnotation,\n VerticalLineAnnotation,\n RectangleAnnotation,\n BandAnnotation,\n TextAnnotation,\n ArrowAnnotation,\n} from './types';\n\n// ============================================\n// Default Styles\n// ============================================\n\nconst DEFAULT_STYLES = {\n line: {\n color: 'rgba(255, 255, 255, 0.7)',\n lineWidth: 1,\n lineDash: [] as number[],\n },\n rectangle: {\n fillColor: 'rgba(100, 100, 255, 0.2)',\n strokeColor: 'rgba(100, 100, 255, 0.5)',\n strokeWidth: 1,\n },\n text: {\n fontSize: 12,\n fontFamily: 'Inter, system-ui, sans-serif',\n color: '#ffffff',\n backgroundColor: 'rgba(0, 0, 0, 0.7)',\n padding: 4,\n },\n arrow: {\n color: 'rgba(255, 255, 255, 0.7)',\n lineWidth: 2,\n headSize: 10,\n },\n};\n\n// ============================================\n// Plot Area Type\n// ============================================\n\nexport interface PlotArea {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n// ============================================\n// AnnotationManager Class\n// ============================================\n\nexport class AnnotationManager {\n private annotations: Map<string, Annotation> = new Map();\n private idCounter = 0;\n\n // ----------------------------------------\n // CRUD Operations\n // ----------------------------------------\n\n /**\n * Add a new annotation\n * @returns The annotation ID\n */\n add(annotation: Annotation): string {\n const id = annotation.id ?? `annotation-${++this.idCounter}`;\n const resolved: Annotation = {\n ...annotation,\n id,\n visible: annotation.visible ?? true,\n interactive: annotation.interactive ?? false,\n zIndex: annotation.zIndex ?? 0,\n };\n\n this.annotations.set(id, resolved);\n return id;\n }\n\n /**\n * Remove an annotation by ID\n */\n remove(id: string): boolean {\n return this.annotations.delete(id);\n }\n\n /**\n * Update an annotation\n */\n update(id: string, updates: Partial<Annotation>): void {\n const existing = this.annotations.get(id);\n if (existing) {\n this.annotations.set(id, { ...existing, ...updates } as Annotation);\n }\n }\n\n /**\n * Get an annotation by ID\n */\n get(id: string): Annotation | undefined {\n return this.annotations.get(id);\n }\n\n /**\n * Get all annotations\n */\n getAll(): Annotation[] {\n return Array.from(this.annotations.values());\n }\n\n /**\n * Clear all annotations\n */\n clear(): void {\n this.annotations.clear();\n }\n\n /**\n * Get count of annotations\n */\n get count(): number {\n return this.annotations.size;\n }\n\n // ----------------------------------------\n // Rendering\n // ----------------------------------------\n\n /**\n * Render all annotations\n */\n render(\n ctx: CanvasRenderingContext2D,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n // Sort by zIndex\n const sorted = this.getAll()\n .filter(a => a.visible !== false)\n .sort((a, b) => (a.zIndex ?? 0) - (b.zIndex ?? 0));\n\n ctx.save();\n\n // Clip to plot area\n ctx.beginPath();\n ctx.rect(plotArea.x, plotArea.y, plotArea.width, plotArea.height);\n ctx.clip();\n\n for (const annotation of sorted) {\n this.renderAnnotation(ctx, annotation, plotArea, bounds, latexAPI);\n }\n\n ctx.restore();\n }\n\n /**\n * Helper to draw text or LaTeX\n */\n private drawLatexOrText(\n ctx: CanvasRenderingContext2D,\n text: string,\n x: number,\n y: number,\n options: {\n fontSize: number;\n fontFamily: string;\n fontWeight?: string | number;\n color: string;\n align?: CanvasTextAlign;\n baseline?: CanvasTextBaseline;\n rotation?: number;\n latex?: boolean;\n },\n latexAPI?: any\n ): void {\n const isLatex = (options.latex || text.includes('\\\\') || text.includes('^') || text.includes('_') || (text.includes('{') && text.includes('}'))) &&\n !!latexAPI && (typeof latexAPI.render === 'function');\n\n if (isLatex) {\n ctx.save();\n ctx.translate(x, y);\n if (options.rotation) ctx.rotate((options.rotation * Math.PI) / 180);\n\n const dims = latexAPI.measure(text, {\n fontSize: options.fontSize,\n fontFamily: options.fontFamily,\n color: options.color\n });\n\n let lx = 0;\n let ly = 0;\n\n // Handle Horizontal Alignment\n const align = options.align ?? \"left\";\n if (align === \"center\") lx = -dims.width / 2;\n else if (align === \"right\") lx = -dims.width;\n\n // Handle Vertical Alignment based on alphabetic baseline of the plugin\n // The plugin draws with textBaseline = 'alphabetic' at the provided y\n const baseline = options.baseline ?? \"alphabetic\";\n if (baseline === \"middle\") {\n ly = -dims.height / 2 + dims.baseline;\n } else if (baseline === \"top\" || baseline === \"hanging\") {\n ly = dims.baseline;\n } else if (baseline === \"bottom\" || baseline === \"ideographic\") {\n ly = -(dims.height - dims.baseline);\n } else {\n // 'alphabetic' or default\n ly = 0;\n }\n\n latexAPI.render(text, ctx, lx, ly, {\n fontSize: options.fontSize,\n fontFamily: options.fontFamily,\n color: options.color\n });\n ctx.restore();\n } else {\n ctx.save();\n ctx.font = `${options.fontWeight ?? ''} ${options.fontSize}px ${options.fontFamily}`;\n ctx.fillStyle = options.color;\n ctx.textAlign = options.align ?? \"left\";\n ctx.textBaseline = options.baseline ?? \"alphabetic\";\n ctx.translate(x, y);\n if (options.rotation) ctx.rotate((options.rotation * Math.PI) / 180);\n ctx.fillText(text, 0, 0);\n ctx.restore();\n }\n }\n\n private renderAnnotation(\n ctx: CanvasRenderingContext2D,\n annotation: Annotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n switch (annotation.type) {\n case 'horizontal-line':\n this.renderHorizontalLine(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n case 'vertical-line':\n this.renderVerticalLine(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n case 'rectangle':\n this.renderRectangle(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n case 'band':\n this.renderBand(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n case 'text':\n this.renderText(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n case 'arrow':\n this.renderArrow(ctx, annotation, plotArea, bounds, latexAPI);\n break;\n }\n }\n\n // ----------------------------------------\n // Coordinate Conversion\n // ----------------------------------------\n\n private dataToPixelX(value: number, bounds: Bounds, plotArea: PlotArea): number {\n const normalized = (value - bounds.xMin) / (bounds.xMax - bounds.xMin);\n return plotArea.x + normalized * plotArea.width;\n }\n\n private dataToPixelY(value: number, bounds: Bounds, plotArea: PlotArea): number {\n const normalized = (value - bounds.yMin) / (bounds.yMax - bounds.yMin);\n return plotArea.y + plotArea.height * (1 - normalized);\n }\n\n // ----------------------------------------\n // Render: Horizontal Line\n // ----------------------------------------\n\n private renderHorizontalLine(\n ctx: CanvasRenderingContext2D,\n annotation: HorizontalLineAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n const y = this.dataToPixelY(annotation.y, bounds, plotArea);\n\n // Skip if outside visible area\n if (y < plotArea.y || y > plotArea.y + plotArea.height) return;\n\n const xStart = annotation.xMin !== undefined\n ? Math.max(this.dataToPixelX(annotation.xMin, bounds, plotArea), plotArea.x)\n : plotArea.x;\n const xEnd = annotation.xMax !== undefined\n ? Math.min(this.dataToPixelX(annotation.xMax, bounds, plotArea), plotArea.x + plotArea.width)\n : plotArea.x + plotArea.width;\n\n ctx.save();\n ctx.strokeStyle = annotation.color ?? DEFAULT_STYLES.line.color;\n ctx.lineWidth = annotation.lineWidth ?? DEFAULT_STYLES.line.lineWidth;\n ctx.setLineDash(annotation.lineDash ?? DEFAULT_STYLES.line.lineDash);\n\n ctx.beginPath();\n ctx.moveTo(xStart, y);\n ctx.lineTo(xEnd, y);\n ctx.stroke();\n\n // Render label if present\n if (annotation.label) {\n this.renderLineLabel(\n ctx,\n annotation.label,\n xStart, xEnd, y,\n annotation.labelPosition ?? 'right',\n 'horizontal',\n annotation.labelBackground,\n latexAPI\n );\n }\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Render: Vertical Line\n // ----------------------------------------\n\n private renderVerticalLine(\n ctx: CanvasRenderingContext2D,\n annotation: VerticalLineAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n const x = this.dataToPixelX(annotation.x, bounds, plotArea);\n\n // Skip if outside visible area\n if (x < plotArea.x || x > plotArea.x + plotArea.width) return;\n\n const yStart = annotation.yMin !== undefined\n ? Math.min(this.dataToPixelY(annotation.yMin, bounds, plotArea), plotArea.y + plotArea.height)\n : plotArea.y;\n const yEnd = annotation.yMax !== undefined\n ? Math.max(this.dataToPixelY(annotation.yMax, bounds, plotArea), plotArea.y)\n : plotArea.y + plotArea.height;\n\n ctx.save();\n ctx.strokeStyle = annotation.color ?? DEFAULT_STYLES.line.color;\n ctx.lineWidth = annotation.lineWidth ?? DEFAULT_STYLES.line.lineWidth;\n ctx.setLineDash(annotation.lineDash ?? DEFAULT_STYLES.line.lineDash);\n\n ctx.beginPath();\n ctx.moveTo(x, yStart);\n ctx.lineTo(x, yEnd);\n ctx.stroke();\n\n // Render label if present\n if (annotation.label) {\n this.renderLineLabel(\n ctx,\n annotation.label,\n yStart, yEnd, x,\n annotation.labelPosition ?? 'top',\n 'vertical',\n annotation.labelBackground,\n latexAPI\n );\n }\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Render: Rectangle\n // ----------------------------------------\n\n private renderRectangle(\n ctx: CanvasRenderingContext2D,\n annotation: RectangleAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n const x1 = this.dataToPixelX(annotation.xMin, bounds, plotArea);\n const x2 = this.dataToPixelX(annotation.xMax, bounds, plotArea);\n const y1 = this.dataToPixelY(annotation.yMax, bounds, plotArea); // Note: Y is inverted\n const y2 = this.dataToPixelY(annotation.yMin, bounds, plotArea);\n\n const x = Math.min(x1, x2);\n const y = Math.min(y1, y2);\n const width = Math.abs(x2 - x1);\n const height = Math.abs(y2 - y1);\n\n ctx.save();\n\n // Fill\n if (annotation.fillColor) {\n ctx.fillStyle = annotation.fillColor;\n ctx.fillRect(x, y, width, height);\n }\n\n // Stroke\n if (annotation.strokeColor) {\n ctx.strokeStyle = annotation.strokeColor;\n ctx.lineWidth = annotation.strokeWidth ?? DEFAULT_STYLES.rectangle.strokeWidth;\n ctx.setLineDash(annotation.strokeDash ?? []);\n ctx.strokeRect(x, y, width, height);\n }\n\n // Label\n if (annotation.label) {\n this.renderCenteredLabel(ctx, annotation.label, x + width / 2, y + height / 2, latexAPI);\n }\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Render: Band\n // ----------------------------------------\n\n private renderBand(\n ctx: CanvasRenderingContext2D,\n annotation: BandAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n // Determine band type and calculate bounds\n let x: number, y: number, width: number, height: number;\n\n if (annotation.xMin !== undefined && annotation.xMax !== undefined) {\n // Vertical band (spans full Y)\n const x1 = this.dataToPixelX(annotation.xMin, bounds, plotArea);\n const x2 = this.dataToPixelX(annotation.xMax, bounds, plotArea);\n x = Math.min(x1, x2);\n width = Math.abs(x2 - x1);\n y = plotArea.y;\n height = plotArea.height;\n\n if (annotation.yMin !== undefined) {\n const yPixel = this.dataToPixelY(annotation.yMin, bounds, plotArea);\n height = yPixel - y;\n }\n if (annotation.yMax !== undefined) {\n const yPixel = this.dataToPixelY(annotation.yMax, bounds, plotArea);\n y = yPixel;\n height = plotArea.y + plotArea.height - y;\n }\n } else if (annotation.yMin !== undefined && annotation.yMax !== undefined) {\n // Horizontal band (spans full X)\n const y1 = this.dataToPixelY(annotation.yMax, bounds, plotArea);\n const y2 = this.dataToPixelY(annotation.yMin, bounds, plotArea);\n y = Math.min(y1, y2);\n height = Math.abs(y2 - y1);\n x = plotArea.x;\n width = plotArea.width;\n } else {\n // Invalid band configuration\n return;\n }\n\n ctx.save();\n\n // Fill\n ctx.fillStyle = annotation.fillColor ?? DEFAULT_STYLES.rectangle.fillColor;\n ctx.fillRect(x, y, width, height);\n\n // Stroke\n if (annotation.strokeColor) {\n ctx.strokeStyle = annotation.strokeColor;\n ctx.lineWidth = annotation.strokeWidth ?? 1;\n ctx.strokeRect(x, y, width, height);\n }\n\n // Label\n if (annotation.label) {\n let labelX = x + width / 2;\n let labelY = y + height / 2;\n\n switch (annotation.labelPosition) {\n case 'top':\n labelY = y + 15;\n break;\n case 'bottom':\n labelY = y + height - 5;\n break;\n case 'left':\n labelX = x + 10;\n break;\n case 'right':\n labelX = x + width - 10;\n break;\n }\n\n this.renderCenteredLabel(ctx, annotation.label, labelX, labelY, latexAPI);\n }\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Render: Text\n // ----------------------------------------\n\n private renderText(\n ctx: CanvasRenderingContext2D,\n annotation: TextAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n const x = this.dataToPixelX(annotation.x, bounds, plotArea);\n const y = this.dataToPixelY(annotation.y, bounds, plotArea);\n\n ctx.save();\n\n // Apply rotation if specified\n if (annotation.rotation) {\n ctx.translate(x, y);\n ctx.rotate((annotation.rotation * Math.PI) / 180);\n ctx.translate(-x, -y);\n }\n\n const fontSize = annotation.fontSize ?? DEFAULT_STYLES.text.fontSize;\n const fontFamily = annotation.fontFamily ?? DEFAULT_STYLES.text.fontFamily;\n const fontWeight = annotation.fontWeight ?? 'normal';\n const lineHeight = fontSize * 1.2;\n\n ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n\n // Support multi-line text\n const lines = annotation.text.split('\\n');\n const padding = annotation.padding ?? DEFAULT_STYLES.text.padding;\n\n // Measure all lines to find max width\n let maxWidth = 0;\n for (const line of lines) {\n maxWidth = Math.max(maxWidth, ctx.measureText(line).width);\n }\n\n const textWidth = maxWidth + padding * 2;\n const textHeight = (lines.length * lineHeight) - (lineHeight - fontSize) + padding * 2;\n\n // Calculate position based on anchor\n let drawX = x;\n let drawY = y;\n\n switch (annotation.anchor) {\n case 'top-left':\n drawX += textWidth / 2;\n drawY += textHeight / 2;\n break;\n case 'top-right':\n drawX -= textWidth / 2;\n drawY += textHeight / 2;\n break;\n case 'bottom-left':\n drawX += textWidth / 2;\n drawY -= textHeight / 2;\n break;\n case 'bottom-right':\n drawX -= textWidth / 2;\n drawY -= textHeight / 2;\n break;\n case 'top-center':\n drawY += textHeight / 2;\n break;\n case 'bottom-center':\n drawY -= textHeight / 2;\n break;\n case 'left-center':\n drawX += textWidth / 2;\n break;\n case 'right-center':\n drawX -= textWidth / 2;\n break;\n }\n\n // Draw background\n if (annotation.backgroundColor) {\n ctx.fillStyle = annotation.backgroundColor;\n ctx.beginPath();\n ctx.roundRect(\n drawX - textWidth / 2,\n drawY - textHeight / 2,\n textWidth,\n textHeight,\n 4\n );\n ctx.fill();\n }\n\n // Draw text lines\n const color = annotation.color ?? DEFAULT_STYLES.text.color;\n const startY = drawY - (textHeight / 2) + padding + (fontSize / 2);\n\n lines.forEach((line, i) => {\n this.drawLatexOrText(ctx, line, drawX, startY + i * lineHeight, {\n fontSize,\n fontFamily,\n fontWeight,\n color,\n align: 'center',\n baseline: 'middle',\n latex: annotation.latex\n }, latexAPI);\n });\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Render: Arrow\n // ----------------------------------------\n\n private renderArrow(\n ctx: CanvasRenderingContext2D,\n annotation: ArrowAnnotation,\n plotArea: PlotArea,\n bounds: Bounds,\n latexAPI?: any\n ): void {\n const x1 = this.dataToPixelX(annotation.x1, bounds, plotArea);\n const y1 = this.dataToPixelY(annotation.y1, bounds, plotArea);\n const x2 = this.dataToPixelX(annotation.x2, bounds, plotArea);\n const y2 = this.dataToPixelY(annotation.y2, bounds, plotArea);\n\n ctx.save();\n ctx.strokeStyle = annotation.color ?? DEFAULT_STYLES.arrow.color;\n ctx.fillStyle = annotation.color ?? DEFAULT_STYLES.arrow.color;\n ctx.lineWidth = annotation.lineWidth ?? DEFAULT_STYLES.arrow.lineWidth;\n\n // Draw line\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n\n // Draw arrow head\n const headSize = annotation.headSize ?? DEFAULT_STYLES.arrow.headSize;\n const angle = Math.atan2(y2 - y1, x2 - x1);\n\n const headStyle = annotation.headStyle ?? 'filled';\n\n if (headStyle !== 'none') {\n ctx.beginPath();\n ctx.moveTo(x2, y2);\n ctx.lineTo(\n x2 - headSize * Math.cos(angle - Math.PI / 6),\n y2 - headSize * Math.sin(angle - Math.PI / 6)\n );\n\n if (headStyle === 'filled') {\n ctx.lineTo(\n x2 - headSize * Math.cos(angle + Math.PI / 6),\n y2 - headSize * Math.sin(angle + Math.PI / 6)\n );\n ctx.closePath();\n ctx.fill();\n } else {\n ctx.moveTo(x2, y2);\n ctx.lineTo(\n x2 - headSize * Math.cos(angle + Math.PI / 6),\n y2 - headSize * Math.sin(angle + Math.PI / 6)\n );\n ctx.stroke();\n }\n }\n\n // Draw tail arrow if specified\n if (annotation.showTail) {\n const tailAngle = angle + Math.PI;\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(\n x1 - headSize * Math.cos(tailAngle - Math.PI / 6),\n y1 - headSize * Math.sin(tailAngle - Math.PI / 6)\n );\n ctx.lineTo(\n x1 - headSize * Math.cos(tailAngle + Math.PI / 6),\n y1 - headSize * Math.sin(tailAngle + Math.PI / 6)\n );\n ctx.closePath();\n ctx.fill();\n }\n\n // Draw label if present\n if (annotation.label) {\n const midX = (x1 + x2) / 2;\n const midY = (y1 + y2) / 2;\n this.renderCenteredLabel(ctx, annotation.label, midX, midY - 10, latexAPI);\n }\n\n ctx.restore();\n }\n\n // ----------------------------------------\n // Helper: Render Labels\n // ----------------------------------------\n\n private renderLineLabel(\n ctx: CanvasRenderingContext2D,\n label: string,\n start: number,\n end: number,\n cross: number,\n position: string,\n orientation: 'horizontal' | 'vertical',\n backgroundColor?: string,\n latexAPI?: any\n ): void {\n ctx.save();\n\n ctx.font = `${DEFAULT_STYLES.text.fontSize}px ${DEFAULT_STYLES.text.fontFamily}`;\n const metrics = ctx.measureText(label);\n const padding = 4;\n const textWidth = metrics.width + padding * 2;\n const textHeight = DEFAULT_STYLES.text.fontSize + padding * 2;\n\n let x: number, y: number;\n\n if (orientation === 'horizontal') {\n y = cross;\n\n switch (position) {\n case 'left':\n x = start + 5;\n ctx.textAlign = 'left';\n break;\n case 'right':\n x = end - 5;\n ctx.textAlign = 'right';\n break;\n default:\n x = (start + end) / 2;\n ctx.textAlign = 'center';\n }\n\n ctx.textBaseline = 'bottom';\n y -= 4;\n } else {\n x = cross;\n\n switch (position) {\n case 'top':\n y = start + textHeight;\n break;\n case 'bottom':\n y = end - 5;\n break;\n default:\n y = (start + end) / 2;\n }\n\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n }\n\n // Background\n if (backgroundColor ?? true) {\n ctx.fillStyle = backgroundColor ?? 'rgba(0, 0, 0, 0.7)';\n const bgX = ctx.textAlign === 'left' ? x - padding\n : ctx.textAlign === 'right' ? x - textWidth + padding\n : x - textWidth / 2;\n ctx.fillRect(bgX, y - textHeight + padding, textWidth, textHeight);\n }\n\n // Text\n this.drawLatexOrText(ctx, label, x, y, {\n fontSize: DEFAULT_STYLES.text.fontSize,\n fontFamily: DEFAULT_STYLES.text.fontFamily,\n color: DEFAULT_STYLES.text.color,\n align: ctx.textAlign,\n baseline: ctx.textBaseline,\n }, latexAPI);\n\n ctx.restore();\n }\n\n private renderCenteredLabel(\n ctx: CanvasRenderingContext2D,\n label: string,\n x: number,\n y: number,\n latexAPI?: any\n ): void {\n ctx.save();\n\n ctx.font = `${DEFAULT_STYLES.text.fontSize}px ${DEFAULT_STYLES.text.fontFamily}`;\n const metrics = ctx.measureText(label);\n const padding = 4;\n const textWidth = metrics.width + padding * 2;\n const textHeight = DEFAULT_STYLES.text.fontSize + padding * 2;\n\n // Background\n ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';\n ctx.beginPath();\n ctx.roundRect(x - textWidth / 2, y - textHeight / 2, textWidth, textHeight, 3);\n ctx.fill();\n\n // Text\n this.drawLatexOrText(ctx, label, x, y, {\n fontSize: DEFAULT_STYLES.text.fontSize,\n fontFamily: DEFAULT_STYLES.text.fontFamily,\n color: DEFAULT_STYLES.text.color,\n align: 'center',\n baseline: 'middle',\n }, latexAPI);\n\n ctx.restore();\n }\n}\n","/**\n * Velo Plot - Annotations Plugin\n * \n * Provides annotation capabilities including:\n * - Line, Rectangle, Band, Text, Arrow annotations\n * - Annotation management and rendering\n * \n * @module plugins/annotations\n */\n\nimport { AnnotationManager } from \"../../core/annotations\";\nimport type { Annotation, AnnotationType } from \"../../core/annotations\";\nimport type { PluginManifest, ChartPlugin, PluginContext } from \"../types\";\n\nexport interface PluginAnnotationsConfig {\n /** Default styles for annotations */\n defaultStyles?: Record<string, any>;\n}\n\nconst manifestAnnotations: PluginManifest = {\n name: \"velo-plot-annotations\",\n version: \"1.0.0\",\n description: \"Annotation support for velo-plot\",\n provides: [\"annotation\"],\n tags: [\"annotation\", \"overlay\", \"label\"],\n};\n\n/**\n * VeloPlot Annotations Plugin\n * \n * Adds support for drawing lines, shapes, and labels on the chart.\n */\nexport function PluginAnnotations(_config: PluginAnnotationsConfig = {}): ChartPlugin<PluginAnnotationsConfig> {\n let annotationManager: AnnotationManager;\n\n return {\n manifest: manifestAnnotations,\n\n onInit(ctx: PluginContext) {\n annotationManager = new AnnotationManager();\n\n // In a real implementation, we would register this manager in the context\n // so the chart can delegate annotation calls to it.\n // For now, we store it in storage for retrieval.\n ctx.storage.set(\"manager\", annotationManager);\n },\n\n onRenderOverlay(ctx) {\n if (ctx.chart.getActiveRenderer() === \"svg\") return;\n\n const plotArea = ctx.render.plotArea;\n const viewBounds = ctx.data.getViewBounds();\n\n // Get LaTeX API if plugin is available\n const latexPlugin = ctx.getPlugin<any>(\"velo-plot-latex\");\n const latexAPI = latexPlugin?.api;\n\n // Render all annotations using the manager and provided contexts\n annotationManager.render(\n ctx.render.ctx2d!,\n plotArea,\n viewBounds,\n latexAPI\n );\n },\n\n onDestroy(_ctx: PluginContext) {\n annotationManager.clear();\n },\n\n api: {\n getManager() {\n return annotationManager;\n },\n add(annotation: Annotation) {\n return annotationManager.add(annotation);\n },\n remove(id: string) {\n return annotationManager.remove(id);\n },\n update(id: string, updates: Partial<Annotation>) {\n return annotationManager.update(id, updates);\n },\n get(id: string) {\n return annotationManager.get(id);\n },\n getAll() {\n return annotationManager.getAll();\n },\n clear() {\n annotationManager.clear();\n }\n }\n };\n}\n\nexport { AnnotationManager };\nexport type { Annotation, AnnotationType };\nexport default PluginAnnotations;\n"],"names":["DEFAULT_STYLES","AnnotationManager","__publicField","annotation","id","resolved","updates","existing","ctx","plotArea","bounds","latexAPI","sorted","a","b","text","x","y","options","dims","lx","ly","align","baseline","value","normalized","xStart","xEnd","yStart","yEnd","x1","x2","y1","y2","width","height","labelX","labelY","fontSize","fontFamily","fontWeight","lineHeight","lines","padding","maxWidth","line","textWidth","textHeight","drawX","drawY","color","startY","i","headSize","angle","headStyle","tailAngle","midX","midY","label","start","end","cross","position","orientation","backgroundColor","metrics","bgX","manifestAnnotations","PluginAnnotations","_config","annotationManager","viewBounds","latexPlugin","_ctx"],"mappings":";;;AAqBA,MAAMA,IAAiB;AAAA,EACrB,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,WAAW;AAAA,IACX,UAAU,CAAA;AAAA,EAAC;AAAA,EAEb,WAAW;AAAA,IACT,WAAW;AAAA,IAEX,aAAa;AAAA,EAAA;AAAA,EAEf,MAAM;AAAA,IACJ,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,OAAO;AAAA,IAEP,SAAS;AAAA,EAAA;AAAA,EAEX,OAAO;AAAA,IACL,OAAO;AAAA,IACP,WAAW;AAAA,IACX,UAAU;AAAA,EAAA;AAEd;AAiBO,MAAMC,EAAkB;AAAA,EAAxB;AACG,IAAAC,EAAA,yCAA2C,IAAA;AAC3C,IAAAA,EAAA,mBAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUpB,IAAIC,GAAgC;AAClC,UAAMC,IAAKD,EAAW,MAAM,cAAc,EAAE,KAAK,SAAS,IACpDE,IAAuB;AAAA,MAC3B,GAAGF;AAAA,MACH,IAAAC;AAAA,MACA,SAASD,EAAW,WAAW;AAAA,MAC/B,aAAaA,EAAW,eAAe;AAAA,MACvC,QAAQA,EAAW,UAAU;AAAA,IAAA;AAG/B,gBAAK,YAAY,IAAIC,GAAIC,CAAQ,GAC1BD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAOA,GAAqB;AAC1B,WAAO,KAAK,YAAY,OAAOA,CAAE;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAOA,GAAYE,GAAoC;AACrD,UAAMC,IAAW,KAAK,YAAY,IAAIH,CAAE;AACxC,IAAIG,KACF,KAAK,YAAY,IAAIH,GAAI,EAAE,GAAGG,GAAU,GAAGD,GAAuB;AAAA,EAEtE;AAAA;AAAA;AAAA;AAAA,EAKA,IAAIF,GAAoC;AACtC,WAAO,KAAK,YAAY,IAAIA,CAAE;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAuB;AACrB,WAAO,MAAM,KAAK,KAAK,YAAY,QAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,YAAY,MAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAAgB;AAClB,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OACEI,GACAC,GACAC,GACAC,GACM;AAEN,UAAMC,IAAS,KAAK,SACjB,OAAO,CAAAC,MAAKA,EAAE,YAAY,EAAK,EAC/B,KAAK,CAACA,GAAGC,OAAOD,EAAE,UAAU,MAAMC,EAAE,UAAU,EAAE;AAEnD,IAAAN,EAAI,KAAA,GAGJA,EAAI,UAAA,GACJA,EAAI,KAAKC,EAAS,GAAGA,EAAS,GAAGA,EAAS,OAAOA,EAAS,MAAM,GAChED,EAAI,KAAA;AAEJ,eAAWL,KAAcS;AACvB,WAAK,iBAAiBJ,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AAGnE,IAAAH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAKQ,gBACNA,GACAO,GACAC,GACAC,GACAC,GAUAP,GACM;AAIN,SAHiBO,EAAQ,SAASH,EAAK,SAAS,IAAI,KAAKA,EAAK,SAAS,GAAG,KAAKA,EAAK,SAAS,GAAG,KAAMA,EAAK,SAAS,GAAG,KAAKA,EAAK,SAAS,GAAG,MAC3I,CAAC,CAACJ,KAAa,OAAOA,EAAS,UAAW,YAE/B;AACX,MAAAH,EAAI,KAAA,GACJA,EAAI,UAAUQ,GAAGC,CAAC,GACdC,EAAQ,YAAUV,EAAI,OAAQU,EAAQ,WAAW,KAAK,KAAM,GAAG;AAEnE,YAAMC,IAAOR,EAAS,QAAQI,GAAM;AAAA,QAClC,UAAUG,EAAQ;AAAA,QAClB,YAAYA,EAAQ;AAAA,QACpB,OAAOA,EAAQ;AAAA,MAAA,CAChB;AAED,UAAIE,IAAK,GACLC,IAAK;AAGT,YAAMC,IAAQJ,EAAQ,SAAS;AAC/B,MAAII,MAAU,WAAUF,IAAK,CAACD,EAAK,QAAQ,IAClCG,MAAU,YAASF,IAAK,CAACD,EAAK;AAIvC,YAAMI,IAAWL,EAAQ,YAAY;AACrC,MAAIK,MAAa,WACfF,IAAK,CAACF,EAAK,SAAS,IAAIA,EAAK,WACpBI,MAAa,SAASA,MAAa,YAC5CF,IAAKF,EAAK,WACDI,MAAa,YAAYA,MAAa,gBAC/CF,IAAK,EAAEF,EAAK,SAASA,EAAK,YAG1BE,IAAK,GAGPV,EAAS,OAAOI,GAAMP,GAAKY,GAAIC,GAAI;AAAA,QACjC,UAAUH,EAAQ;AAAA,QAClB,YAAYA,EAAQ;AAAA,QACpB,OAAOA,EAAQ;AAAA,MAAA,CAChB,GACDV,EAAI,QAAA;AAAA,IACN;AACE,MAAAA,EAAI,KAAA,GACJA,EAAI,OAAO,GAAGU,EAAQ,cAAc,EAAE,IAAIA,EAAQ,QAAQ,MAAMA,EAAQ,UAAU,IAClFV,EAAI,YAAYU,EAAQ,OACxBV,EAAI,YAAYU,EAAQ,SAAS,QACjCV,EAAI,eAAeU,EAAQ,YAAY,cACvCV,EAAI,UAAUQ,GAAGC,CAAC,GACdC,EAAQ,YAAUV,EAAI,OAAQU,EAAQ,WAAW,KAAK,KAAM,GAAG,GACnEV,EAAI,SAASO,GAAM,GAAG,CAAC,GACvBP,EAAI,QAAA;AAAA,EAER;AAAA,EAEQ,iBACNA,GACAL,GACAM,GACAC,GACAC,GACM;AACN,YAAQR,EAAW,MAAA;AAAA,MACjB,KAAK;AACH,aAAK,qBAAqBK,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AACrE;AAAA,MACF,KAAK;AACH,aAAK,mBAAmBH,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AACnE;AAAA,MACF,KAAK;AACH,aAAK,gBAAgBH,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AAChE;AAAA,MACF,KAAK;AACH,aAAK,WAAWH,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AAC3D;AAAA,MACF,KAAK;AACH,aAAK,WAAWH,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AAC3D;AAAA,MACF,KAAK;AACH,aAAK,YAAYH,GAAKL,GAAYM,GAAUC,GAAQC,CAAQ;AAC5D;AAAA,IAAA;AAAA,EAEN;AAAA;AAAA;AAAA;AAAA,EAMQ,aAAaa,GAAed,GAAgBD,GAA4B;AAC9E,UAAMgB,KAAcD,IAAQd,EAAO,SAASA,EAAO,OAAOA,EAAO;AACjE,WAAOD,EAAS,IAAIgB,IAAahB,EAAS;AAAA,EAC5C;AAAA,EAEQ,aAAae,GAAed,GAAgBD,GAA4B;AAC9E,UAAMgB,KAAcD,IAAQd,EAAO,SAASA,EAAO,OAAOA,EAAO;AACjE,WAAOD,EAAS,IAAIA,EAAS,UAAU,IAAIgB;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAMQ,qBACNjB,GACAL,GACAM,GACAC,GACAC,GACM;AACN,UAAMM,IAAI,KAAK,aAAad,EAAW,GAAGO,GAAQD,CAAQ;AAG1D,QAAIQ,IAAIR,EAAS,KAAKQ,IAAIR,EAAS,IAAIA,EAAS,OAAQ;AAExD,UAAMiB,IAASvB,EAAW,SAAS,SAC/B,KAAK,IAAI,KAAK,aAAaA,EAAW,MAAMO,GAAQD,CAAQ,GAAGA,EAAS,CAAC,IACzEA,EAAS,GACPkB,IAAOxB,EAAW,SAAS,SAC7B,KAAK,IAAI,KAAK,aAAaA,EAAW,MAAMO,GAAQD,CAAQ,GAAGA,EAAS,IAAIA,EAAS,KAAK,IAC1FA,EAAS,IAAIA,EAAS;AAE1B,IAAAD,EAAI,KAAA,GACJA,EAAI,cAAcL,EAAW,SAASH,EAAe,KAAK,OAC1DQ,EAAI,YAAYL,EAAW,aAAaH,EAAe,KAAK,WAC5DQ,EAAI,YAAYL,EAAW,YAAYH,EAAe,KAAK,QAAQ,GAEnEQ,EAAI,UAAA,GACJA,EAAI,OAAOkB,GAAQT,CAAC,GACpBT,EAAI,OAAOmB,GAAMV,CAAC,GAClBT,EAAI,OAAA,GAGAL,EAAW,SACb,KAAK;AAAA,MACHK;AAAA,MACAL,EAAW;AAAA,MACXuB;AAAA,MAAQC;AAAA,MAAMV;AAAA,MACdd,EAAW,iBAAiB;AAAA,MAC5B;AAAA,MACAA,EAAW;AAAA,MACXQ;AAAA,IAAA,GAIJH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,mBACNA,GACAL,GACAM,GACAC,GACAC,GACM;AACN,UAAMK,IAAI,KAAK,aAAab,EAAW,GAAGO,GAAQD,CAAQ;AAG1D,QAAIO,IAAIP,EAAS,KAAKO,IAAIP,EAAS,IAAIA,EAAS,MAAO;AAEvD,UAAMmB,IAASzB,EAAW,SAAS,SAC/B,KAAK,IAAI,KAAK,aAAaA,EAAW,MAAMO,GAAQD,CAAQ,GAAGA,EAAS,IAAIA,EAAS,MAAM,IAC3FA,EAAS,GACPoB,IAAO1B,EAAW,SAAS,SAC7B,KAAK,IAAI,KAAK,aAAaA,EAAW,MAAMO,GAAQD,CAAQ,GAAGA,EAAS,CAAC,IACzEA,EAAS,IAAIA,EAAS;AAE1B,IAAAD,EAAI,KAAA,GACJA,EAAI,cAAcL,EAAW,SAASH,EAAe,KAAK,OAC1DQ,EAAI,YAAYL,EAAW,aAAaH,EAAe,KAAK,WAC5DQ,EAAI,YAAYL,EAAW,YAAYH,EAAe,KAAK,QAAQ,GAEnEQ,EAAI,UAAA,GACJA,EAAI,OAAOQ,GAAGY,CAAM,GACpBpB,EAAI,OAAOQ,GAAGa,CAAI,GAClBrB,EAAI,OAAA,GAGAL,EAAW,SACb,KAAK;AAAA,MACHK;AAAA,MACAL,EAAW;AAAA,MACXyB;AAAA,MAAQC;AAAA,MAAMb;AAAA,MACdb,EAAW,iBAAiB;AAAA,MAC5B;AAAA,MACAA,EAAW;AAAA,MACXQ;AAAA,IAAA,GAIJH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,gBACNA,GACAL,GACAM,GACAC,GACAC,GACM;AACN,UAAMmB,IAAK,KAAK,aAAa3B,EAAW,MAAMO,GAAQD,CAAQ,GACxDsB,IAAK,KAAK,aAAa5B,EAAW,MAAMO,GAAQD,CAAQ,GACxDuB,IAAK,KAAK,aAAa7B,EAAW,MAAMO,GAAQD,CAAQ,GACxDwB,IAAK,KAAK,aAAa9B,EAAW,MAAMO,GAAQD,CAAQ,GAExDO,IAAI,KAAK,IAAIc,GAAIC,CAAE,GACnBd,IAAI,KAAK,IAAIe,GAAIC,CAAE,GACnBC,IAAQ,KAAK,IAAIH,IAAKD,CAAE,GACxBK,IAAS,KAAK,IAAIF,IAAKD,CAAE;AAE/B,IAAAxB,EAAI,KAAA,GAGAL,EAAW,cACbK,EAAI,YAAYL,EAAW,WAC3BK,EAAI,SAASQ,GAAGC,GAAGiB,GAAOC,CAAM,IAI9BhC,EAAW,gBACbK,EAAI,cAAcL,EAAW,aAC7BK,EAAI,YAAYL,EAAW,eAAeH,EAAe,UAAU,aACnEQ,EAAI,YAAYL,EAAW,cAAc,CAAA,CAAE,GAC3CK,EAAI,WAAWQ,GAAGC,GAAGiB,GAAOC,CAAM,IAIhChC,EAAW,SACb,KAAK,oBAAoBK,GAAKL,EAAW,OAAOa,IAAIkB,IAAQ,GAAGjB,IAAIkB,IAAS,GAAGxB,CAAQ,GAGzFH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,WACNA,GACAL,GACAM,GACAC,GACAC,GACM;AAEN,QAAIK,GAAWC,GAAWiB,GAAeC;AAEzC,QAAIhC,EAAW,SAAS,UAAaA,EAAW,SAAS,QAAW;AAElE,YAAM2B,IAAK,KAAK,aAAa3B,EAAW,MAAMO,GAAQD,CAAQ,GACxDsB,IAAK,KAAK,aAAa5B,EAAW,MAAMO,GAAQD,CAAQ;AAC9D,MAAAO,IAAI,KAAK,IAAIc,GAAIC,CAAE,GACnBG,IAAQ,KAAK,IAAIH,IAAKD,CAAE,GACxBb,IAAIR,EAAS,GACb0B,IAAS1B,EAAS,QAEdN,EAAW,SAAS,WAEtBgC,IADe,KAAK,aAAahC,EAAW,MAAMO,GAAQD,CAAQ,IAChDQ,IAEhBd,EAAW,SAAS,WAEtBc,IADe,KAAK,aAAad,EAAW,MAAMO,GAAQD,CAAQ,GAElE0B,IAAS1B,EAAS,IAAIA,EAAS,SAASQ;AAAA,IAE5C,WAAWd,EAAW,SAAS,UAAaA,EAAW,SAAS,QAAW;AAEzE,YAAM6B,IAAK,KAAK,aAAa7B,EAAW,MAAMO,GAAQD,CAAQ,GACxDwB,IAAK,KAAK,aAAa9B,EAAW,MAAMO,GAAQD,CAAQ;AAC9D,MAAAQ,IAAI,KAAK,IAAIe,GAAIC,CAAE,GACnBE,IAAS,KAAK,IAAIF,IAAKD,CAAE,GACzBhB,IAAIP,EAAS,GACbyB,IAAQzB,EAAS;AAAA,IACnB;AAEE;AAiBF,QAdAD,EAAI,KAAA,GAGJA,EAAI,YAAYL,EAAW,aAAaH,EAAe,UAAU,WACjEQ,EAAI,SAASQ,GAAGC,GAAGiB,GAAOC,CAAM,GAG5BhC,EAAW,gBACbK,EAAI,cAAcL,EAAW,aAC7BK,EAAI,YAAYL,EAAW,eAAe,GAC1CK,EAAI,WAAWQ,GAAGC,GAAGiB,GAAOC,CAAM,IAIhChC,EAAW,OAAO;AACpB,UAAIiC,IAASpB,IAAIkB,IAAQ,GACrBG,IAASpB,IAAIkB,IAAS;AAE1B,cAAQhC,EAAW,eAAA;AAAA,QACjB,KAAK;AACH,UAAAkC,IAASpB,IAAI;AACb;AAAA,QACF,KAAK;AACH,UAAAoB,IAASpB,IAAIkB,IAAS;AACtB;AAAA,QACF,KAAK;AACH,UAAAC,IAASpB,IAAI;AACb;AAAA,QACF,KAAK;AACH,UAAAoB,IAASpB,IAAIkB,IAAQ;AACrB;AAAA,MAAA;AAGJ,WAAK,oBAAoB1B,GAAKL,EAAW,OAAOiC,GAAQC,GAAQ1B,CAAQ;AAAA,IAC1E;AAEA,IAAAH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,WACNA,GACAL,GACAM,GACAC,GACAC,GACM;AACN,UAAMK,IAAI,KAAK,aAAab,EAAW,GAAGO,GAAQD,CAAQ,GACpDQ,IAAI,KAAK,aAAad,EAAW,GAAGO,GAAQD,CAAQ;AAE1D,IAAAD,EAAI,KAAA,GAGAL,EAAW,aACbK,EAAI,UAAUQ,GAAGC,CAAC,GAClBT,EAAI,OAAQL,EAAW,WAAW,KAAK,KAAM,GAAG,GAChDK,EAAI,UAAU,CAACQ,GAAG,CAACC,CAAC;AAGtB,UAAMqB,IAAWnC,EAAW,YAAYH,EAAe,KAAK,UACtDuC,IAAapC,EAAW,cAAcH,EAAe,KAAK,YAC1DwC,IAAarC,EAAW,cAAc,UACtCsC,IAAaH,IAAW;AAE9B,IAAA9B,EAAI,OAAO,GAAGgC,CAAU,IAAIF,CAAQ,MAAMC,CAAU,IACpD/B,EAAI,YAAY,UAChBA,EAAI,eAAe;AAGnB,UAAMkC,IAAQvC,EAAW,KAAK,MAAM;AAAA,CAAI,GAClCwC,IAAUxC,EAAW,WAAWH,EAAe,KAAK;AAG1D,QAAI4C,IAAW;AACf,eAAWC,KAAQH;AACjB,MAAAE,IAAW,KAAK,IAAIA,GAAUpC,EAAI,YAAYqC,CAAI,EAAE,KAAK;AAG3D,UAAMC,IAAYF,IAAWD,IAAU,GACjCI,IAAcL,EAAM,SAASD,KAAeA,IAAaH,KAAYK,IAAU;AAGrF,QAAIK,IAAQhC,GACRiC,IAAQhC;AAEZ,YAAQd,EAAW,QAAA;AAAA,MACjB,KAAK;AACH,QAAA6C,KAASF,IAAY,GACrBG,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAC,KAASF,IAAY,GACrBG,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAC,KAASF,IAAY,GACrBG,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAC,KAASF,IAAY,GACrBG,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAE,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAE,KAASF,IAAa;AACtB;AAAA,MACF,KAAK;AACH,QAAAC,KAASF,IAAY;AACrB;AAAA,MACF,KAAK;AACH,QAAAE,KAASF,IAAY;AACrB;AAAA,IAAA;AAIJ,IAAI3C,EAAW,oBACbK,EAAI,YAAYL,EAAW,iBAC3BK,EAAI,UAAA,GACJA,EAAI;AAAA,MACFwC,IAAQF,IAAY;AAAA,MACpBG,IAAQF,IAAa;AAAA,MACrBD;AAAA,MACAC;AAAA,MACA;AAAA,IAAA,GAEFvC,EAAI,KAAA;AAIN,UAAM0C,IAAQ/C,EAAW,SAASH,EAAe,KAAK,OAChDmD,IAASF,IAASF,IAAa,IAAKJ,IAAWL,IAAW;AAEhE,IAAAI,EAAM,QAAQ,CAACG,GAAMO,MAAM;AACzB,WAAK,gBAAgB5C,GAAKqC,GAAMG,GAAOG,IAASC,IAAIX,GAAY;AAAA,QAC9D,UAAAH;AAAA,QACA,YAAAC;AAAA,QACA,YAAAC;AAAA,QACA,OAAAU;AAAA,QACA,OAAO;AAAA,QACP,UAAU;AAAA,QACV,OAAO/C,EAAW;AAAA,MAAA,GACjBQ,CAAQ;AAAA,IACb,CAAC,GAEDH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,YACNA,GACAL,GACAM,GACAC,GACAC,GACM;AACN,UAAMmB,IAAK,KAAK,aAAa3B,EAAW,IAAIO,GAAQD,CAAQ,GACtDuB,IAAK,KAAK,aAAa7B,EAAW,IAAIO,GAAQD,CAAQ,GACtDsB,IAAK,KAAK,aAAa5B,EAAW,IAAIO,GAAQD,CAAQ,GACtDwB,IAAK,KAAK,aAAa9B,EAAW,IAAIO,GAAQD,CAAQ;AAE5D,IAAAD,EAAI,KAAA,GACJA,EAAI,cAAcL,EAAW,SAASH,EAAe,MAAM,OAC3DQ,EAAI,YAAYL,EAAW,SAASH,EAAe,MAAM,OACzDQ,EAAI,YAAYL,EAAW,aAAaH,EAAe,MAAM,WAG7DQ,EAAI,UAAA,GACJA,EAAI,OAAOsB,GAAIE,CAAE,GACjBxB,EAAI,OAAOuB,GAAIE,CAAE,GACjBzB,EAAI,OAAA;AAGJ,UAAM6C,IAAWlD,EAAW,YAAYH,EAAe,MAAM,UACvDsD,IAAQ,KAAK,MAAMrB,IAAKD,GAAID,IAAKD,CAAE,GAEnCyB,IAAYpD,EAAW,aAAa;AA4B1C,QA1BIoD,MAAc,WAChB/C,EAAI,UAAA,GACJA,EAAI,OAAOuB,GAAIE,CAAE,GACjBzB,EAAI;AAAA,MACFuB,IAAKsB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,MAC5CrB,IAAKoB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,IAAA,GAG1CC,MAAc,YAChB/C,EAAI;AAAA,MACFuB,IAAKsB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,MAC5CrB,IAAKoB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,IAAA,GAE9C9C,EAAI,UAAA,GACJA,EAAI,KAAA,MAEJA,EAAI,OAAOuB,GAAIE,CAAE,GACjBzB,EAAI;AAAA,MACFuB,IAAKsB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,MAC5CrB,IAAKoB,IAAW,KAAK,IAAIC,IAAQ,KAAK,KAAK,CAAC;AAAA,IAAA,GAE9C9C,EAAI,OAAA,KAKJL,EAAW,UAAU;AACvB,YAAMqD,IAAYF,IAAQ,KAAK;AAC/B,MAAA9C,EAAI,UAAA,GACJA,EAAI,OAAOsB,GAAIE,CAAE,GACjBxB,EAAI;AAAA,QACFsB,IAAKuB,IAAW,KAAK,IAAIG,IAAY,KAAK,KAAK,CAAC;AAAA,QAChDxB,IAAKqB,IAAW,KAAK,IAAIG,IAAY,KAAK,KAAK,CAAC;AAAA,MAAA,GAElDhD,EAAI;AAAA,QACFsB,IAAKuB,IAAW,KAAK,IAAIG,IAAY,KAAK,KAAK,CAAC;AAAA,QAChDxB,IAAKqB,IAAW,KAAK,IAAIG,IAAY,KAAK,KAAK,CAAC;AAAA,MAAA,GAElDhD,EAAI,UAAA,GACJA,EAAI,KAAA;AAAA,IACN;AAGA,QAAIL,EAAW,OAAO;AACpB,YAAMsD,KAAQ3B,IAAKC,KAAM,GACnB2B,KAAQ1B,IAAKC,KAAM;AACzB,WAAK,oBAAoBzB,GAAKL,EAAW,OAAOsD,GAAMC,IAAO,IAAI/C,CAAQ;AAAA,IAC3E;AAEA,IAAAH,EAAI,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAMQ,gBACNA,GACAmD,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAtD,GACM;AACN,IAAAH,EAAI,KAAA,GAEJA,EAAI,OAAO,GAAGR,EAAe,KAAK,QAAQ,MAAMA,EAAe,KAAK,UAAU;AAC9E,UAAMkE,IAAU1D,EAAI,YAAYmD,CAAK,GAC/BhB,IAAU,GACVG,IAAYoB,EAAQ,QAAQvB,IAAU,GACtCI,IAAa/C,EAAe,KAAK,WAAW2C,IAAU;AAE5D,QAAI3B,GAAWC;AAEf,QAAI+C,MAAgB,cAAc;AAGhC,cAFA/C,IAAI6C,GAEIC,GAAA;AAAA,QACN,KAAK;AACH,UAAA/C,IAAI4C,IAAQ,GACZpD,EAAI,YAAY;AAChB;AAAA,QACF,KAAK;AACH,UAAAQ,IAAI6C,IAAM,GACVrD,EAAI,YAAY;AAChB;AAAA,QACF;AACE,UAAAQ,KAAK4C,IAAQC,KAAO,GACpBrD,EAAI,YAAY;AAAA,MAAA;AAGpB,MAAAA,EAAI,eAAe,UACnBS,KAAK;AAAA,IACP,OAAO;AAGL,cAFAD,IAAI8C,GAEIC,GAAA;AAAA,QACN,KAAK;AACH,UAAA9C,IAAI2C,IAAQb;AACZ;AAAA,QACF,KAAK;AACH,UAAA9B,IAAI4C,IAAM;AACV;AAAA,QACF;AACE,UAAA5C,KAAK2C,IAAQC,KAAO;AAAA,MAAA;AAGxB,MAAArD,EAAI,YAAY,UAChBA,EAAI,eAAe;AAAA,IACrB;AAGA,QAAIyD,KAAmB,IAAM;AAC3B,MAAAzD,EAAI,YAAYyD,KAAmB;AACnC,YAAME,IAAM3D,EAAI,cAAc,SAASQ,IAAI2B,IACvCnC,EAAI,cAAc,UAAUQ,IAAI8B,IAAYH,IAC1C3B,IAAI8B,IAAY;AACtB,MAAAtC,EAAI,SAAS2D,GAAKlD,IAAI8B,IAAaJ,GAASG,GAAWC,CAAU;AAAA,IACnE;AAGA,SAAK,gBAAgBvC,GAAKmD,GAAO3C,GAAGC,GAAG;AAAA,MACrC,UAAUjB,EAAe,KAAK;AAAA,MAC9B,YAAYA,EAAe,KAAK;AAAA,MAChC,OAAOA,EAAe,KAAK;AAAA,MAC3B,OAAOQ,EAAI;AAAA,MACX,UAAUA,EAAI;AAAA,IAAA,GACbG,CAAQ,GAEXH,EAAI,QAAA;AAAA,EACN;AAAA,EAEQ,oBACNA,GACAmD,GACA3C,GACAC,GACAN,GACM;AACN,IAAAH,EAAI,KAAA,GAEJA,EAAI,OAAO,GAAGR,EAAe,KAAK,QAAQ,MAAMA,EAAe,KAAK,UAAU;AAC9E,UAAMkE,IAAU1D,EAAI,YAAYmD,CAAK,GAC/BhB,IAAU,GACVG,IAAYoB,EAAQ,QAAQvB,IAAU,GACtCI,IAAa/C,EAAe,KAAK,WAAW2C,IAAU;AAG5D,IAAAnC,EAAI,YAAY,sBAChBA,EAAI,UAAA,GACJA,EAAI,UAAUQ,IAAI8B,IAAY,GAAG7B,IAAI8B,IAAa,GAAGD,GAAWC,GAAY,CAAC,GAC7EvC,EAAI,KAAA,GAGJ,KAAK,gBAAgBA,GAAKmD,GAAO3C,GAAGC,GAAG;AAAA,MACrC,UAAUjB,EAAe,KAAK;AAAA,MAC9B,YAAYA,EAAe,KAAK;AAAA,MAChC,OAAOA,EAAe,KAAK;AAAA,MAC3B,OAAO;AAAA,MACP,UAAU;AAAA,IAAA,GACTW,CAAQ,GAEXH,EAAI,QAAA;AAAA,EACN;AACF;ACnyBA,MAAM4D,IAAsC;AAAA,EACxC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU,CAAC,YAAY;AAAA,EACvB,MAAM,CAAC,cAAc,WAAW,OAAO;AAC3C;AAOO,SAASC,EAAkBC,IAAmC,IAA0C;AAC3G,MAAIC;AAEJ,SAAO;AAAA,IACH,UAAUH;AAAA,IAEV,OAAO5D,GAAoB;AACvB,MAAA+D,IAAoB,IAAItE,EAAA,GAKxBO,EAAI,QAAQ,IAAI,WAAW+D,CAAiB;AAAA,IAChD;AAAA,IAEA,gBAAgB/D,GAAK;AACjB,UAAIA,EAAI,MAAM,kBAAA,MAAwB,MAAO;AAE7C,YAAMC,IAAWD,EAAI,OAAO,UACtBgE,IAAahE,EAAI,KAAK,cAAA,GAGtBiE,IAAcjE,EAAI,UAAe,iBAAiB,GAClDG,IAAW8D,KAAA,gBAAAA,EAAa;AAG9B,MAAAF,EAAkB;AAAA,QACd/D,EAAI,OAAO;AAAA,QACXC;AAAA,QACA+D;AAAA,QACA7D;AAAA,MAAA;AAAA,IAER;AAAA,IAEA,UAAU+D,GAAqB;AAC3B,MAAAH,EAAkB,MAAA;AAAA,IACtB;AAAA,IAEA,KAAK;AAAA,MACD,aAAa;AACT,eAAOA;AAAA,MACX;AAAA,MACA,IAAIpE,GAAwB;AACxB,eAAOoE,EAAkB,IAAIpE,CAAU;AAAA,MAC3C;AAAA,MACA,OAAOC,GAAY;AACf,eAAOmE,EAAkB,OAAOnE,CAAE;AAAA,MACtC;AAAA,MACA,OAAOA,GAAYE,GAA8B;AAC7C,eAAOiE,EAAkB,OAAOnE,GAAIE,CAAO;AAAA,MAC/C;AAAA,MACA,IAAIF,GAAY;AACZ,eAAOmE,EAAkB,IAAInE,CAAE;AAAA,MACnC;AAAA,MACA,SAAS;AACL,eAAOmE,EAAkB,OAAA;AAAA,MAC7B;AAAA,MACA,QAAQ;AACJ,QAAAA,EAAkB,MAAA;AAAA,MACtB;AAAA,IAAA;AAAA,EACJ;AAER;"}