velo-plot 3.0.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 (191) hide show
  1. package/README.md +22 -15
  2. package/dist/ChartCore-KYG2HTcK.js +7474 -0
  3. package/dist/ChartCore-KYG2HTcK.js.map +1 -0
  4. package/dist/GpuChartRenderer-Dxc0hrQA.js +75 -0
  5. package/dist/GpuChartRenderer-Dxc0hrQA.js.map +1 -0
  6. package/dist/{index.core-BmZe2jRQ.js → PluginRegistry-CDf_jcnp.js} +19 -33
  7. package/dist/PluginRegistry-CDf_jcnp.js.map +1 -0
  8. package/dist/SVGDocumentBuilder-C-uLkcFW.js +83 -0
  9. package/dist/SVGDocumentBuilder-C-uLkcFW.js.map +1 -0
  10. package/dist/angular-hooks.js +1 -1
  11. package/dist/angular.js +8 -8
  12. package/dist/{axisFormat-CzumxpCL.js → axisFormat-Sz4WIJfQ.js} +2 -2
  13. package/dist/{axisFormat-CzumxpCL.js.map → axisFormat-Sz4WIJfQ.js.map} +1 -1
  14. package/dist/{chartSyncBridge-DbWrwtyP.js → chartSyncBridge-C1uRy0ZS.js} +12 -11
  15. package/dist/{chartSyncBridge-DbWrwtyP.js.map → chartSyncBridge-C1uRy0ZS.js.map} +1 -1
  16. package/dist/core/ChartStatistics.d.ts +1 -1
  17. package/dist/core/chart/ChartCore.d.ts +19 -20
  18. package/dist/core/chart/ChartFeatureHooks.d.ts +7 -0
  19. package/dist/core/chart/ChartRenderLoop.d.ts +5 -0
  20. package/dist/core/chart/ChartRenderer.d.ts +9 -0
  21. package/dist/core/chart/ChartSetup.d.ts +1 -0
  22. package/dist/core/chart/chartExportPatch.d.ts +2 -0
  23. package/dist/core/chart/exporter/SVGExporter.d.ts +9 -7
  24. package/dist/core/chart/exporter/svg/SVGDocumentBuilder.d.ts +27 -0
  25. package/dist/core/chart/exporter/svg/SVGExportContext.d.ts +147 -0
  26. package/dist/core/chart/exporter/svg/SVGOrchestrator.d.ts +3 -0
  27. package/dist/core/chart/exporter/svg/SVGThemeAdapter.d.ts +22 -0
  28. package/dist/core/chart/exporter/svg/__tests__/testFixtures.d.ts +46 -0
  29. package/dist/core/chart/exporter/svg/__tests__/visualTestUtils.d.ts +12 -0
  30. package/dist/core/chart/exporter/svg/overlay/axes.d.ts +4 -0
  31. package/dist/core/chart/exporter/svg/overlay/border.d.ts +4 -0
  32. package/dist/core/chart/exporter/svg/overlay/errorBars.d.ts +7 -0
  33. package/dist/core/chart/exporter/svg/overlay/grid.d.ts +4 -0
  34. package/dist/core/chart/exporter/svg/overlay/index.d.ts +12 -0
  35. package/dist/core/chart/exporter/svg/overlay/legend.d.ts +4 -0
  36. package/dist/core/chart/exporter/svg/overlay/pluginCharts.d.ts +6 -0
  37. package/dist/core/chart/exporter/svg/overlay/polarGrid.d.ts +4 -0
  38. package/dist/core/chart/exporter/svg/overlay/specialChart.d.ts +15 -0
  39. package/dist/core/chart/exporter/svg/overlay/title.d.ts +4 -0
  40. package/dist/core/chart/exporter/svg/plugins/annotations.d.ts +5 -0
  41. package/dist/core/chart/exporter/svg/plugins/brokenAxis.d.ts +20 -0
  42. package/dist/core/chart/exporter/svg/plugins/latex.d.ts +9 -0
  43. package/dist/core/chart/exporter/svg/plugins/register.d.ts +8 -0
  44. package/dist/core/chart/exporter/svg/plugins/regression.d.ts +33 -0
  45. package/dist/core/chart/exporter/svg/plugins/roi.d.ts +12 -0
  46. package/dist/core/chart/exporter/svg/plugins/tradeMarkers.d.ts +3 -0
  47. package/dist/core/chart/exporter/svg/plugins/types.d.ts +28 -0
  48. package/dist/core/chart/exporter/svg/plugins/watermark.d.ts +13 -0
  49. package/dist/core/chart/exporter/svg/series/band.d.ts +6 -0
  50. package/dist/core/chart/exporter/svg/series/bar.d.ts +6 -0
  51. package/dist/core/chart/exporter/svg/series/boxplot.d.ts +6 -0
  52. package/dist/core/chart/exporter/svg/series/candlestick.d.ts +6 -0
  53. package/dist/core/chart/exporter/svg/series/finitePoints.d.ts +6 -0
  54. package/dist/core/chart/exporter/svg/series/gauge.d.ts +5 -0
  55. package/dist/core/chart/exporter/svg/series/heatmap.d.ts +6 -0
  56. package/dist/core/chart/exporter/svg/series/indicator.d.ts +6 -0
  57. package/dist/core/chart/exporter/svg/series/line.d.ts +12 -0
  58. package/dist/core/chart/exporter/svg/series/polar.d.ts +6 -0
  59. package/dist/core/chart/exporter/svg/series/radar.d.ts +5 -0
  60. package/dist/core/chart/exporter/svg/series/registry.d.ts +10 -0
  61. package/dist/core/chart/exporter/svg/series/sankey.d.ts +5 -0
  62. package/dist/core/chart/exporter/svg/series/scatter.d.ts +1 -0
  63. package/dist/core/chart/exporter/svg/series/ternary.d.ts +7 -0
  64. package/dist/core/chart/exporter/svg/series/waterfall.d.ts +6 -0
  65. package/dist/core/chart/exporter/svg/seriesAtTimestamp.d.ts +4 -0
  66. package/dist/core/chart/exporter/svg/seriesUtils.d.ts +3 -0
  67. package/dist/core/chart/exporter/svg/symbols.d.ts +5 -0
  68. package/dist/core/chart/exporter/svg/tickUtils.d.ts +9 -0
  69. package/dist/core/chart/mountSVGString.d.ts +5 -0
  70. package/dist/core/chart/overlaySeriesRegistry.d.ts +7 -0
  71. package/dist/core/chart/series/SeriesActions.d.ts +1 -0
  72. package/dist/core/chart/series/SeriesBufferLite.d.ts +13 -0
  73. package/dist/core/chart/series/seriesOptionsRegistry.d.ts +8 -0
  74. package/dist/core/chart/series/seriesTypeRegistry.d.ts +5 -0
  75. package/dist/core/chart/types.d.ts +2 -2
  76. package/dist/core/stacked/StackSVGComposer.d.ts +14 -0
  77. package/dist/core/stacked/index.d.ts +3 -2
  78. package/dist/core/stacked/types.d.ts +12 -4
  79. package/dist/createStackedChart-DjA3aJAu.js +2761 -0
  80. package/dist/createStackedChart-DjA3aJAu.js.map +1 -0
  81. package/dist/{hooks-CYPCxoZx.js → hooks-4wQH27r9.js} +7 -7
  82. package/dist/{hooks-CYPCxoZx.js.map → hooks-4wQH27r9.js.map} +1 -1
  83. package/dist/{index-qunX30Xu.js → index-B7PTX94B.js} +2133 -2133
  84. package/dist/index-B7PTX94B.js.map +1 -0
  85. package/dist/{index-BMiZoKmm.js → index-BgrvqltV.js} +67 -67
  86. package/dist/index-BgrvqltV.js.map +1 -0
  87. package/dist/index-Bj-xyXY6.js +582 -0
  88. package/dist/index-Bj-xyXY6.js.map +1 -0
  89. package/dist/index-qhscKTDy.js.map +1 -1
  90. package/dist/index.core.d.ts +8 -6
  91. package/dist/index.d.ts +1 -14
  92. package/dist/plugins/3d.js +3 -1
  93. package/dist/plugins/3d.js.map +1 -1
  94. package/dist/plugins/PluginManager.d.ts +5 -0
  95. package/dist/plugins/analysis.js.map +1 -1
  96. package/dist/plugins/annotations.js +8 -7
  97. package/dist/plugins/annotations.js.map +1 -1
  98. package/dist/plugins/broken-axis.js +198 -152
  99. package/dist/plugins/broken-axis.js.map +1 -1
  100. package/dist/plugins/createPlugin.d.ts +8 -0
  101. package/dist/plugins/debug.js +32 -32
  102. package/dist/plugins/debug.js.map +1 -1
  103. package/dist/plugins/forecasting.js +273 -258
  104. package/dist/plugins/forecasting.js.map +1 -1
  105. package/dist/plugins/gpu.js +2033 -209
  106. package/dist/plugins/gpu.js.map +1 -1
  107. package/dist/plugins/i18n.js +286 -23
  108. package/dist/plugins/i18n.js.map +1 -1
  109. package/dist/plugins/latex.js +766 -207
  110. package/dist/plugins/latex.js.map +1 -1
  111. package/dist/plugins/loading/index.d.ts +1 -2
  112. package/dist/plugins/loading.js +3 -4
  113. package/dist/plugins/ml-integration.js +107 -93
  114. package/dist/plugins/ml-integration.js.map +1 -1
  115. package/dist/plugins/offscreen.js +11 -10
  116. package/dist/plugins/offscreen.js.map +1 -1
  117. package/dist/plugins/radar/types.d.ts +11 -0
  118. package/dist/plugins/radar.js +64 -53
  119. package/dist/plugins/radar.js.map +1 -1
  120. package/dist/plugins/regression.js +254 -256
  121. package/dist/plugins/regression.js.map +1 -1
  122. package/dist/plugins/roi/index.d.ts +2 -0
  123. package/dist/plugins/roi.js +184 -145
  124. package/dist/plugins/roi.js.map +1 -1
  125. package/dist/plugins/snapshot.js +20 -15
  126. package/dist/plugins/snapshot.js.map +1 -1
  127. package/dist/plugins/streaming.js +1 -1
  128. package/dist/plugins/tools.js +1 -1
  129. package/dist/plugins/types.d.ts +4 -0
  130. package/dist/react.js +55 -58
  131. package/dist/react.js.map +1 -1
  132. package/dist/regression-HNdyk1Dm.js +28 -0
  133. package/dist/regression-HNdyk1Dm.js.map +1 -0
  134. package/dist/renderer/ChartSeriesRenderer.d.ts +3 -2
  135. package/dist/renderer/NativeWebGLRenderer.d.ts +2 -1
  136. package/dist/renderer/SVGChartRenderer.d.ts +15 -0
  137. package/dist/renderer/SankeyRenderer.d.ts +1 -0
  138. package/dist/renderer/native/NativeWebGLRenderer.d.ts +5 -1
  139. package/dist/renderer/native/draw.d.ts +2 -47
  140. package/dist/renderer/native/drawCore.d.ts +27 -0
  141. package/dist/renderer/native/drawExtended.d.ts +29 -0
  142. package/dist/renderer/native/frameRenderExtended.d.ts +1 -0
  143. package/dist/renderer/native/frameRenderRegistry.d.ts +27 -0
  144. package/dist/renderer/native/programFactoryCore.d.ts +6 -0
  145. package/dist/renderer/native/programFactoryExtended.d.ts +4 -0
  146. package/dist/renderer/native/utils.d.ts +3 -29
  147. package/dist/renderer/native/utilsCore.d.ts +14 -0
  148. package/dist/renderer/native/utilsExtended.d.ts +17 -0
  149. package/dist/renderer/overlaySeriesExtended.d.ts +1 -0
  150. package/dist/renderer/registerExtendedSeries.d.ts +1 -0
  151. package/dist/renderer/registerSVG.d.ts +5 -0
  152. package/dist/renderer/registerWebGPU.d.ts +2 -0
  153. package/dist/renderer/sankeyLayout.d.ts +29 -0
  154. package/dist/renderer/seriesBufferExtended.d.ts +4 -0
  155. package/dist/scientific/index.d.ts +1 -5
  156. package/dist/scientific/registerScientific.d.ts +1 -0
  157. package/dist/scientific.js +41 -41
  158. package/dist/solid.js +56 -59
  159. package/dist/solid.js.map +1 -1
  160. package/dist/svelte.js +26 -29
  161. package/dist/svelte.js.map +1 -1
  162. package/dist/tickUtils-B_X-ha13.js +41 -0
  163. package/dist/tickUtils-B_X-ha13.js.map +1 -0
  164. package/dist/trading/index.d.ts +1 -4
  165. package/dist/trading/registerTrading.d.ts +3 -0
  166. package/dist/trading.js +42 -42
  167. package/dist/types.d.ts +5 -4
  168. package/dist/velo-plot.full.js +1951 -1275
  169. package/dist/velo-plot.full.js.map +1 -1
  170. package/dist/velo-plot.js +33 -28
  171. package/dist/velo-plot.js.map +1 -1
  172. package/dist/vue/VeloPlot.vue.d.ts +1 -1
  173. package/dist/vue/index.d.ts +33 -33
  174. package/dist/vue.js +17 -20
  175. package/dist/vue.js.map +1 -1
  176. package/package.json +14 -1
  177. package/dist/ChartCore-BpzRvN4Y.js +0 -8467
  178. package/dist/ChartCore-BpzRvN4Y.js.map +0 -1
  179. package/dist/createStackedChart-Dm-YqUT7.js +0 -756
  180. package/dist/createStackedChart-Dm-YqUT7.js.map +0 -1
  181. package/dist/gpuRenderer-BpaMYz-k.js +0 -1848
  182. package/dist/gpuRenderer-BpaMYz-k.js.map +0 -1
  183. package/dist/index-BMiZoKmm.js.map +0 -1
  184. package/dist/index-qunX30Xu.js.map +0 -1
  185. package/dist/index-x4stH3jD.js +0 -282
  186. package/dist/index-x4stH3jD.js.map +0 -1
  187. package/dist/index.core-BmZe2jRQ.js.map +0 -1
  188. package/dist/mockDatafeed-DHIDPcpX.js +0 -515
  189. package/dist/mockDatafeed-DHIDPcpX.js.map +0 -1
  190. package/dist/symbols-DT0eLlpW.js +0 -568
  191. package/dist/symbols-DT0eLlpW.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":";;AAWO,SAASA,GAAkBC,GAA8B;AAC9D,QAAMC,IAAID,EAAK,MAAM,QACfE,IAAS,IAAI,aAAaD,CAAC,GAC3BE,IAAS,IAAI,aAAaF,CAAC,GAC3BG,IAAQ,IAAI,aAAaH,CAAC,GAC1BI,IAAU,IAAI,aAAaJ,CAAC;AAElC,WAASK,IAAI,GAAGA,IAAIL,GAAGK,KAAK;AAC1B,UAAMC,IAAIP,EAAK,KAAKM,CAAC,GACfE,IAAIR,EAAK,KAAKM,CAAC,GACfG,IAAIT,EAAK,IAAIM,CAAC,GACdI,IAAIV,EAAK,MAAMM,CAAC;AAEtB,IAAAD,EAAQC,CAAC,KAAKC,IAAIC,IAAIC,IAAIC,KAAK,GAC/BR,EAAOI,CAAC,IAAIA,MAAM,KAAKC,IAAIG,KAAK,KAAKR,EAAOI,IAAI,CAAC,IAAID,EAAQC,IAAI,CAAC,KAAK,GACvEH,EAAOG,CAAC,IAAI,KAAK,IAAIE,GAAGN,EAAOI,CAAC,GAAGD,EAAQC,CAAC,CAAC,GAC7CF,EAAME,CAAC,IAAI,KAAK,IAAIG,GAAGP,EAAOI,CAAC,GAAGD,EAAQC,CAAC,CAAC;AAAA,EAC9C;AAEA,SAAO,EAAE,MAAMJ,GAAQ,MAAMC,GAAQ,KAAKC,GAAO,OAAOC,EAAA;AAC1D;ACeO,SAASM,GAAWC,GAOzB;AACA,QAAMX,IAAIW,EAAK,QACTC,IAAI,IAAI,aAAaZ,CAAC,GACtBa,IAAO,IAAI,aAAab,CAAC,GACzBc,IAAO,IAAI,aAAad,CAAC,GACzBe,IAAM,IAAI,aAAaf,CAAC,GACxBgB,IAAQ,IAAI,aAAahB,CAAC,GAC1BiB,IAAS,IAAI,aAAajB,CAAC;AACjC,WAASK,IAAI,GAAGA,IAAIL,GAAGK,KAAK;AAC1B,UAAMa,IAAIP,EAAKN,CAAC;AAChB,IAAAO,EAAEP,CAAC,IAAIa,EAAE,MACTL,EAAKR,CAAC,IAAIa,EAAE,MACZJ,EAAKT,CAAC,IAAIa,EAAE,MACZH,EAAIV,CAAC,IAAIa,EAAE,KACXF,EAAMX,CAAC,IAAIa,EAAE,OACbD,EAAOZ,CAAC,IAAIa,EAAE,UAAU;AAAA,EAC1B;AACA,SAAO,EAAE,GAAAN,GAAG,MAAAC,GAAM,MAAAC,GAAM,KAAAC,GAAK,OAAAC,GAAO,QAAAC,EAAA;AACtC;ACpDA,SAASE,EAAaC,GAA4B;AAChD,MAAIC,IAAID;AACR,SAAO,OACLC,IAAKA,IAAI,QAAS,aACVA,IAAI,KAAK;AAErB;AAEA,SAASC,GAAaC,GAAcC,GAAYC,GAAeC,GAAcC,GAA2B;AACtG,QAAMhB,IAAc,CAAA;AACpB,MAAIiB,IAAQF;AACZ,WAASG,IAAIN,GAAMM,KAAKL,GAAIK,KAAKJ,GAAO;AACtC,UAAMZ,IAAOe,GACPE,KAASH,EAAA,IAAS,QAAQ,GAC1BX,IAAQ,KAAK,IAAI,GAAGH,IAAOiB,CAAK,GAChChB,IAAO,KAAK,IAAID,GAAMG,CAAK,IAAIW,MAAS,KACxCZ,IAAM,KAAK,IAAIF,GAAMG,CAAK,IAAIW,MAAS;AAC7C,IAAAhB,EAAK,KAAK;AAAA,MACR,MAAMkB;AAAA,MACN,MAAAhB;AAAA,MACA,MAAAC;AAAA,MACA,KAAAC;AAAA,MACA,OAAAC;AAAA,MACA,QAAQ,MAAOW,MAAS;AAAA,IAAA,CACzB,GACDC,IAAQZ;AAAA,EACV;AACA,SAAOL;AACT;AAEO,SAASoB,GAAmBC,IAA+B,IAAqB;AACrF,QAAMP,IAAQO,EAAQ,SAAS,KACzBC,IAAYD,EAAQ,aAAa,KACjCL,IAAOR,EAAaa,EAAQ,QAAQ,EAAE,GACtCE,wBAAY,IAAA;AAElB,SAAO;AAAA,IACL,MAAM,cAAcC,GAAkC;AACpD,aAAO;AAAA,QACL,QAAQA;AAAA,QACR,MAAMA;AAAA,QACN,aAAa,eAAeA,CAAG;AAAA,QAC/B,UAAU;AAAA,QACV,SAAS;AAAA,QACT,YAAY;AAAA,MAAA;AAAA,IAEhB;AAAA,IAEA,MAAM,QAAQC,GAAyC;AACrD,YAAMC,IAAM,GAAGD,EAAQ,MAAM,IAAIA,EAAQ,IAAI,IAAIA,EAAQ,EAAE;AAC3D,aAAKF,EAAM,IAAIG,CAAG,KAChBH,EAAM;AAAA,QACJG;AAAA,QACAf,GAAac,EAAQ,MAAMA,EAAQ,IAAIX,GAAOQ,GAAWN,CAAI;AAAA,MAAA,GAG1DO,EAAM,IAAIG,CAAG;AAAA,IACtB;AAAA,IAEA,cAAcD,GAA2C;AACvD,UAAIE,IAAOL,IAAYN,EAAA,IAAS;AAChC,YAAMY,IAAQ,YAAY,MAAM;AAC9B,cAAM1B,IAAOyB,GACPtB,IAAQ,KAAK,IAAI,GAAGH,KAAQc,EAAA,IAAS,OAAO,CAAC,GAC7Cb,IAAO,KAAK,IAAID,GAAMG,CAAK,IAAIW,EAAA,GAC/BZ,IAAM,KAAK,IAAIF,GAAMG,CAAK,IAAIW,EAAA;AACpC,QAAAS,EAAQ,MAAM;AAAA,UACZ,MAAM,KAAK,IAAA;AAAA,UACX,MAAAvB;AAAA,UACA,MAAAC;AAAA,UACA,KAAAC;AAAA,UACA,OAAAC;AAAA,UACA,QAAQ,MAAOW,MAAS;AAAA,QAAA,CACzB,GACDW,IAAOtB;AAAA,MACT,GAAGS,CAAK;AACR,aAAO,MAAM,cAAcc,CAAK;AAAA,IAClC;AAAA,EAAA;AAEJ;AChFO,SAASC,GACdC,GACA7B,GACQ;AACR,MAAI6B,EAAK,WAAW,EAAG,QAAO;AAC9B,MAAIC,IAAU,GACVC,IAAW,KAAK,IAAIF,EAAK,CAAC,IAAI7B,CAAC;AACnC,WAASP,IAAI,GAAGA,IAAIoC,EAAK,QAAQpC,KAAK;AACpC,UAAMuC,IAAI,KAAK,IAAIH,EAAKpC,CAAC,IAAIO,CAAC;AAC9B,IAAIgC,IAAID,MACNA,IAAWC,GACXF,IAAUrC;AAAA,EAEd;AACA,SAAOqC;AACT;AAEO,SAASG,GAAaC,GAAkD;AAC7E,MAA+BA,EAAM,KAAK,WAAW;AACnD,WAAO,EAAE,GAAGA,EAAM,GAAG,GAAGA,EAAM,EAAA;AAGhC,QAAMC,IAAMP,GAAoBM,EAAM,MAAMA,EAAM,CAAC;AACnD,MAAIC,IAAM,EAAG,QAAO,EAAE,GAAGD,EAAM,GAAG,GAAGA,EAAM,EAAA;AAE3C,QAAML,IAAOK,EAAM,KAAKC,CAAG,GACrBC,IAAa;AAAA,IACjBF,EAAM,KAAKC,CAAG;AAAA,IACdD,EAAM,KAAKC,CAAG;AAAA,IACdD,EAAM,IAAIC,CAAG;AAAA,IACbD,EAAM,MAAMC,CAAG;AAAA,EAAA,GAGXE,IAAUH,EAAM,aAAaA,EAAM,CAAC,GACpCI,IAAYJ,EAAM,kBAAkB;AAC1C,MAAIK,IAAQL,EAAM,GACdM,IAAa;AAEjB,aAAWC,KAAML,GAAY;AAC3B,UAAMM,IAAKR,EAAM,aAAaO,CAAE,GAC1BE,IAAO,KAAK,IAAID,IAAKL,CAAO;AAClC,IAAIM,IAAOH,KAAcG,KAAQL,MAC/BE,IAAaG,GACbJ,IAAQE;AAAA,EAEZ;AAEA,SAAO,EAAE,GAAGZ,GAAM,GAAGU,EAAA;AACvB;AC9CO,SAASK,EAAmBC,GAAiBvC,GAA8B;AAChF,QAAMwC,IAASxC,EAAE,IAAIuC,EAAE,GACjBE,IAAQ,KAAK,IAAIF,EAAE,CAAC,GACpBG,IAAUD,IAAQ,IAAKD,IAASC,IAAS,MAAM,GAC/ChD,IAAO,KAAK,MAAM,KAAK,IAAIO,EAAE,IAAIuC,EAAE,CAAC,CAAC;AAC3C,SAAO,EAAE,QAAAC,GAAQ,SAAAE,GAAS,MAAAjD,GAAM,IAAI+C,KAAU,EAAA;AAChD;AAEO,SAASG,EAAkBC,GAAwB;AACxD,QAAMC,IAAOD,EAAE,UAAU,IAAI,MAAM;AACnC,SAAO,GAAGC,CAAI,GAAGD,EAAE,OAAO,QAAQ,CAAC,CAAC,KAAKC,CAAI,GAAGD,EAAE,QAAQ,QAAQ,CAAC,CAAC,QAAQA,EAAE,IAAI;AACpF;AAGO,SAASE,EAAYC,GAAuB;AACjD,QAAMC,IAAM,KAAK,IAAID,CAAK,GACpBE,IAAWD,KAAO,MAAO,IAAIA,KAAO,IAAI,IAAI;AAClD,SAAOD,EAAM,eAAe,SAAS;AAAA,IACnC,uBAAuBE;AAAA,IACvB,uBAAuBA;AAAA,EAAA,CACxB;AACH;ACjBA,MAAMC,IAAa,CAAC,GAAG,OAAO,OAAO,KAAK,OAAO,OAAO,CAAC,GACnDC,KAAoB,GACpBC,KAAqB,WACrBC,KAAuB;AAiB7B,SAASC,EAAUC,GAAeC,GAAuB;AACvD,SAAOD,EAAM,WAAW,GAAG,KAAKA,EAAM,WAAW,IAAIA,IAAQC,IAAQD;AACvE;AAYA,MAAME,KAA2B;AAAA,EAC/B,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU,CAAC,SAAS;AAAA,EACpB,MAAM,CAAC,WAAW,eAAe,SAAS;AAC5C;AAoBA,SAASC,EAAcC,GAA4B;AACjD,SAAOA,MAAS,UAAUA,MAAS;AACrC;AAEA,SAASC,GAAsBC,GAAwC;AACrE,aAAW1D,KAAK0D,EAAI,KAAK,aAAA;AACvB,QAAI1D,EAAE,cAAc,cAAe,QAAOA;AAG9C;AAEO,SAAS2D,GACdC,IAAmC,IACI;AACvC,MAAIF,IAA4B;AAChC,QAAMG,IAAeD,EAAO,iBAAiB,IACvCE,IAAmB;AAAA,IACvB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,IACP,UAAU;AAAA,IACV,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,QAAQ;AAAA,IACR,QAAQF,EAAO,UAAU;AAAA,IACzB,WAAW,CAAA;AAAA,IACX,WAAW,CAAA;AAAA,EAAC,GAGRG,IAASH,EAAO,SAAS,WACzBI,IAAYJ,EAAO,kBAAkBX,IACrCgB,IAAcL,EAAO,oBAAoBV;AAE/C,WAASgB,IAAyB;;AAChC,aAAOC,IAAAT,KAAA,iBAAAU,IAAAV,EAAK,OAAM,mBAAX,gBAAAS,EAAA,KAAAC,OAAiC,CAAA;AAAA,EAC1C;AAEA,WAASC,IAAiB;AACxB,IAAAP,EAAM,UAAU,KAAKI,GAAU,GAC/BJ,EAAM,YAAY,CAAA;AAAA,EACpB;AAEA,WAASQ,IAA8B;AACrC,IAAAR,EAAM,UAAU,MAChBA,EAAM,QAAQ,MACdA,EAAM,WAAW,IACjBA,EAAM,YAAY,IAClBA,EAAM,iBAAiB;AAAA,EACzB;AAEA,WAASS,EAAgBf,GAAyB;;AAChD,IAAAM,EAAM,OAAON,GACbc,EAAA,IACAF,IAAAR,EAAO,iBAAP,QAAAQ,EAAA,KAAAR,GAAsBJ,KACtBW,IAAAT,KAAA,gBAAAA,EAAK,kBAAL,QAAAS,EAAA,KAAAT;AAAA,EACF;AAEA,WAASc,IAAqB;;AAC5B,IAAAF,EAAA,GACIT,IACFU,EAAgB,MAAM,KAEtBH,IAAAV,KAAA,gBAAAA,EAAK,kBAAL,QAAAU,EAAA,KAAAV;AAAA,EAEJ;AAEA,WAASe,EAAalF,GAAWmF,GAAsB;AACrD,QAAI,CAAChB,KAAO,CAACI,EAAM,OAAQ,QAAO,EAAE,GAAAvE,GAAG,GAAAmF,EAAA;AACvC,UAAMC,IAASlB,GAAsBC,CAAG;AACxC,QAAI,CAACiB,EAAQ,QAAO,EAAE,GAAApF,GAAG,GAAAmF,EAAA;AACzB,UAAMnD,IAAIoD,EAAO,QAAA;AACjB,WAAI,CAACpD,EAAE,QAAQ,CAACA,EAAE,QAAQ,CAACA,EAAE,OAAO,CAACA,EAAE,QAAc,EAAE,GAAAhC,GAAG,GAAAmF,EAAA,IACnDlD,GAAa;AAAA,MAClB,GAAAjC;AAAA,MACA,GAAAmF;AAAA,MACA,MAAMnD,EAAE;AAAA,MACR,MAAMA,EAAE;AAAA,MACR,MAAMA,EAAE;AAAA,MACR,KAAKA,EAAE;AAAA,MACP,OAAOA,EAAE;AAAA,MACT,cAAcmC,EAAI,OAAO;AAAA,MACzB,cAAc,CAACkB,MAAOlB,EAAK,OAAO,aAAakB,CAAE;AAAA,MACjD,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAEA,WAASC,EAAeC,GAA0BC,GAAoC;AACpF,WAAON;AAAA,MACLK,EAAU,OAAO,aAAaC,EAAM,MAAM;AAAA,MAC1CD,EAAU,OAAO,aAAaC,EAAM,MAAM;AAAA,IAAA;AAAA,EAE9C;AAEA,WAASC,EAAiBN,GAAiB;AACzC,IAAKhB,MACLW,EAAA,GACAX,EAAI,MAAM,cAAc;AAAA,MACtB,MAAM;AAAA,MACN,GAAAgB;AAAA,MACA,OAAOX;AAAA,MACP,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,WAASkB,EAAe1F,GAAiB;AACvC,IAAKmE,MACLW,EAAA,GACAX,EAAI,MAAM,cAAc;AAAA,MACtB,MAAM;AAAA,MACN,GAAAnE;AAAA,MACA,OAAOwE;AAAA,MACP,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,WAASmB,EAAcC,GAAeC,GAAqB;AACzD,QAAI,CAAC1B,EAAK;AACV,IAAAW,EAAA;AAEA,UAAM5B,IAAIN,EAAmBgD,GAAIC,CAAE,GAC7BhC,IAAQX,EAAE,KAAKuB,IAAYC,GAC3BoB,KAAQF,EAAG,IAAIC,EAAG,KAAK;AAC7B,IAAA1B,EAAI,MAAM,cAAc;AAAA,MACtB,MAAM;AAAA,MACN,MAAM,KAAK,IAAIyB,EAAG,GAAGC,EAAG,CAAC;AAAA,MACzB,MAAM,KAAK,IAAID,EAAG,GAAGC,EAAG,CAAC;AAAA,MACzB,MAAM,KAAK,IAAID,EAAG,GAAGC,EAAG,CAAC;AAAA,MACzB,MAAM,KAAK,IAAID,EAAG,GAAGC,EAAG,CAAC;AAAA,MACzB,aAAahC;AAAA,MACb,WAAWD,EAAUC,GAAO,IAAI;AAAA,MAChC,aAAa;AAAA,IAAA,CACd,GACDM,EAAI,MAAM,cAAc;AAAA,MACtB,MAAM;AAAA,MACN,IAAI2B;AAAA,MACJ,IAAIF,EAAG;AAAA,MACP,IAAIE;AAAA,MACJ,IAAID,EAAG;AAAA,MACP,OAAAhC;AAAA,MACA,WAAW;AAAA,MACX,aAAa;AAAA,IAAA,CACd,GACDM,EAAI,MAAM,cAAc;AAAA,MACtB,MAAM;AAAA,MACN,GAAG2B;AAAA,MACH,GAAGD,EAAG;AAAA,MACN,MAAM5C,EAAkBC,CAAC;AAAA,MACzB,OAAO;AAAA,MACP,iBAAiBW;AAAA,MACjB,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,QAAQX,EAAE,KAAK,kBAAkB;AAAA,MACjC,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,WAAS6C,EAAeH,GAAeC,GAAqB;AAC1D,QAAK1B,GAEL;AAAA,UAAII,EAAM,SAAS,WAAW;AAC5B,QAAAoB,EAAcC,GAAIC,CAAE;AACpB;AAAA,MACF;AAIA,UAFAf,EAAA,GAEIP,EAAM,SAAS;AACjB,QAAAJ,EAAI,MAAM,cAAc;AAAA,UACtB,MAAM;AAAA,UACN,IAAIyB,EAAG;AAAA,UACP,IAAIA,EAAG;AAAA,UACP,IAAIC,EAAG;AAAA,UACP,IAAIA,EAAG;AAAA,UACP,OAAOrB;AAAA,UACP,aAAa;AAAA,QAAA,CACd;AAAA,eACQD,EAAM,SAAS;AACxB,QAAAJ,EAAI,MAAM,cAAc;AAAA,UACtB,MAAM;AAAA,UACN,MAAM,KAAK,IAAIyB,EAAG,GAAGC,EAAG,CAAC;AAAA,UACzB,MAAM,KAAK,IAAID,EAAG,GAAGC,EAAG,CAAC;AAAA,UACzB,MAAM,KAAK,IAAID,EAAG,GAAGC,EAAG,CAAC;AAAA,UACzB,MAAM,KAAK,IAAID,EAAG,GAAGC,EAAG,CAAC;AAAA,UACzB,aAAarB;AAAA,UACb,WAAWA,IAAS;AAAA,UACpB,aAAa;AAAA,QAAA,CACd;AAAA,eACQD,EAAM,SAAS,aAAa;AACrC,cAAMyB,IAAO,KAAK,IAAIJ,EAAG,GAAGC,EAAG,CAAC,GAC1BI,IAAO,KAAK,IAAIL,EAAG,GAAGC,EAAG,CAAC;AAChC,mBAAWK,KAAS1C,GAAY;AAC9B,gBAAM2C,IAAKF,KAAQA,IAAOD,KAAQE;AAClC,UAAA/B,EAAI,MAAM,cAAc;AAAA,YACtB,MAAM;AAAA,YACN,GAAGgC;AAAA,YACH,OAAO3B;AAAA,YACP,UAAU0B,MAAU,KAAKA,MAAU,IAAI,SAAY,CAAC,GAAG,CAAC;AAAA,YACxD,OAAO,IAAIA,IAAQ,KAAK,QAAQ,CAAC,CAAC,MAAM9C,EAAY+C,CAAE,CAAC;AAAA,YACvD,eAAe;AAAA,YACf,aAAa;AAAA,UAAA,CACd;AAAA,QACH;AAAA,MACF;AAAA;AAAA,EACF;AAEA,WAASC,EACPC,GACAC,GACAC,GACM;AACN,UAAMtC,IAAOM,EAAM;AACnB,QAAI,CAACP,EAAcC,CAAI,KAAK,CAACM,EAAM,OAAQ;AAE3C,UAAMiC,IAASjC,EAAM,QACfkC,IAASlC,EAAM,WAAWA,EAAM;AAEtC,IAAA8B,EAAI,KAAA,GACJA,EAAI,cAAc7B,GAClB6B,EAAI,YAAY,KAChBA,EAAI,YAAY,CAAC,GAAG,CAAC,CAAC,GACtBA,EAAI,cAAc;AAElB,UAAMK,IAAO,CAAC1G,GAAWmF,OAAe;AAAA,MACtC,IAAIoB,EAAO,aAAavG,CAAC;AAAA,MACzB,IAAIuG,EAAO,aAAapB,CAAC;AAAA,IAAA;AAG3B,QAAIlB,MAAS,cAAc;AACzB,YAAM,EAAE,IAAAvB,EAAA,IAAOgE,EAAK,GAAGF,EAAO,CAAC;AAC/B,MAAAH,EAAI,UAAA,GACJA,EAAI,OAAOC,EAAS,GAAG5D,CAAE,GACzB2D,EAAI,OAAOC,EAAS,IAAIA,EAAS,OAAO5D,CAAE,GAC1C2D,EAAI,OAAA;AAAA,IACN,WAAWpC,MAAS,YAAY;AAC9B,YAAM,EAAE,IAAA0C,EAAA,IAAOD,EAAKF,EAAO,GAAG,CAAC;AAC/B,MAAAH,EAAI,UAAA,GACJA,EAAI,OAAOM,GAAIL,EAAS,CAAC,GACzBD,EAAI,OAAOM,GAAIL,EAAS,IAAIA,EAAS,MAAM,GAC3CD,EAAI,OAAA;AAAA,IACN,WAAWI,GAAQ;AACjB,YAAM5D,IAAI6D,EAAKD,EAAO,GAAGA,EAAO,CAAC,GAC3BnG,IAAIoG,EAAKF,EAAO,GAAGA,EAAO,CAAC;AAEjC,UAAIvC,MAAS;AACX,QAAAoC,EAAI,UAAA,GACJA,EAAI,OAAOxD,EAAE,IAAIA,EAAE,EAAE,GACrBwD,EAAI,OAAO/F,EAAE,IAAIA,EAAE,EAAE,GACrB+F,EAAI,OAAA;AAAA,eACKpC,MAAS,aAAa;AAC/B,cAAMjE,IAAI,KAAK,IAAI6C,EAAE,IAAIvC,EAAE,EAAE,GACvB6E,IAAI,KAAK,IAAItC,EAAE,IAAIvC,EAAE,EAAE,GACvBsG,IAAI,KAAK,IAAItG,EAAE,KAAKuC,EAAE,EAAE,GACxBlD,IAAI,KAAK,IAAIW,EAAE,KAAKuC,EAAE,EAAE;AAC9B,QAAAwD,EAAI,WAAWrG,GAAGmF,GAAGyB,GAAGjH,CAAC,GACzB0G,EAAI,YAAY7B,IAAS,MACzB6B,EAAI,SAASrG,GAAGmF,GAAGyB,GAAGjH,CAAC;AAAA,MACzB,WAAWsE,MAAS,aAAa;AAC/B,cAAM+B,IAAO,KAAK,IAAIS,EAAO,GAAGD,EAAO,CAAC,GAClCP,IAAO,KAAK,IAAIQ,EAAO,GAAGD,EAAO,CAAC;AACxC,QAAAH,EAAI,OAAO,mBACXA,EAAI,YAAY,QAChBA,EAAI,eAAe;AACnB,mBAAWH,KAAS1C,GAAY;AAC9B,gBAAM2C,IAAKF,KAAQA,IAAOD,KAAQE,GAC5B,EAAE,IAAAxD,EAAA,IAAOgE,EAAK,GAAGP,CAAE;AACzB,UAAAE,EAAI,UAAA,GACJA,EAAI,OAAOC,EAAS,GAAG5D,CAAE,GACzB2D,EAAI,OAAOC,EAAS,IAAIA,EAAS,OAAO5D,CAAE,GAC1C2D,EAAI,OAAA,GACJA,EAAI,KAAA,GACJA,EAAI,YAAY,EAAE,GAClBA,EAAI,cAAc,GAClBA,EAAI,YAAY7B,GAChB6B,EAAI;AAAA,YACF,IAAIH,IAAQ,KAAK,QAAQ,CAAC,CAAC,MAAM9C,EAAY+C,CAAE,CAAC;AAAA,YAChDG,EAAS,IAAI;AAAA,YACb5D,IAAK;AAAA,UAAA,GAEP2D,EAAI,QAAA;AAAA,QACN;AAAA,MACF,MAAA,CAAWpC,MAAS,aAClB4C,EAAmBR,GAAKxD,GAAGvC,GAAGmG,GAAQD,CAAM;AAAA,IAEhD;AAEA,IAAAH,EAAI,QAAA;AAAA,EACN;AAEA,WAASQ,EACPR,GACAxD,GACAvC,GACAmG,GACAD,GACM;AACN,UAAMtD,IAAIN,EAAmB6D,GAAQD,CAAM,GACrC3C,IAAQX,EAAE,KAAKuB,IAAYC,GAC3B1E,IAAI,KAAK,IAAI6C,EAAE,IAAIvC,EAAE,EAAE,GACvB6E,IAAI,KAAK,IAAItC,EAAE,IAAIvC,EAAE,EAAE,GACvBsG,IAAI,KAAK,IAAItG,EAAE,KAAKuC,EAAE,EAAE,GACxBlD,IAAI,KAAK,IAAIW,EAAE,KAAKuC,EAAE,EAAE;AAE9B,IAAAwD,EAAI,YAAY,EAAE,GAClBA,EAAI,cAAc,KAClBA,EAAI,YAAYzC,EAAUC,GAAO,IAAI,GACrCwC,EAAI,SAASrG,GAAGmF,GAAGyB,GAAGjH,CAAC,GACvB0G,EAAI,cAAcxC,GAClBwC,EAAI,YAAY,KAChBA,EAAI,WAAWrG,GAAGmF,GAAGyB,GAAGjH,CAAC;AAGzB,UAAMmG,KAAQjD,EAAE,KAAKvC,EAAE,MAAM;AAC7B,IAAA+F,EAAI,UAAA,GACJA,EAAI,OAAOP,GAAMjD,EAAE,EAAE,GACrBwD,EAAI,OAAOP,GAAMxF,EAAE,EAAE,GACrB+F,EAAI,OAAA;AACJ,UAAMS,IAAU,GACVC,IAAMzG,EAAE,MAAMuC,EAAE,KAAK,IAAI;AAC/B,IAAAwD,EAAI,UAAA,GACJA,EAAI,OAAOP,GAAMxF,EAAE,EAAE,GACrB+F,EAAI,OAAOP,IAAO,GAAGxF,EAAE,KAAKyG,IAAMD,CAAO,GACzCT,EAAI,OAAOP,IAAO,GAAGxF,EAAE,KAAKyG,IAAMD,CAAO,GACzCT,EAAI,UAAA,GACJA,EAAI,YAAYxC,GAChBwC,EAAI,KAAA;AAGJ,UAAMW,IAAQ/D,EAAkBC,CAAC;AACjC,IAAAmD,EAAI,OAAO;AAGX,UAAMY,IAFQZ,EAAI,YAAYW,CAAK,EAAE,QACxB,IACe,GACtBE,IAAO,IACPC,IAAOrB,IAAOmB,IAAO,GACrBG,IAAOlE,EAAE,KAAK5C,EAAE,KAAK4G,IAAO,IAAI5G,EAAE,KAAK;AAC7C,IAAA+F,EAAI,cAAc,GAClBA,EAAI,YAAYxC,GAChBwC,EAAI,SAASc,GAAMC,GAAMH,GAAMC,CAAI,GACnCb,EAAI,YAAY,WAChBA,EAAI,YAAY,UAChBA,EAAI,eAAe,UACnBA,EAAI,SAASW,GAAOlB,GAAMsB,IAAOF,IAAO,CAAC;AAAA,EAC3C;AAOA,WAASG,EAAaC,GAA0C;AAC9D,UAAMrD,IAAOM,EAAM;AACnB,QAAI,CAACP,EAAcC,CAAI,KAAK,CAACM,EAAM,eAAe,CAAA;AAElD,UAAMgD,IACJC,EAAcF,EAAO,OAAO,KAAK,CAAC,GAAGA,EAAO,QAAQ,OAAA,CAAQ,EAAE,CAAC;AACjE,QAAI,CAACC,EAAQ,QAAO,CAAA;AAEpB,UAAMjB,IAAWgB,EAAO,UAClBd,IAASjC,EAAM,QACfkC,IAASlC,EAAM,WAAWA,EAAM,OAChCmC,IAAO,CAAC1G,GAAWmF,OAAe;AAAA,MACtC,IAAImC,EAAO,OAAO,UAAUtH,CAAC;AAAA,MAC7B,IAAIuH,EAAO,UAAUpC,CAAC;AAAA,IAAA,IAElBsC,IAAO,0BACPC,IAAgB,CAAA;AAEtB,QAAIzD,MAAS,cAAc;AACzB,YAAM,EAAE,IAAAvB,EAAA,IAAOgE,EAAK,GAAGF,EAAO,CAAC;AAC/B,MAAAkB,EAAI;AAAA,QACF,aAAaC,EAAIrB,EAAS,CAAC,CAAC,SAASqB,EAAIjF,CAAE,CAAC,SAASiF,EAAIrB,EAAS,IAAIA,EAAS,KAAK,CAAC,SAASqB,EAAIjF,CAAE,CAAC,aAAa8B,CAAM,wBAAwBiD,CAAI;AAAA,MAAA;AAAA,IAExJ,WAAWxD,MAAS,YAAY;AAC9B,YAAM,EAAE,IAAA0C,EAAA,IAAOD,EAAKF,EAAO,GAAG,CAAC;AAC/B,MAAAkB,EAAI;AAAA,QACF,aAAaC,EAAIhB,CAAE,CAAC,SAASgB,EAAIrB,EAAS,CAAC,CAAC,SAASqB,EAAIhB,CAAE,CAAC,SAASgB,EAAIrB,EAAS,IAAIA,EAAS,MAAM,CAAC,aAAa9B,CAAM,wBAAwBiD,CAAI;AAAA,MAAA;AAAA,IAEzJ,WAAWhB,GAAQ;AACjB,YAAM5D,IAAI6D,EAAKD,EAAO,GAAGA,EAAO,CAAC,GAC3BnG,IAAIoG,EAAKF,EAAO,GAAGA,EAAO,CAAC;AAEjC,UAAIvC,MAAS;AACX,QAAAyD,EAAI;AAAA,UACF,aAAaC,EAAI9E,EAAE,EAAE,CAAC,SAAS8E,EAAI9E,EAAE,EAAE,CAAC,SAAS8E,EAAIrH,EAAE,EAAE,CAAC,SAASqH,EAAIrH,EAAE,EAAE,CAAC,aAAakE,CAAM,wBAAwBiD,CAAI;AAAA,QAAA;AAAA,eAEpHxD,MAAS,aAAa;AAC/B,cAAMjE,IAAI,KAAK,IAAI6C,EAAE,IAAIvC,EAAE,EAAE,GACvB6E,IAAI,KAAK,IAAItC,EAAE,IAAIvC,EAAE,EAAE,GACvBsG,IAAI,KAAK,IAAItG,EAAE,KAAKuC,EAAE,EAAE,GACxBlD,IAAI,KAAK,IAAIW,EAAE,KAAKuC,EAAE,EAAE;AAC9B,QAAA6E,EAAI;AAAA,UACF,YAAYC,EAAI3H,CAAC,CAAC,QAAQ2H,EAAIxC,CAAC,CAAC,YAAYwC,EAAIf,CAAC,CAAC,aAAae,EAAIhI,CAAC,CAAC,WAAW6E,CAAM,eAAeA,CAAM,wBAAwBiD,CAAI;AAAA,QAAA;AAAA,MAE3I,WAAWxD,MAAS,aAAa;AAC/B,cAAM+B,IAAO,KAAK,IAAIS,EAAO,GAAGD,EAAO,CAAC,GAClCP,IAAO,KAAK,IAAIQ,EAAO,GAAGD,EAAO,CAAC;AACxC,mBAAWN,KAAS1C,GAAY;AAC9B,gBAAM2C,IAAKF,KAAQA,IAAOD,KAAQE,GAC5B,EAAE,IAAAxD,EAAA,IAAOgE,EAAK,GAAGP,CAAE;AACzB,UAAAuB,EAAI;AAAA,YACF,aAAaC,EAAIrB,EAAS,CAAC,CAAC,SAASqB,EAAIjF,CAAE,CAAC,SAASiF,EAAIrB,EAAS,IAAIA,EAAS,KAAK,CAAC,SAASqB,EAAIjF,CAAE,CAAC,aAAa8B,CAAM,wBAAwBiD,CAAI;AAAA,UAAA,GAEtJC,EAAI;AAAA,YACF,YAAYC,EAAIrB,EAAS,IAAI,CAAC,CAAC,QAAQqB,EAAIjF,IAAK,CAAC,CAAC,WAAW8B,CAAM,8CAA8C0B,IAAQ,KAAK,QAAQ,CAAC,CAAC,MAAM9C,EAAY+C,CAAE,CAAC;AAAA,UAAA;AAAA,QAEjK;AAAA,MACF,WAAWlC,MAAS,WAAW;AAC7B,cAAMf,IAAIN,EAAmB6D,GAAQD,CAAM,GACrC3C,IAAQX,EAAE,KAAKuB,IAAYC,GAC3B1E,IAAI,KAAK,IAAI6C,EAAE,IAAIvC,EAAE,EAAE,GACvB6E,IAAI,KAAK,IAAItC,EAAE,IAAIvC,EAAE,EAAE,GACvBsG,IAAI,KAAK,IAAItG,EAAE,KAAKuC,EAAE,EAAE,GACxBlD,IAAI,KAAK,IAAIW,EAAE,KAAKuC,EAAE,EAAE,GACxBiD,KAAQjD,EAAE,KAAKvC,EAAE,MAAM;AAC7B,QAAAoH,EAAI;AAAA,UACF,YAAYC,EAAI3H,CAAC,CAAC,QAAQ2H,EAAIxC,CAAC,CAAC,YAAYwC,EAAIf,CAAC,CAAC,aAAae,EAAIhI,CAAC,CAAC,WAAWiE,EAAUC,GAAO,IAAI,CAAC,aAAaA,CAAK;AAAA,QAAA,GAE1H6D,EAAI;AAAA,UACF,aAAaC,EAAI7B,CAAI,CAAC,SAAS6B,EAAI9E,EAAE,EAAE,CAAC,SAAS8E,EAAI7B,CAAI,CAAC,SAAS6B,EAAIrH,EAAE,EAAE,CAAC,aAAauD,CAAK;AAAA,QAAA,GAEhG6D,EAAI;AAAA,UACF,YAAYC,EAAI7B,CAAI,CAAC,QAAQ6B,EAAIzE,EAAE,KAAK5C,EAAE,KAAK,KAAKA,EAAE,KAAK,EAAE,CAAC,WAAWuD,CAAK,kEAAkEZ,EAAkBC,CAAC,CAAC;AAAA,QAAA;AAAA,MAExK;AAAA,IACF;AAEA,WAAOwE;AAAA,EACT;AAEA,WAASE,EAAgBrC,GAA0BC,GAA+B;;AAChF,QAAI,CAACA,EAAM,WAAY;AAEvB,IAAAA,EAAM,eAAA;AACN,UAAMqC,IAAQvC,EAAeC,GAAWC,CAAK;AAE7C,QAAIjB,EAAM,SAAS,cAAc;AAC/B,MAAAkB,EAAiBoC,EAAM,CAAC,GACxB5C,EAAA;AACA;AAAA,IACF;AAEA,QAAIV,EAAM,SAAS,YAAY;AAC7B,MAAAmB,EAAemC,EAAM,CAAC,GACtB5C,EAAA;AACA;AAAA,IACF;AAEA,QAAIV,EAAM,SAAS;AACjB,MAAAwB,EAAexB,EAAM,SAASsD,CAAK,GACnC5C,EAAA;AACA;AAAA,IACF;AAEA,IAAAV,EAAM,QAAQsD,GACdtD,EAAM,WAAW,IACjBA,EAAM,YAAY,IAClBA,EAAM,iBAAiB,EAAE,GAAGiB,EAAM,QAAQ,GAAGA,EAAM,OAAA,GACnDjB,EAAM,SAASsD,IACfhD,IAAAU,EAAU,kBAAV,QAAAV,EAAA,KAAAU;AAAA,EACF;AAEA,WAASuC,EAAgBvC,GAA0BC,GAA+B;;AAChF,UAAMqC,IAAQvC,EAAeC,GAAWC,CAAK;AAG7C,QAFAjB,EAAM,SAASsD,GAEXtD,EAAM,YAAYA,EAAM,gBAAgB;AAC1C,YAAMwD,IAAKvC,EAAM,SAASjB,EAAM,eAAe,GACzCc,IAAKG,EAAM,SAASjB,EAAM,eAAe;AAC/C,MAAI,KAAK,MAAMwD,GAAI1C,CAAE,KAAK5B,OACxBc,EAAM,YAAY;AAAA,IAEtB;AAEA,IAAAiB,EAAM,eAAA,IACNX,IAAAU,EAAU,kBAAV,QAAAV,EAAA,KAAAU;AAAA,EACF;AAEA,WAASyC,EAAczC,GAA0BC,GAA+B;;AAC9E,QAAI,CAACjB,EAAM,YAAY,CAACA,EAAM,MAAO;AAErC,UAAMsD,IAAQvC,EAAeC,GAAWC,CAAK,GACvCyC,IAAQ1D,EAAM;AAIpB,QAHAA,EAAM,WAAW,IACjBA,EAAM,iBAAiB,MAEnBA,EAAM,WAAW;AACnB,MAAAwB,EAAekC,GAAOJ,CAAK,GAC3B5C,EAAA;AACA;AAAA,IACF;AAEA,IAAAV,EAAM,UAAU0D,GAChB1D,EAAM,QAAQ,MACdA,EAAM,SAASsD,IACfhD,IAAAU,EAAU,kBAAV,QAAAV,EAAA,KAAAU;AAAA,EACF;AAwCA,SAAO;AAAA,IAAA,UACLxB;AAAAA,IACA,KAxCqD;AAAA,MACrD,QAAQE,GAAM;AACZ,QAAAe,EAAgBf,CAAI;AAAA,MACtB;AAAA,MACA,UAAU;AACR,eAAOM,EAAM;AAAA,MACf;AAAA,MACA,UAAU2D,GAAS;AACjB,QAAA3D,EAAM,SAAS2D;AAAA,MACjB;AAAA,MACA,WAAW;AACT,eAAO3D,EAAM;AAAA,MACf;AAAA,MACA,OAAO;AACL,YAAI,CAACJ,KAAOI,EAAM,UAAU,WAAW,EAAG,QAAO;AACjD,QAAAA,EAAM,UAAU,KAAKI,GAAU;AAC/B,cAAMwD,IAAO5D,EAAM,UAAU,IAAA,GACvB6D,IAAUzD,EAAA;AAChB,mBAAW,KAAKyD,EAAS,CAAAjE,EAAI,MAAM,iBAAiB,EAAE,EAAG;AACzD,mBAAW,KAAKgE,EAAM,CAAAhE,EAAI,MAAM,cAAc,CAAC;AAC/C,eAAO;AAAA,MACT;AAAA,MACA,OAAO;AACL,YAAI,CAACA,KAAOI,EAAM,UAAU,WAAW,EAAG,QAAO;AACjD,QAAAA,EAAM,UAAU,KAAKI,GAAU;AAC/B,cAAM0D,IAAO9D,EAAM,UAAU,IAAA,GACvB6D,IAAUzD,EAAA;AAChB,mBAAW,KAAKyD,EAAS,CAAAjE,EAAI,MAAM,iBAAiB,EAAE,EAAG;AACzD,mBAAW,KAAKkE,EAAM,CAAAlE,EAAI,MAAM,cAAc,CAAC;AAC/C,eAAO;AAAA,MACT;AAAA,MACA,QAAQ;AACN,YAAKA,GACL;AAAA,UAAAW,EAAA;AACA,qBAAWjC,KAAK8B,OAAgB,MAAM,iBAAiB9B,EAAE,EAAG;AAAA;AAAA,MAC9D;AAAA,IAAA;AAAA,IAMA,OAAO0C,GAAW;AAChB,MAAApB,IAAMoB;AAAA,IACR;AAAA,IACA,YAAY;AACV,MAAApB,IAAM;AAAA,IACR;AAAA,IACA,cAAcoB,GAAWC,GAAO;AAC9B,UAAKxB,EAAcO,EAAM,IAAI,GAE7B;AAAA,YAAIiB,EAAM,SAAS,aAAa;AAC9B,UAAAoC,EAAgBrC,GAAWC,CAAK;AAChC;AAAA,QACF;AAEA,YAAIA,EAAM,SAAS,aAAa;AAC9B,UAAAsC,EAAgBvC,GAAWC,CAAK;AAChC;AAAA,QACF;AAEA,QAAIA,EAAM,SAAS,aACjBwC,EAAczC,GAAWC,CAAK;AAAA;AAAA,IAElC;AAAA,IACA,gBAAgBD,GAAW;AACzB,YAAMc,IAAMd,EAAU,OAAO;AAC7B,MAAKc,KACLD,EAAYC,GAAKd,EAAU,OAAO,UAAUA,EAAU,MAAM;AAAA,IAC9D;AAAA,IACA,YAAY+B,GAAQ;;AAClB,UAAKA,EAAO,aACRzC,IAAAyC,EAAO,kBAAP,gBAAAzC,EAAsB,QAAQ,qBAAoB;AACtD,mBAAWyD,KAAMjB,EAAaC,CAAM;AAClC,UAAAA,EAAO,QAAQ,KAAK,WAAWgB,CAAE;AAAA,IAErC;AAAA,EAAA;AAEJ;AC3nBA,MAAMvE,KAA2B;AAAA,EAC/B,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU,CAAC,QAAQ;AAAA,EACnB,MAAM,CAAC,UAAU,SAAS;AAC5B;AAWO,SAASwE,GAAalE,GAA6D;AACxF,MAAIF,IAA4B,MAC5BqE,IAA8B,MAC9BC,IAAQ,GACR9G,IAA+C,MAC/C+G,IAAQ;AACZ,QAAMC,IAAUtE,EAAO,WAAW;AAElC,WAASuE,EAAYC,GAAmB;AACtC,UAAMhJ,IAAIsE,GACJ2E,IAAMN,GACNpJ,IAAI,KAAK,IAAIyJ,IAAM,GAAGC,EAAI,EAAE,MAAM,GAClCC,IAAQ,CAACC,MAAwBA,IAAMA,EAAI,SAAS,GAAG5J,CAAC,IAAI;AAClE,IAAAS,EAAE,MAAM,aAAawE,EAAO,UAAU;AAAA,MACpC,GAAG0E,EAAMD,EAAI,CAAC;AAAA,MACd,GAAGC,EAAMD,EAAI,CAAC;AAAA,MACd,MAAMC,EAAMD,EAAI,IAAI;AAAA,MACpB,MAAMC,EAAMD,EAAI,IAAI;AAAA,MACpB,KAAKC,EAAMD,EAAI,GAAG;AAAA,MAClB,OAAOC,EAAMD,EAAI,KAAK;AAAA,IAAA,CACvB;AAAA,EACH;AAEA,QAAMG,IAA2C;AAAA,IAC/C,KAAKxI,IAAI,GAAG;AACV,MAAK+H,MACLE,IAAQ,KAAK,IAAI,KAAKjI,CAAC,GACnBkB,mBAAqBA,CAAK,GAC9BA,IAAQ,YAAY,MAAM;AACxB,YAAI,CAACwC,KAAO,CAACqE,GAAQ;AACnB,UAAAS,EAAI,MAAA;AACJ;AAAA,QACF;AACA,YAAIR,KAASD,EAAO,EAAE,SAAS,GAAG;AAChC,UAAAS,EAAI,MAAA;AACJ;AAAA,QACF;AACA,QAAAR,KACAG,EAAYH,CAAK;AAAA,MACnB,GAAGE,IAAUD,CAAK;AAAA,IACpB;AAAA,IACA,QAAQ;AACN,MAAI/G,MACF,cAAcA,CAAK,GACnBA,IAAQ;AAAA,IAEZ;AAAA,IACA,KAAKuH,IAAQ,GAAG;AACd,MAAKV,MACLC,IAAQ,KAAK,IAAID,EAAO,EAAE,SAAS,GAAGC,IAAQS,CAAK,GACnDN,EAAYH,CAAK;AAAA,IACnB;AAAA,IACA,KAAKhJ,GAAG;AACN,MAAK+I,MACLC,IAAQ,KAAK,IAAI,GAAG,KAAK,IAAID,EAAO,EAAE,SAAS,GAAG/I,CAAC,CAAC,GACpDmJ,EAAYH,CAAK;AAAA,IACnB;AAAA,IACA,WAAW;AACT,aAAOA;AAAA,IACT;AAAA,IACA,YAAY;AACV,cAAOD,KAAA,gBAAAA,EAAQ,EAAE,WAAU;AAAA,IAC7B;AAAA,IACA,YAAY;AACV,aAAO7G,KAAS;AAAA,IAClB;AAAA,EAAA;AAGF,SAAO;AAAA,IACL,UAAAoC;AAAA,IACA,KAAAkF;AAAA,IACA,OAAO1D,GAAW;AAChB,MAAApB,IAAMoB;AACN,YAAMH,IAASjB,EAAI,MAAM,UAAUE,EAAO,QAAQ;AAClD,UAAI,CAACe,GAAQ;AACX,gBAAQ,KAAK,0BAA0Bf,EAAO,QAAQ,aAAa;AACnE;AAAA,MACF;AACA,YAAM,IAAIe,EAAO,QAAA;AACjB,MAAAoD,IAAS;AAAA,QACP,GAAG,aAAa,KAAK,EAAE,CAAC;AAAA,QACxB,GAAG,EAAE,IAAI,aAAa,KAAK,EAAE,CAAC,IAAI;AAAA,QAClC,MAAM,EAAE,OAAO,aAAa,KAAK,EAAE,IAAI,IAAI;AAAA,QAC3C,MAAM,EAAE,OAAO,aAAa,KAAK,EAAE,IAAI,IAAI;AAAA,QAC3C,KAAK,EAAE,MAAM,aAAa,KAAK,EAAE,GAAG,IAAI;AAAA,QACxC,OAAO,EAAE,QAAQ,aAAa,KAAK,EAAE,KAAK,IAAI;AAAA,MAAA,GAEhDC,IAAQ,KAAK,IAAI,GAAGD,EAAO,EAAE,SAAS,CAAC;AAAA,IACzC;AAAA,IACA,YAAY;AACV,MAAAS,EAAI,MAAA,GACJ9E,IAAM,MACNqE,IAAS;AAAA,IACX;AAAA,EAAA;AAEJ;"}
@@ -1 +1 @@
1
- {"version":3,"file":"index-qhscKTDy.js","sources":["../src/core/loading/index.ts","../src/plugins/loading/index.ts"],"sourcesContent":["/**\n * Velo Plot - Loading Indicator Module\n * \n * Provides visual loading/progress indicators for chart operations.\n * Supports progress bars, spinners, and skeleton placeholders.\n * \n * @module loading\n */\n\n// ============================================\n// Types\n// ============================================\n\nexport type LoadingIndicatorType = 'spinner' | 'progress' | 'skeleton' | 'pulse';\n\nexport interface LoadingIndicatorOptions {\n /** Indicator type (default: 'spinner') */\n type?: LoadingIndicatorType;\n /** Message to display (default: 'Loading...') */\n message?: string;\n /** Show percentage for progress type (default: true) */\n showPercentage?: boolean;\n /** Background overlay opacity (0-1, default: 0.7) */\n overlayOpacity?: number;\n /** Accent color for spinner/progress (default: '#00f2ff') */\n accentColor?: string;\n /** Background color (default: 'rgba(0,0,0,0.7)') */\n backgroundColor?: string;\n /** Text color (default: '#ffffff') */\n textColor?: string;\n /** Size: 'small', 'medium', 'large' (default: 'medium') */\n size?: 'small' | 'medium' | 'large';\n /** Custom CSS class */\n className?: string;\n /** Auto-hide after completion (default: true) */\n autoHide?: boolean;\n /** Hide delay in ms after completion (default: 300) */\n hideDelay?: number;\n}\n\nexport interface LoadingState {\n /** Whether loading is in progress */\n isLoading: boolean;\n /** Progress value (0-100) */\n progress: number;\n /** Current message */\n message: string;\n /** Start time of loading */\n startTime: number | null;\n /** Estimated time remaining in ms */\n eta: number | null;\n}\n\n// ============================================\n// Loading Indicator Implementation\n// ============================================\n\nexport class LoadingIndicator {\n private container: HTMLElement;\n private element: HTMLDivElement | null = null;\n private options: Required<LoadingIndicatorOptions>;\n private state: LoadingState = {\n isLoading: false,\n progress: 0,\n message: '',\n startTime: null,\n eta: null,\n };\n\n // For ETA calculation\n private progressHistory: { time: number; progress: number }[] = [];\n\n constructor(container: HTMLElement, options?: LoadingIndicatorOptions) {\n this.container = container;\n this.options = {\n type: 'spinner',\n message: 'Loading...',\n showPercentage: true,\n overlayOpacity: 0.7,\n accentColor: '#00f2ff',\n backgroundColor: 'rgba(0, 0, 0, 0.7)',\n textColor: '#ffffff',\n size: 'medium',\n className: 'velo-plot-loading',\n autoHide: true,\n hideDelay: 200,\n ...options,\n };\n this.state.message = this.options.message;\n }\n\n /**\n * Show the loading indicator\n */\n show(message?: string): void {\n this.state.isLoading = true;\n this.state.progress = 0;\n this.state.startTime = performance.now();\n this.state.eta = null;\n this.progressHistory = [];\n \n if (message) {\n this.state.message = message;\n }\n\n this.createElement();\n this.render();\n }\n\n /**\n * Hide the loading indicator\n */\n hide(): void {\n if (!this.state.isLoading) return;\n this.state.isLoading = false;\n \n if (this.element) {\n this.element.style.opacity = '0';\n }\n\n if (this.options.autoHide) {\n setTimeout(() => {\n this.destroyElement();\n }, this.options.hideDelay);\n } else {\n this.destroyElement();\n }\n }\n\n /**\n * Update progress (0-100)\n */\n setProgress(progress: number, message?: string): void {\n const clampedProgress = Math.max(0, Math.min(100, progress));\n this.state.progress = clampedProgress;\n \n if (message) {\n this.state.message = message;\n }\n\n // Track progress for ETA\n this.progressHistory.push({\n time: performance.now(),\n progress: clampedProgress,\n });\n\n // Keep only recent history\n if (this.progressHistory.length > 10) {\n this.progressHistory.shift();\n }\n\n // Calculate ETA\n this.calculateEta();\n \n this.render();\n\n // Auto-complete\n if (clampedProgress >= 100 && this.options.autoHide) {\n this.hide();\n }\n }\n\n /**\n * Update message only\n */\n setMessage(message: string): void {\n this.state.message = message;\n this.render();\n }\n\n /**\n * Check if loading is in progress\n */\n isLoading(): boolean {\n return this.state.isLoading;\n }\n\n /**\n * Get current progress\n */\n getProgress(): number {\n return this.state.progress;\n }\n\n /**\n * Get current state\n */\n getState(): LoadingState {\n return { ...this.state };\n }\n\n /**\n * Destroy the indicator\n */\n destroy(): void {\n this.hide();\n this.destroyElement();\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private createElement(): void {\n if (this.element) return;\n\n this.element = document.createElement('div');\n this.element.className = this.options.className;\n \n // Apply overlay styles\n Object.assign(this.element.style, {\n position: 'absolute',\n top: '0',\n left: '0',\n right: '0',\n bottom: '0',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: this.options.backgroundColor,\n zIndex: '9998',\n transition: 'opacity 0.2s ease',\n });\n\n // Create inner content\n this.element.innerHTML = this.getInnerHtml();\n \n // Inject styles\n this.injectStyles();\n\n this.container.style.position = 'relative';\n this.container.appendChild(this.element);\n }\n\n private destroyElement(): void {\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n this.element = null;\n }\n\n private render(): void {\n if (!this.element) return;\n this.element.innerHTML = this.getInnerHtml();\n }\n\n private getInnerHtml(): string {\n const { type, accentColor, textColor, size, showPercentage } = this.options;\n const { progress, message, eta } = this.state;\n \n const sizeMap = { small: 24, medium: 40, large: 56 };\n const spinnerSize = sizeMap[size];\n const fontSize = size === 'small' ? 12 : size === 'large' ? 16 : 14;\n\n let content = '';\n\n switch (type) {\n case 'spinner':\n content = `\n <div class=\"velo-plot-loading-spinner\" style=\"\n width: ${spinnerSize}px;\n height: ${spinnerSize}px;\n border: 3px solid rgba(255,255,255,0.2);\n border-top-color: ${accentColor};\n border-radius: 50%;\n animation: velo-plot-spin 0.8s linear infinite;\n \"></div>\n `;\n break;\n\n case 'progress':\n content = `\n <div class=\"velo-plot-loading-progress\" style=\"\n width: 200px;\n height: 8px;\n background: rgba(255,255,255,0.2);\n border-radius: 4px;\n overflow: hidden;\n \">\n <div style=\"\n width: ${progress}%;\n height: 100%;\n background: ${accentColor};\n transition: width 0.2s ease;\n \"></div>\n </div>\n ${showPercentage ? `\n <div style=\"\n color: ${textColor};\n font-size: ${fontSize}px;\n margin-top: 8px;\n font-family: system-ui, sans-serif;\n \">${Math.round(progress)}%</div>\n ` : ''}\n `;\n break;\n\n case 'skeleton':\n content = `\n <div class=\"velo-plot-loading-skeleton\" style=\"\n width: 80%;\n max-width: 300px;\n \">\n <div class=\"velo-plot-skeleton-line\" style=\"height: 20px; margin-bottom: 8px;\"></div>\n <div class=\"velo-plot-skeleton-line\" style=\"height: 16px; width: 60%; margin-bottom: 8px;\"></div>\n <div class=\"velo-plot-skeleton-line\" style=\"height: 40px;\"></div>\n </div>\n `;\n break;\n\n case 'pulse':\n content = `\n <div class=\"velo-plot-loading-pulse\" style=\"\n width: ${spinnerSize}px;\n height: ${spinnerSize}px;\n background: ${accentColor};\n border-radius: 50%;\n animation: velo-plot-pulse 1.2s ease-in-out infinite;\n \"></div>\n `;\n break;\n }\n\n // Add message\n if (message) {\n content += `\n <div style=\"\n color: ${textColor};\n font-size: ${fontSize}px;\n margin-top: 12px;\n font-family: system-ui, sans-serif;\n \">${message}</div>\n `;\n }\n\n // Add ETA if available\n if (eta !== null && eta > 0 && type === 'progress') {\n content += `\n <div style=\"\n color: rgba(255,255,255,0.6);\n font-size: ${fontSize - 2}px;\n margin-top: 4px;\n font-family: system-ui, sans-serif;\n \">~${this.formatTime(eta)} remaining</div>\n `;\n }\n\n return content;\n }\n\n private injectStyles(): void {\n const styleId = 'velo-plot-loading-styles';\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n @keyframes velo-plot-spin {\n to { transform: rotate(360deg); }\n }\n \n @keyframes velo-plot-pulse {\n 0%, 100% { transform: scale(1); opacity: 1; }\n 50% { transform: scale(1.2); opacity: 0.7; }\n }\n \n @keyframes velo-plot-skeleton-shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n }\n \n .velo-plot-skeleton-line {\n background: linear-gradient(\n 90deg,\n rgba(255,255,255,0.1) 25%,\n rgba(255,255,255,0.2) 50%,\n rgba(255,255,255,0.1) 75%\n );\n background-size: 200% 100%;\n animation: velo-plot-skeleton-shimmer 1.5s infinite;\n border-radius: 4px;\n }\n `;\n document.head.appendChild(style);\n }\n\n private calculateEta(): void {\n if (this.progressHistory.length < 2) {\n this.state.eta = null;\n return;\n }\n\n const first = this.progressHistory[0];\n const last = this.progressHistory[this.progressHistory.length - 1];\n \n const progressDelta = last.progress - first.progress;\n const timeDelta = last.time - first.time;\n\n if (progressDelta <= 0) {\n this.state.eta = null;\n return;\n }\n\n const remainingProgress = 100 - last.progress;\n const rate = progressDelta / timeDelta;\n this.state.eta = remainingProgress / rate;\n }\n\n private formatTime(ms: number): string {\n const seconds = Math.ceil(ms / 1000);\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = seconds % 60;\n return `${minutes}m ${remainingSeconds}s`;\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\n/**\n * Create a loading indicator for a container\n */\nexport function createLoadingIndicator(\n container: HTMLElement,\n options?: LoadingIndicatorOptions\n): LoadingIndicator {\n return new LoadingIndicator(container, options);\n}\n\n/**\n * Show loading with a simple spinner\n */\nexport function showLoading(\n container: HTMLElement,\n message?: string\n): LoadingIndicator {\n const indicator = new LoadingIndicator(container, { message });\n indicator.show();\n return indicator;\n}\n\n/**\n * Show progress loading\n */\nexport function showProgress(\n container: HTMLElement,\n message?: string\n): LoadingIndicator {\n const indicator = new LoadingIndicator(container, {\n type: 'progress',\n message,\n });\n indicator.show();\n return indicator;\n}\n","/**\n * VeloPlot Engine - Loading Indicator Plugin\n * \n * Provides customizable loading and progress indicators.\n * \n * @module plugins/loading\n */\n\nimport { LoadingIndicator } from \"../../core/loading\";\nimport type { LoadingIndicatorOptions } from \"../../core/loading\";\nimport type { PluginManifest, ChartPlugin, PluginContext } from \"../types\";\n\nexport interface PluginLoadingConfig extends Partial<LoadingIndicatorOptions> {\n /** Auto-show on heavy data operations */\n autoShow?: boolean;\n}\n\nconst manifestLoading: PluginManifest = {\n name: \"velo-plot-loading\",\n version: \"1.0.0\",\n description: \"Loading and progress indicators for velo-plot\",\n provides: [\"ui\"],\n tags: [\"loading\", \"progress\", \"ui\", \"ux\"],\n};\n\n/**\n * VeloPlot Loading Plugin\n * \n * Adds sleek loading indicators and progress trackers to the chart.\n */\nexport function PluginLoading(_config: PluginLoadingConfig = {}): ChartPlugin<PluginLoadingConfig> {\n let indicator: LoadingIndicator | null = null;\n\n return {\n manifest: manifestLoading,\n\n onInit(ctx: PluginContext) { \n // Create the indicator using the container from the UI context\n indicator = new LoadingIndicator(ctx.ui.container, {\n ..._config,\n // Inherit theme colors if not explicitly provided\n accentColor: _config.accentColor || (ctx.ui.theme.isDark ? '#00f2ff' : '#00b4d8'),\n });\n\n // If autoShow is enabled (or by default during init), show it\n if (_config.autoShow !== false) {\n indicator.show(_config.message || 'Initializing Chart...');\n }\n\n // Optional: Auto-hide on first successful render WITH data\n if (_config.autoHide !== false) {\n const off = ctx.events.on('render', () => {\n const hasData = ctx.data.getAllSeries().some(s => s.getPointCount() > 0);\n if (hasData) {\n indicator?.hide();\n off();\n }\n });\n }\n },\n\n onDestroy(_ctx: PluginContext) {\n indicator?.destroy();\n indicator = null;\n },\n\n api: {\n show(message?: string) {\n indicator?.show(message);\n },\n hide() {\n indicator?.hide();\n },\n setProgress(progress: number, message?: string) {\n indicator?.setProgress(progress, message);\n },\n setMessage(message: string) {\n indicator?.setMessage(message);\n },\n getIndicator: () => indicator\n }\n };\n}\n\nexport { LoadingIndicator };\nexport default PluginLoading;\n"],"names":["LoadingIndicator","container","options","__publicField","message","progress","clampedProgress","type","accentColor","textColor","size","showPercentage","eta","spinnerSize","fontSize","content","styleId","style","first","last","progressDelta","timeDelta","remainingProgress","rate","ms","seconds","minutes","remainingSeconds","createLoadingIndicator","showLoading","indicator","showProgress","manifestLoading","PluginLoading","_config","ctx","off","s","_ctx"],"mappings":"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"}
1
+ {"version":3,"file":"index-qhscKTDy.js","sources":["../src/core/loading/index.ts","../src/plugins/loading/index.ts"],"sourcesContent":["/**\n * Velo Plot - Loading Indicator Module\n * \n * Provides visual loading/progress indicators for chart operations.\n * Supports progress bars, spinners, and skeleton placeholders.\n * \n * @module loading\n */\n\n// ============================================\n// Types\n// ============================================\n\nexport type LoadingIndicatorType = 'spinner' | 'progress' | 'skeleton' | 'pulse';\n\nexport interface LoadingIndicatorOptions {\n /** Indicator type (default: 'spinner') */\n type?: LoadingIndicatorType;\n /** Message to display (default: 'Loading...') */\n message?: string;\n /** Show percentage for progress type (default: true) */\n showPercentage?: boolean;\n /** Background overlay opacity (0-1, default: 0.7) */\n overlayOpacity?: number;\n /** Accent color for spinner/progress (default: '#00f2ff') */\n accentColor?: string;\n /** Background color (default: 'rgba(0,0,0,0.7)') */\n backgroundColor?: string;\n /** Text color (default: '#ffffff') */\n textColor?: string;\n /** Size: 'small', 'medium', 'large' (default: 'medium') */\n size?: 'small' | 'medium' | 'large';\n /** Custom CSS class */\n className?: string;\n /** Auto-hide after completion (default: true) */\n autoHide?: boolean;\n /** Hide delay in ms after completion (default: 300) */\n hideDelay?: number;\n}\n\nexport interface LoadingState {\n /** Whether loading is in progress */\n isLoading: boolean;\n /** Progress value (0-100) */\n progress: number;\n /** Current message */\n message: string;\n /** Start time of loading */\n startTime: number | null;\n /** Estimated time remaining in ms */\n eta: number | null;\n}\n\n// ============================================\n// Loading Indicator Implementation\n// ============================================\n\nexport class LoadingIndicator {\n private container: HTMLElement;\n private element: HTMLDivElement | null = null;\n private options: Required<LoadingIndicatorOptions>;\n private state: LoadingState = {\n isLoading: false,\n progress: 0,\n message: '',\n startTime: null,\n eta: null,\n };\n\n // For ETA calculation\n private progressHistory: { time: number; progress: number }[] = [];\n\n constructor(container: HTMLElement, options?: LoadingIndicatorOptions) {\n this.container = container;\n this.options = {\n type: 'spinner',\n message: 'Loading...',\n showPercentage: true,\n overlayOpacity: 0.7,\n accentColor: '#00f2ff',\n backgroundColor: 'rgba(0, 0, 0, 0.7)',\n textColor: '#ffffff',\n size: 'medium',\n className: 'velo-plot-loading',\n autoHide: true,\n hideDelay: 200,\n ...options,\n };\n this.state.message = this.options.message;\n }\n\n /**\n * Show the loading indicator\n */\n show(message?: string): void {\n this.state.isLoading = true;\n this.state.progress = 0;\n this.state.startTime = performance.now();\n this.state.eta = null;\n this.progressHistory = [];\n \n if (message) {\n this.state.message = message;\n }\n\n this.createElement();\n this.render();\n }\n\n /**\n * Hide the loading indicator\n */\n hide(): void {\n if (!this.state.isLoading) return;\n this.state.isLoading = false;\n \n if (this.element) {\n this.element.style.opacity = '0';\n }\n\n if (this.options.autoHide) {\n setTimeout(() => {\n this.destroyElement();\n }, this.options.hideDelay);\n } else {\n this.destroyElement();\n }\n }\n\n /**\n * Update progress (0-100)\n */\n setProgress(progress: number, message?: string): void {\n const clampedProgress = Math.max(0, Math.min(100, progress));\n this.state.progress = clampedProgress;\n \n if (message) {\n this.state.message = message;\n }\n\n // Track progress for ETA\n this.progressHistory.push({\n time: performance.now(),\n progress: clampedProgress,\n });\n\n // Keep only recent history\n if (this.progressHistory.length > 10) {\n this.progressHistory.shift();\n }\n\n // Calculate ETA\n this.calculateEta();\n \n this.render();\n\n // Auto-complete\n if (clampedProgress >= 100 && this.options.autoHide) {\n this.hide();\n }\n }\n\n /**\n * Update message only\n */\n setMessage(message: string): void {\n this.state.message = message;\n this.render();\n }\n\n /**\n * Check if loading is in progress\n */\n isLoading(): boolean {\n return this.state.isLoading;\n }\n\n /**\n * Get current progress\n */\n getProgress(): number {\n return this.state.progress;\n }\n\n /**\n * Get current state\n */\n getState(): LoadingState {\n return { ...this.state };\n }\n\n /**\n * Destroy the indicator\n */\n destroy(): void {\n this.hide();\n this.destroyElement();\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private createElement(): void {\n if (this.element) return;\n\n this.element = document.createElement('div');\n this.element.className = this.options.className;\n \n // Apply overlay styles\n Object.assign(this.element.style, {\n position: 'absolute',\n top: '0',\n left: '0',\n right: '0',\n bottom: '0',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: this.options.backgroundColor,\n zIndex: '9998',\n transition: 'opacity 0.2s ease',\n });\n\n // Create inner content\n this.element.innerHTML = this.getInnerHtml();\n \n // Inject styles\n this.injectStyles();\n\n this.container.style.position = 'relative';\n this.container.appendChild(this.element);\n }\n\n private destroyElement(): void {\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n this.element = null;\n }\n\n private render(): void {\n if (!this.element) return;\n this.element.innerHTML = this.getInnerHtml();\n }\n\n private getInnerHtml(): string {\n const { type, accentColor, textColor, size, showPercentage } = this.options;\n const { progress, message, eta } = this.state;\n \n const sizeMap = { small: 24, medium: 40, large: 56 };\n const spinnerSize = sizeMap[size];\n const fontSize = size === 'small' ? 12 : size === 'large' ? 16 : 14;\n\n let content = '';\n\n switch (type) {\n case 'spinner':\n content = `\n <div class=\"velo-plot-loading-spinner\" style=\"\n width: ${spinnerSize}px;\n height: ${spinnerSize}px;\n border: 3px solid rgba(255,255,255,0.2);\n border-top-color: ${accentColor};\n border-radius: 50%;\n animation: velo-plot-spin 0.8s linear infinite;\n \"></div>\n `;\n break;\n\n case 'progress':\n content = `\n <div class=\"velo-plot-loading-progress\" style=\"\n width: 200px;\n height: 8px;\n background: rgba(255,255,255,0.2);\n border-radius: 4px;\n overflow: hidden;\n \">\n <div style=\"\n width: ${progress}%;\n height: 100%;\n background: ${accentColor};\n transition: width 0.2s ease;\n \"></div>\n </div>\n ${showPercentage ? `\n <div style=\"\n color: ${textColor};\n font-size: ${fontSize}px;\n margin-top: 8px;\n font-family: system-ui, sans-serif;\n \">${Math.round(progress)}%</div>\n ` : ''}\n `;\n break;\n\n case 'skeleton':\n content = `\n <div class=\"velo-plot-loading-skeleton\" style=\"\n width: 80%;\n max-width: 300px;\n \">\n <div class=\"velo-plot-skeleton-line\" style=\"height: 20px; margin-bottom: 8px;\"></div>\n <div class=\"velo-plot-skeleton-line\" style=\"height: 16px; width: 60%; margin-bottom: 8px;\"></div>\n <div class=\"velo-plot-skeleton-line\" style=\"height: 40px;\"></div>\n </div>\n `;\n break;\n\n case 'pulse':\n content = `\n <div class=\"velo-plot-loading-pulse\" style=\"\n width: ${spinnerSize}px;\n height: ${spinnerSize}px;\n background: ${accentColor};\n border-radius: 50%;\n animation: velo-plot-pulse 1.2s ease-in-out infinite;\n \"></div>\n `;\n break;\n }\n\n // Add message\n if (message) {\n content += `\n <div style=\"\n color: ${textColor};\n font-size: ${fontSize}px;\n margin-top: 12px;\n font-family: system-ui, sans-serif;\n \">${message}</div>\n `;\n }\n\n // Add ETA if available\n if (eta !== null && eta > 0 && type === 'progress') {\n content += `\n <div style=\"\n color: rgba(255,255,255,0.6);\n font-size: ${fontSize - 2}px;\n margin-top: 4px;\n font-family: system-ui, sans-serif;\n \">~${this.formatTime(eta)} remaining</div>\n `;\n }\n\n return content;\n }\n\n private injectStyles(): void {\n const styleId = 'velo-plot-loading-styles';\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n @keyframes velo-plot-spin {\n to { transform: rotate(360deg); }\n }\n \n @keyframes velo-plot-pulse {\n 0%, 100% { transform: scale(1); opacity: 1; }\n 50% { transform: scale(1.2); opacity: 0.7; }\n }\n \n @keyframes velo-plot-skeleton-shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n }\n \n .velo-plot-skeleton-line {\n background: linear-gradient(\n 90deg,\n rgba(255,255,255,0.1) 25%,\n rgba(255,255,255,0.2) 50%,\n rgba(255,255,255,0.1) 75%\n );\n background-size: 200% 100%;\n animation: velo-plot-skeleton-shimmer 1.5s infinite;\n border-radius: 4px;\n }\n `;\n document.head.appendChild(style);\n }\n\n private calculateEta(): void {\n if (this.progressHistory.length < 2) {\n this.state.eta = null;\n return;\n }\n\n const first = this.progressHistory[0];\n const last = this.progressHistory[this.progressHistory.length - 1];\n \n const progressDelta = last.progress - first.progress;\n const timeDelta = last.time - first.time;\n\n if (progressDelta <= 0) {\n this.state.eta = null;\n return;\n }\n\n const remainingProgress = 100 - last.progress;\n const rate = progressDelta / timeDelta;\n this.state.eta = remainingProgress / rate;\n }\n\n private formatTime(ms: number): string {\n const seconds = Math.ceil(ms / 1000);\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = seconds % 60;\n return `${minutes}m ${remainingSeconds}s`;\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\n/**\n * Create a loading indicator for a container\n */\nexport function createLoadingIndicator(\n container: HTMLElement,\n options?: LoadingIndicatorOptions\n): LoadingIndicator {\n return new LoadingIndicator(container, options);\n}\n\n/**\n * Show loading with a simple spinner\n */\nexport function showLoading(\n container: HTMLElement,\n message?: string\n): LoadingIndicator {\n const indicator = new LoadingIndicator(container, { message });\n indicator.show();\n return indicator;\n}\n\n/**\n * Show progress loading\n */\nexport function showProgress(\n container: HTMLElement,\n message?: string\n): LoadingIndicator {\n const indicator = new LoadingIndicator(container, {\n type: 'progress',\n message,\n });\n indicator.show();\n return indicator;\n}\n","/**\n * VeloPlot Engine - Loading Indicator Plugin\n * \n * Provides customizable loading and progress indicators.\n * \n * @module plugins/loading\n */\n\nimport { LoadingIndicator } from \"../../core/loading\";\nimport type { LoadingIndicatorOptions } from \"../../core/loading\";\nimport type { PluginManifest, ChartPlugin, PluginContext } from \"../types\";\n\nexport interface PluginLoadingConfig extends Partial<LoadingIndicatorOptions> {\n /** Auto-show on heavy data operations */\n autoShow?: boolean;\n}\n\nconst manifestLoading: PluginManifest = {\n name: \"velo-plot-loading\",\n version: \"1.0.0\",\n description: \"Loading and progress indicators for velo-plot\",\n provides: [\"ui\"],\n tags: [\"loading\", \"progress\", \"ui\", \"ux\"],\n};\n\n/**\n * VeloPlot Loading Plugin\n * \n * Adds sleek loading indicators and progress trackers to the chart.\n */\nexport function PluginLoading(_config: PluginLoadingConfig = {}): ChartPlugin<PluginLoadingConfig> {\n let indicator: LoadingIndicator | null = null;\n\n return {\n manifest: manifestLoading,\n\n onInit(ctx: PluginContext) { \n // Create the indicator using the container from the UI context\n indicator = new LoadingIndicator(ctx.ui.container, {\n ..._config,\n // Inherit theme colors if not explicitly provided\n accentColor: _config.accentColor || (ctx.ui.theme.isDark ? '#00f2ff' : '#00b4d8'),\n });\n\n // If autoShow is enabled (or by default during init), show it\n if (_config.autoShow !== false) {\n indicator.show(_config.message || 'Initializing Chart...');\n }\n\n // Optional: Auto-hide on first successful render WITH data\n if (_config.autoHide !== false) {\n const off = ctx.events.on('render', () => {\n const hasData = ctx.data.getAllSeries().some(s => s.getPointCount() > 0);\n if (hasData) {\n indicator?.hide();\n off();\n }\n });\n }\n },\n\n onDestroy(_ctx: PluginContext) {\n indicator?.destroy();\n indicator = null;\n },\n\n api: {\n show(message?: string) {\n indicator?.show(message);\n },\n hide() {\n indicator?.hide();\n },\n setProgress(progress: number, message?: string) {\n indicator?.setProgress(progress, message);\n },\n setMessage(message: string) {\n indicator?.setMessage(message);\n },\n getIndicator: () => indicator\n }\n };\n}\n\nexport default PluginLoading;\n"],"names":["LoadingIndicator","container","options","__publicField","message","progress","clampedProgress","type","accentColor","textColor","size","showPercentage","eta","spinnerSize","fontSize","content","styleId","style","first","last","progressDelta","timeDelta","remainingProgress","rate","ms","seconds","minutes","remainingSeconds","createLoadingIndicator","showLoading","indicator","showProgress","manifestLoading","PluginLoading","_config","ctx","off","s","_ctx"],"mappings":"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"}
@@ -2,7 +2,6 @@
2
2
  * Velo Plot - Core Bundle
3
3
  *
4
4
  * Minimal bundle containing only the essential features for 2D charts.
5
- * Achieve ~60KB gzipped by excluding optional plugins.
6
5
  */
7
6
  export { createChart } from './core/Chart';
8
7
  export { Series } from './core/Series';
@@ -11,10 +10,13 @@ export type { Chart, ChartOptions, ExportOptions } from './core/Chart';
11
10
  export type { AxisOptions, SeriesOptions, SeriesData, SeriesStyle, ZoomOptions, Point, Bounds, Range, ScaleType, SeriesType, } from './types';
12
11
  export { LinearScale, LogScale, createScale } from './scales';
13
12
  export type { Scale } from './scales';
14
- export { NativeWebGLRenderer, parseColor, createRenderer, createNativeRenderer, } from './renderer';
15
- export type { IWebGLRenderer, SeriesRenderData, RenderOptions } from './renderer';
13
+ export { NativeWebGLRenderer, parseColor, } from './renderer/NativeWebGLRenderer';
14
+ export { createRenderer, createNativeRenderer, } from './renderer/RendererInterface';
15
+ export type { IWebGLRenderer, SeriesRenderData, RenderOptions, } from './renderer/RendererInterface';
16
16
  export { DARK_THEME, LIGHT_THEME, DEFAULT_THEME, createTheme, getThemeByName, } from './theme';
17
17
  export type { ChartTheme, GridTheme, AxisTheme } from './theme';
18
- export { AnimationEngine, easings, DEFAULT_ANIMATION_CONFIG, getSharedAnimationEngine, } from './core/animation';
19
- export { createPluginContext, PluginManagerImpl, getPluginRegistry, registerPlugin, definePlugin, createPlugin, createConfigurablePlugin, } from './plugins';
20
- export type { PluginManifest, PluginContext, ChartPlugin, PluginFactory, PluginManager, } from './plugins';
18
+ export { createPluginContext } from './plugins/PluginContext';
19
+ export { PluginManagerImpl } from './plugins/PluginManager';
20
+ export { getPluginRegistry, registerPlugin, definePlugin, } from './plugins/PluginRegistry';
21
+ export { createPlugin, createConfigurablePlugin } from './plugins/createPlugin';
22
+ export type { PluginManifest, PluginContext, ChartPlugin, PluginFactory, PluginManager, } from './plugins/types';
package/dist/index.d.ts CHANGED
@@ -1,17 +1,4 @@
1
- /**
2
- * Velo Plot - High-Performance Scientific Charting
3
- *
4
- * A WebGL-based charting engine designed for scientific data visualization
5
- * and high-performance rendering of large datasets.
6
- *
7
- * Features:
8
- * - 10⁵–10⁶ points at 60 FPS
9
- * - Zoom/pan via GPU uniforms (no buffer recreation)
10
- * - Scientific precision with Float32/Float64 arrays
11
- * - Data analysis utilities (peak detection, cycle detection, etc.)
12
- *
13
- * @packageDocumentation
14
- */
1
+
15
2
  export { createChart } from './core/Chart';
16
3
  export { Series } from './core/Series';
17
4
  export { EventEmitter } from './core/EventEmitter';
@@ -2969,7 +2969,9 @@ class Ct {
2969
2969
  return;
2970
2970
  }
2971
2971
  const e = this.impulseData, t = e.baseY ?? 0;
2972
- let i = 1 / 0, s = -1 / 0, n = t, o = -1 / 0, l = 1 / 0, h = -1 / 0;
2972
+ let i = 1 / 0, s = -1 / 0;
2973
+ const n = t;
2974
+ let o = -1 / 0, l = 1 / 0, h = -1 / 0;
2973
2975
  for (let c = 0; c < e.x.length; c++)
2974
2976
  e.x[c] < i && (i = e.x[c]), e.x[c] > s && (s = e.x[c]), e.y[c] > o && (o = e.y[c]), e.z[c] < l && (l = e.z[c]), e.z[c] > h && (h = e.z[c]);
2975
2977
  this.bounds = { minX: i, maxX: s, minY: n, maxY: o, minZ: l, maxZ: h };