@forgecharts/sdk 1.1.23 → 1.1.28

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 (562) hide show
  1. package/dist/__tests__/backwardCompatibility.test.d.ts +14 -0
  2. package/dist/__tests__/backwardCompatibility.test.d.ts.map +1 -0
  3. package/dist/__tests__/backwardCompatibility.test.js +159 -0
  4. package/dist/__tests__/backwardCompatibility.test.js.map +1 -0
  5. package/dist/__tests__/candleInvariant.test.d.ts +20 -0
  6. package/dist/__tests__/candleInvariant.test.d.ts.map +1 -0
  7. package/dist/__tests__/candleInvariant.test.js +415 -0
  8. package/dist/__tests__/candleInvariant.test.js.map +1 -0
  9. package/dist/__tests__/public-api-surface.d.ts +13 -0
  10. package/dist/__tests__/public-api-surface.d.ts.map +1 -0
  11. package/{src/__tests__/public-api-surface.ts → dist/__tests__/public-api-surface.js} +4 -42
  12. package/dist/__tests__/public-api-surface.js.map +1 -0
  13. package/dist/__tests__/timeframeBoundary.test.d.ts +17 -0
  14. package/dist/__tests__/timeframeBoundary.test.d.ts.map +1 -0
  15. package/dist/__tests__/timeframeBoundary.test.js +452 -0
  16. package/dist/__tests__/timeframeBoundary.test.js.map +1 -0
  17. package/dist/api/DrawingManager.d.ts +20 -0
  18. package/dist/api/DrawingManager.d.ts.map +1 -0
  19. package/dist/api/DrawingManager.js +190 -0
  20. package/dist/api/DrawingManager.js.map +1 -0
  21. package/dist/api/EventBus.d.ts +19 -0
  22. package/dist/api/EventBus.d.ts.map +1 -0
  23. package/dist/api/EventBus.js +44 -0
  24. package/dist/api/EventBus.js.map +1 -0
  25. package/dist/api/IndicatorDAG.d.ts +85 -0
  26. package/dist/api/IndicatorDAG.d.ts.map +1 -0
  27. package/dist/api/IndicatorDAG.js +316 -0
  28. package/dist/api/IndicatorDAG.js.map +1 -0
  29. package/dist/api/IndicatorRegistry.d.ts +22 -0
  30. package/dist/api/IndicatorRegistry.d.ts.map +1 -0
  31. package/dist/api/IndicatorRegistry.js +39 -0
  32. package/dist/api/IndicatorRegistry.js.map +1 -0
  33. package/dist/api/LayoutManager.d.ts +30 -0
  34. package/dist/api/LayoutManager.d.ts.map +1 -0
  35. package/dist/api/LayoutManager.js +51 -0
  36. package/dist/api/LayoutManager.js.map +1 -0
  37. package/dist/api/PaneManager.d.ts +42 -0
  38. package/dist/api/PaneManager.d.ts.map +1 -0
  39. package/dist/api/PaneManager.js +119 -0
  40. package/dist/api/PaneManager.js.map +1 -0
  41. package/dist/api/ReferenceAPI.d.ts +78 -0
  42. package/dist/api/ReferenceAPI.d.ts.map +1 -0
  43. package/dist/api/ReferenceAPI.js +153 -0
  44. package/dist/api/ReferenceAPI.js.map +1 -0
  45. package/dist/api/TChart.d.ts +345 -0
  46. package/dist/api/TChart.d.ts.map +1 -0
  47. package/dist/api/TChart.js +765 -0
  48. package/dist/api/TChart.js.map +1 -0
  49. package/{src/api/createChart.ts → dist/api/createChart.d.ts} +2 -7
  50. package/dist/api/createChart.d.ts.map +1 -0
  51. package/dist/api/createChart.js +42 -0
  52. package/dist/api/createChart.js.map +1 -0
  53. package/dist/api/drawing tools/fib gann menu/fibRetracement.d.ts +4 -0
  54. package/dist/api/drawing tools/fib gann menu/fibRetracement.d.ts.map +1 -0
  55. package/dist/api/drawing tools/fib gann menu/fibRetracement.js +22 -0
  56. package/dist/api/drawing tools/fib gann menu/fibRetracement.js.map +1 -0
  57. package/dist/api/drawing tools/lines menu/crossLine.d.ts +4 -0
  58. package/dist/api/drawing tools/lines menu/crossLine.d.ts.map +1 -0
  59. package/dist/api/drawing tools/lines menu/crossLine.js +16 -0
  60. package/dist/api/drawing tools/lines menu/crossLine.js.map +1 -0
  61. package/dist/api/drawing tools/lines menu/disjointChannel.d.ts +17 -0
  62. package/dist/api/drawing tools/lines menu/disjointChannel.d.ts.map +1 -0
  63. package/dist/api/drawing tools/lines menu/disjointChannel.js +59 -0
  64. package/dist/api/drawing tools/lines menu/disjointChannel.js.map +1 -0
  65. package/dist/api/drawing tools/lines menu/extendedLine.d.ts +4 -0
  66. package/dist/api/drawing tools/lines menu/extendedLine.d.ts.map +1 -0
  67. package/dist/api/drawing tools/lines menu/extendedLine.js +17 -0
  68. package/dist/api/drawing tools/lines menu/extendedLine.js.map +1 -0
  69. package/dist/api/drawing tools/lines menu/flatTopBottom.d.ts +4 -0
  70. package/dist/api/drawing tools/lines menu/flatTopBottom.d.ts.map +1 -0
  71. package/dist/api/drawing tools/lines menu/flatTopBottom.js +41 -0
  72. package/dist/api/drawing tools/lines menu/flatTopBottom.js.map +1 -0
  73. package/dist/api/drawing tools/lines menu/horizontal.d.ts +4 -0
  74. package/dist/api/drawing tools/lines menu/horizontal.d.ts.map +1 -0
  75. package/dist/api/drawing tools/lines menu/horizontal.js +19 -0
  76. package/dist/api/drawing tools/lines menu/horizontal.js.map +1 -0
  77. package/dist/api/drawing tools/lines menu/horizontalRay.d.ts +4 -0
  78. package/dist/api/drawing tools/lines menu/horizontalRay.d.ts.map +1 -0
  79. package/dist/api/drawing tools/lines menu/horizontalRay.js +20 -0
  80. package/dist/api/drawing tools/lines menu/horizontalRay.js.map +1 -0
  81. package/dist/api/drawing tools/lines menu/infoLine.d.ts +4 -0
  82. package/dist/api/drawing tools/lines menu/infoLine.d.ts.map +1 -0
  83. package/dist/api/drawing tools/lines menu/infoLine.js +107 -0
  84. package/dist/api/drawing tools/lines menu/infoLine.js.map +1 -0
  85. package/dist/api/drawing tools/lines menu/insidePitchfork.d.ts +4 -0
  86. package/dist/api/drawing tools/lines menu/insidePitchfork.d.ts.map +1 -0
  87. package/dist/api/drawing tools/lines menu/insidePitchfork.js +31 -0
  88. package/dist/api/drawing tools/lines menu/insidePitchfork.js.map +1 -0
  89. package/dist/api/drawing tools/lines menu/modifiedSchiffPitchfork.d.ts +4 -0
  90. package/dist/api/drawing tools/lines menu/modifiedSchiffPitchfork.d.ts.map +1 -0
  91. package/dist/api/drawing tools/lines menu/modifiedSchiffPitchfork.js +15 -0
  92. package/dist/api/drawing tools/lines menu/modifiedSchiffPitchfork.js.map +1 -0
  93. package/dist/api/drawing tools/lines menu/parallelChannel.d.ts +4 -0
  94. package/dist/api/drawing tools/lines menu/parallelChannel.d.ts.map +1 -0
  95. package/dist/api/drawing tools/lines menu/parallelChannel.js +43 -0
  96. package/dist/api/drawing tools/lines menu/parallelChannel.js.map +1 -0
  97. package/dist/api/drawing tools/lines menu/pitchfork.d.ts +4 -0
  98. package/dist/api/drawing tools/lines menu/pitchfork.d.ts.map +1 -0
  99. package/dist/api/drawing tools/lines menu/pitchfork.js +12 -0
  100. package/dist/api/drawing tools/lines menu/pitchfork.js.map +1 -0
  101. package/dist/api/drawing tools/lines menu/ray.d.ts +4 -0
  102. package/dist/api/drawing tools/lines menu/ray.d.ts.map +1 -0
  103. package/dist/api/drawing tools/lines menu/ray.js +23 -0
  104. package/dist/api/drawing tools/lines menu/ray.js.map +1 -0
  105. package/dist/api/drawing tools/lines menu/regressionTrend.d.ts +4 -0
  106. package/dist/api/drawing tools/lines menu/regressionTrend.d.ts.map +1 -0
  107. package/dist/api/drawing tools/lines menu/regressionTrend.js +127 -0
  108. package/dist/api/drawing tools/lines menu/regressionTrend.js.map +1 -0
  109. package/dist/api/drawing tools/lines menu/schiffPitchfork.d.ts +4 -0
  110. package/dist/api/drawing tools/lines menu/schiffPitchfork.d.ts.map +1 -0
  111. package/dist/api/drawing tools/lines menu/schiffPitchfork.js +15 -0
  112. package/dist/api/drawing tools/lines menu/schiffPitchfork.js.map +1 -0
  113. package/dist/api/drawing tools/lines menu/trendAngle.d.ts +4 -0
  114. package/dist/api/drawing tools/lines menu/trendAngle.d.ts.map +1 -0
  115. package/dist/api/drawing tools/lines menu/trendAngle.js +51 -0
  116. package/dist/api/drawing tools/lines menu/trendAngle.js.map +1 -0
  117. package/dist/api/drawing tools/lines menu/trendline.d.ts +4 -0
  118. package/dist/api/drawing tools/lines menu/trendline.d.ts.map +1 -0
  119. package/dist/api/drawing tools/lines menu/trendline.js +11 -0
  120. package/dist/api/drawing tools/lines menu/trendline.js.map +1 -0
  121. package/dist/api/drawing tools/lines menu/vertical.d.ts +4 -0
  122. package/dist/api/drawing tools/lines menu/vertical.d.ts.map +1 -0
  123. package/dist/api/drawing tools/lines menu/vertical.js +11 -0
  124. package/dist/api/drawing tools/lines menu/vertical.js.map +1 -0
  125. package/dist/api/drawing tools/pointers menu/crosshair.d.ts +16 -0
  126. package/dist/api/drawing tools/pointers menu/crosshair.d.ts.map +1 -0
  127. package/{src/api/drawing tools/pointers menu/crosshair.ts → dist/api/drawing tools/pointers menu/crosshair.js } +6 -7
  128. package/dist/api/drawing tools/pointers menu/crosshair.js.map +1 -0
  129. package/dist/api/drawing tools/pointers menu/cursor.d.ts +15 -0
  130. package/dist/api/drawing tools/pointers menu/cursor.d.ts.map +1 -0
  131. package/{src/api/drawing tools/pointers menu/cursor.ts → dist/api/drawing tools/pointers menu/cursor.js } +7 -8
  132. package/dist/api/drawing tools/pointers menu/cursor.js.map +1 -0
  133. package/dist/api/drawing tools/pointers menu/demonstration.d.ts +30 -0
  134. package/dist/api/drawing tools/pointers menu/demonstration.d.ts.map +1 -0
  135. package/{src/api/drawing tools/pointers menu/demonstration.ts → dist/api/drawing tools/pointers menu/demonstration.js } +9 -14
  136. package/dist/api/drawing tools/pointers menu/demonstration.js.map +1 -0
  137. package/dist/api/drawing tools/pointers menu/dot.d.ts +23 -0
  138. package/dist/api/drawing tools/pointers menu/dot.d.ts.map +1 -0
  139. package/{src/api/drawing tools/pointers menu/dot.ts → dist/api/drawing tools/pointers menu/dot.js } +8 -11
  140. package/dist/api/drawing tools/pointers menu/dot.js.map +1 -0
  141. package/dist/api/drawing tools/shapes menu/rectangle.d.ts +4 -0
  142. package/dist/api/drawing tools/shapes menu/rectangle.d.ts.map +1 -0
  143. package/dist/api/drawing tools/shapes menu/rectangle.js +19 -0
  144. package/dist/api/drawing tools/shapes menu/rectangle.js.map +1 -0
  145. package/dist/api/drawing tools/shapes menu/text.d.ts +4 -0
  146. package/dist/api/drawing tools/shapes menu/text.d.ts.map +1 -0
  147. package/dist/api/drawing tools/shapes menu/text.js +25 -0
  148. package/dist/api/drawing tools/shapes menu/text.js.map +1 -0
  149. package/dist/api/drawingUtils.d.ts +22 -0
  150. package/dist/api/drawingUtils.d.ts.map +1 -0
  151. package/dist/api/drawingUtils.js +83 -0
  152. package/dist/api/drawingUtils.js.map +1 -0
  153. package/dist/core/CanvasLayer.d.ts +26 -0
  154. package/dist/core/CanvasLayer.d.ts.map +1 -0
  155. package/dist/core/CanvasLayer.js +56 -0
  156. package/dist/core/CanvasLayer.js.map +1 -0
  157. package/dist/core/Chart.d.ts +164 -0
  158. package/dist/core/Chart.d.ts.map +1 -0
  159. package/dist/core/Chart.js +839 -0
  160. package/dist/core/Chart.js.map +1 -0
  161. package/dist/core/CoordTransform.d.ts +168 -0
  162. package/dist/core/CoordTransform.d.ts.map +1 -0
  163. package/dist/core/CoordTransform.js +224 -0
  164. package/dist/core/CoordTransform.js.map +1 -0
  165. package/dist/core/Crosshair.d.ts +30 -0
  166. package/dist/core/Crosshair.d.ts.map +1 -0
  167. package/dist/core/Crosshair.js +186 -0
  168. package/dist/core/Crosshair.js.map +1 -0
  169. package/dist/core/IndicatorEngine.d.ts +51 -0
  170. package/dist/core/IndicatorEngine.d.ts.map +1 -0
  171. package/dist/core/IndicatorEngine.js +181 -0
  172. package/dist/core/IndicatorEngine.js.map +1 -0
  173. package/dist/core/InteractionManager.d.ts +197 -0
  174. package/dist/core/InteractionManager.d.ts.map +1 -0
  175. package/dist/core/InteractionManager.js +698 -0
  176. package/dist/core/InteractionManager.js.map +1 -0
  177. package/dist/core/PriceScale.d.ts +27 -0
  178. package/dist/core/PriceScale.d.ts.map +1 -0
  179. package/dist/core/PriceScale.js +113 -0
  180. package/dist/core/PriceScale.js.map +1 -0
  181. package/dist/core/Series.d.ts +40 -0
  182. package/dist/core/Series.d.ts.map +1 -0
  183. package/dist/core/Series.js +114 -0
  184. package/dist/core/Series.js.map +1 -0
  185. package/dist/core/TimeScale.d.ts +43 -0
  186. package/dist/core/TimeScale.d.ts.map +1 -0
  187. package/dist/core/TimeScale.js +150 -0
  188. package/dist/core/TimeScale.js.map +1 -0
  189. package/dist/datafeed/DatafeedConnector.d.ts +89 -0
  190. package/dist/datafeed/DatafeedConnector.d.ts.map +1 -0
  191. package/dist/datafeed/DatafeedConnector.js +268 -0
  192. package/dist/datafeed/DatafeedConnector.js.map +1 -0
  193. package/dist/engine/CandleEngine.d.ts +207 -0
  194. package/dist/engine/CandleEngine.d.ts.map +1 -0
  195. package/dist/engine/CandleEngine.js +318 -0
  196. package/dist/engine/CandleEngine.js.map +1 -0
  197. package/dist/engine/__tests__/CandleEngine.test.d.ts +2 -0
  198. package/dist/engine/__tests__/CandleEngine.test.d.ts.map +1 -0
  199. package/dist/engine/__tests__/CandleEngine.test.js +300 -0
  200. package/dist/engine/__tests__/CandleEngine.test.js.map +1 -0
  201. package/dist/engine/candleInvariants.d.ts +66 -0
  202. package/dist/engine/candleInvariants.d.ts.map +1 -0
  203. package/dist/engine/candleInvariants.js +134 -0
  204. package/dist/engine/candleInvariants.js.map +1 -0
  205. package/{src/engine/mergeUtils.ts → dist/engine/mergeUtils.d.ts} +15 -52
  206. package/dist/engine/mergeUtils.d.ts.map +1 -0
  207. package/dist/engine/mergeUtils.js +64 -0
  208. package/dist/engine/mergeUtils.js.map +1 -0
  209. package/dist/engine/timeframeUtils.d.ts +80 -0
  210. package/dist/engine/timeframeUtils.d.ts.map +1 -0
  211. package/{src/engine/timeframeUtils.ts → dist/engine/timeframeUtils.js} +30 -48
  212. package/dist/engine/timeframeUtils.js.map +1 -0
  213. package/dist/index.d.ts +40 -0
  214. package/dist/index.d.ts.map +1 -0
  215. package/dist/index.js +49 -0
  216. package/dist/index.js.map +1 -0
  217. package/dist/internal.d.ts +29 -0
  218. package/dist/internal.d.ts.map +1 -0
  219. package/{src/internal.ts → dist/internal.js} +2 -11
  220. package/dist/internal.js.map +1 -0
  221. package/dist/licensing/ChartRuntimeResolver.d.ts +233 -0
  222. package/dist/licensing/ChartRuntimeResolver.d.ts.map +1 -0
  223. package/dist/licensing/ChartRuntimeResolver.js +310 -0
  224. package/dist/licensing/ChartRuntimeResolver.js.map +1 -0
  225. package/dist/licensing/LicenseManager.d.ts +55 -0
  226. package/dist/licensing/LicenseManager.d.ts.map +1 -0
  227. package/dist/licensing/LicenseManager.js +114 -0
  228. package/dist/licensing/LicenseManager.js.map +1 -0
  229. package/dist/licensing/__tests__/ChartRuntimeResolver.test.d.ts +13 -0
  230. package/dist/licensing/__tests__/ChartRuntimeResolver.test.d.ts.map +1 -0
  231. package/dist/licensing/__tests__/ChartRuntimeResolver.test.js +177 -0
  232. package/dist/licensing/__tests__/ChartRuntimeResolver.test.js.map +1 -0
  233. package/dist/licensing/__tests__/LicenseManager.test.d.ts +12 -0
  234. package/dist/licensing/__tests__/LicenseManager.test.d.ts.map +1 -0
  235. package/dist/licensing/__tests__/LicenseManager.test.js +153 -0
  236. package/dist/licensing/__tests__/LicenseManager.test.js.map +1 -0
  237. package/dist/licensing/licenseTypes.d.ts +18 -0
  238. package/dist/licensing/licenseTypes.d.ts.map +1 -0
  239. package/dist/licensing/licenseTypes.js +2 -0
  240. package/dist/licensing/licenseTypes.js.map +1 -0
  241. package/dist/pine/PineCompiler.d.ts +35 -0
  242. package/dist/pine/PineCompiler.d.ts.map +1 -0
  243. package/dist/pine/PineCompiler.js +44 -0
  244. package/dist/pine/PineCompiler.js.map +1 -0
  245. package/dist/pine/diagnostics.d.ts +20 -0
  246. package/dist/pine/diagnostics.d.ts.map +1 -0
  247. package/dist/pine/diagnostics.js +11 -0
  248. package/dist/pine/diagnostics.js.map +1 -0
  249. package/{src/pine/index.ts → dist/pine/index.d.ts} +4 -3
  250. package/dist/pine/index.d.ts.map +1 -0
  251. package/dist/pine/index.js +5 -0
  252. package/dist/pine/index.js.map +1 -0
  253. package/dist/pine/pine-ast.d.ts +142 -0
  254. package/dist/pine/pine-ast.d.ts.map +1 -0
  255. package/dist/pine/pine-ast.js +19 -0
  256. package/dist/pine/pine-ast.js.map +1 -0
  257. package/dist/pine/pine-lexer.d.ts +41 -0
  258. package/dist/pine/pine-lexer.d.ts.map +1 -0
  259. package/dist/pine/pine-lexer.js +249 -0
  260. package/dist/pine/pine-lexer.js.map +1 -0
  261. package/dist/pine/pine-parser.d.ts +51 -0
  262. package/dist/pine/pine-parser.d.ts.map +1 -0
  263. package/dist/pine/pine-parser.js +416 -0
  264. package/dist/pine/pine-parser.js.map +1 -0
  265. package/dist/pine/pine-transpiler.d.ts +33 -0
  266. package/dist/pine/pine-transpiler.d.ts.map +1 -0
  267. package/dist/pine/pine-transpiler.js +260 -0
  268. package/dist/pine/pine-transpiler.js.map +1 -0
  269. package/dist/pixi/LayerName.d.ts +18 -0
  270. package/dist/pixi/LayerName.d.ts.map +1 -0
  271. package/dist/pixi/LayerName.js +35 -0
  272. package/dist/pixi/LayerName.js.map +1 -0
  273. package/dist/pixi/PixiCandlestickRenderer.d.ts +23 -0
  274. package/dist/pixi/PixiCandlestickRenderer.d.ts.map +1 -0
  275. package/dist/pixi/PixiCandlestickRenderer.js +107 -0
  276. package/dist/pixi/PixiCandlestickRenderer.js.map +1 -0
  277. package/dist/pixi/PixiChart.d.ts +72 -0
  278. package/dist/pixi/PixiChart.d.ts.map +1 -0
  279. package/dist/pixi/PixiChart.js +367 -0
  280. package/dist/pixi/PixiChart.js.map +1 -0
  281. package/dist/pixi/PixiCrosshairRenderer.d.ts +29 -0
  282. package/dist/pixi/PixiCrosshairRenderer.d.ts.map +1 -0
  283. package/dist/pixi/PixiCrosshairRenderer.js +110 -0
  284. package/dist/pixi/PixiCrosshairRenderer.js.map +1 -0
  285. package/dist/pixi/PixiDrawingRenderer.d.ts +17 -0
  286. package/dist/pixi/PixiDrawingRenderer.d.ts.map +1 -0
  287. package/dist/pixi/PixiDrawingRenderer.js +111 -0
  288. package/dist/pixi/PixiDrawingRenderer.js.map +1 -0
  289. package/dist/pixi/PixiGridRenderer.d.ts +22 -0
  290. package/dist/pixi/PixiGridRenderer.d.ts.map +1 -0
  291. package/dist/pixi/PixiGridRenderer.js +114 -0
  292. package/dist/pixi/PixiGridRenderer.js.map +1 -0
  293. package/dist/pixi/PixiLayerManager.d.ts +56 -0
  294. package/dist/pixi/PixiLayerManager.d.ts.map +1 -0
  295. package/dist/pixi/PixiLayerManager.js +92 -0
  296. package/dist/pixi/PixiLayerManager.js.map +1 -0
  297. package/dist/react/canvas/ChartCanvas.d.ts +85 -0
  298. package/dist/react/canvas/ChartCanvas.d.ts.map +1 -0
  299. package/dist/react/canvas/ChartCanvas.js +604 -0
  300. package/dist/react/canvas/ChartCanvas.js.map +1 -0
  301. package/dist/react/canvas/ChartContextMenu.d.ts +18 -0
  302. package/dist/react/canvas/ChartContextMenu.d.ts.map +1 -0
  303. package/dist/react/canvas/ChartContextMenu.js +5 -0
  304. package/dist/react/canvas/ChartContextMenu.js.map +1 -0
  305. package/dist/react/canvas/ChartSettingsDialog.d.ts +25 -0
  306. package/dist/react/canvas/ChartSettingsDialog.d.ts.map +1 -0
  307. package/dist/react/canvas/ChartSettingsDialog.js +28 -0
  308. package/dist/react/canvas/ChartSettingsDialog.js.map +1 -0
  309. package/dist/react/canvas/IndicatorLabel.d.ts +21 -0
  310. package/dist/react/canvas/IndicatorLabel.d.ts.map +1 -0
  311. package/dist/react/canvas/IndicatorLabel.js +196 -0
  312. package/dist/react/canvas/IndicatorLabel.js.map +1 -0
  313. package/dist/react/canvas/IndicatorPane.d.ts +32 -0
  314. package/dist/react/canvas/IndicatorPane.d.ts.map +1 -0
  315. package/dist/react/canvas/IndicatorPane.js +395 -0
  316. package/dist/react/canvas/IndicatorPane.js.map +1 -0
  317. package/dist/react/canvas/PointerOverlay.d.ts +23 -0
  318. package/dist/react/canvas/PointerOverlay.d.ts.map +1 -0
  319. package/dist/react/canvas/PointerOverlay.js +61 -0
  320. package/dist/react/canvas/PointerOverlay.js.map +1 -0
  321. package/dist/react/canvas/toolbars/LeftToolbar.d.ts +19 -0
  322. package/dist/react/canvas/toolbars/LeftToolbar.d.ts.map +1 -0
  323. package/dist/react/canvas/toolbars/LeftToolbar.js +407 -0
  324. package/dist/react/canvas/toolbars/LeftToolbar.js.map +1 -0
  325. package/dist/react/hooks/useChartCapabilities.d.ts +21 -0
  326. package/dist/react/hooks/useChartCapabilities.d.ts.map +1 -0
  327. package/dist/react/hooks/useChartCapabilities.js +66 -0
  328. package/dist/react/hooks/useChartCapabilities.js.map +1 -0
  329. package/dist/react/index.d.ts +30 -0
  330. package/dist/react/index.d.ts.map +1 -0
  331. package/dist/react/index.js +28 -0
  332. package/dist/react/index.js.map +1 -0
  333. package/dist/react/internal.d.ts +38 -0
  334. package/dist/react/internal.d.ts.map +1 -0
  335. package/dist/react/internal.js +44 -0
  336. package/dist/react/internal.js.map +1 -0
  337. package/dist/react/shell/ManagedAppShell.d.ts +91 -0
  338. package/dist/react/shell/ManagedAppShell.d.ts.map +1 -0
  339. package/dist/react/shell/ManagedAppShell.js +440 -0
  340. package/dist/react/shell/ManagedAppShell.js.map +1 -0
  341. package/dist/react/trading/TradingBridge.d.ts +86 -0
  342. package/dist/react/trading/TradingBridge.d.ts.map +1 -0
  343. package/dist/react/trading/TradingBridge.js +73 -0
  344. package/dist/react/trading/TradingBridge.js.map +1 -0
  345. package/dist/react/workspace/ChartWorkspace.d.ts +73 -0
  346. package/dist/react/workspace/ChartWorkspace.d.ts.map +1 -0
  347. package/dist/react/workspace/ChartWorkspace.js +42 -0
  348. package/dist/react/workspace/ChartWorkspace.js.map +1 -0
  349. package/dist/react/workspace/FloatingPanel.d.ts +18 -0
  350. package/dist/react/workspace/FloatingPanel.d.ts.map +1 -0
  351. package/dist/react/workspace/FloatingPanel.js +82 -0
  352. package/dist/react/workspace/FloatingPanel.js.map +1 -0
  353. package/dist/react/workspace/IndicatorsDialog.d.ts +8 -0
  354. package/dist/react/workspace/IndicatorsDialog.d.ts.map +1 -0
  355. package/dist/react/workspace/IndicatorsDialog.js +121 -0
  356. package/dist/react/workspace/IndicatorsDialog.js.map +1 -0
  357. package/dist/react/workspace/LayoutMenu.d.ts +33 -0
  358. package/dist/react/workspace/LayoutMenu.d.ts.map +1 -0
  359. package/dist/react/workspace/LayoutMenu.js +113 -0
  360. package/dist/react/workspace/LayoutMenu.js.map +1 -0
  361. package/dist/react/workspace/SymbolSearchDialog.d.ts +10 -0
  362. package/dist/react/workspace/SymbolSearchDialog.d.ts.map +1 -0
  363. package/dist/react/workspace/SymbolSearchDialog.js +245 -0
  364. package/dist/react/workspace/SymbolSearchDialog.js.map +1 -0
  365. package/dist/react/workspace/TabBar.d.ts +17 -0
  366. package/dist/react/workspace/TabBar.d.ts.map +1 -0
  367. package/dist/react/workspace/TabBar.js +29 -0
  368. package/dist/react/workspace/TabBar.js.map +1 -0
  369. package/dist/react/workspace/toolbars/BottomToolbar.d.ts +19 -0
  370. package/dist/react/workspace/toolbars/BottomToolbar.d.ts.map +1 -0
  371. package/dist/react/workspace/toolbars/BottomToolbar.js +236 -0
  372. package/dist/react/workspace/toolbars/BottomToolbar.js.map +1 -0
  373. package/dist/react/workspace/toolbars/RightToolbar.d.ts +8 -0
  374. package/dist/react/workspace/toolbars/RightToolbar.d.ts.map +1 -0
  375. package/dist/react/workspace/toolbars/RightToolbar.js +18 -0
  376. package/dist/react/workspace/toolbars/RightToolbar.js.map +1 -0
  377. package/dist/react/workspace/toolbars/TopToolbar.d.ts +41 -0
  378. package/dist/react/workspace/toolbars/TopToolbar.d.ts.map +1 -0
  379. package/dist/react/workspace/toolbars/TopToolbar.js +82 -0
  380. package/dist/react/workspace/toolbars/TopToolbar.js.map +1 -0
  381. package/dist/renderers/CandlestickRenderer.d.ts +13 -0
  382. package/dist/renderers/CandlestickRenderer.d.ts.map +1 -0
  383. package/dist/renderers/CandlestickRenderer.js +98 -0
  384. package/dist/renderers/CandlestickRenderer.js.map +1 -0
  385. package/dist/renderers/HistogramRenderer.d.ts +11 -0
  386. package/dist/renderers/HistogramRenderer.d.ts.map +1 -0
  387. package/dist/renderers/HistogramRenderer.js +50 -0
  388. package/dist/renderers/HistogramRenderer.js.map +1 -0
  389. package/dist/renderers/LineRenderer.d.ts +12 -0
  390. package/dist/renderers/LineRenderer.d.ts.map +1 -0
  391. package/dist/renderers/LineRenderer.js +64 -0
  392. package/dist/renderers/LineRenderer.js.map +1 -0
  393. package/dist/theme/colors.d.ts +4 -0
  394. package/dist/theme/colors.d.ts.map +1 -0
  395. package/dist/theme/colors.js +19 -0
  396. package/dist/theme/colors.js.map +1 -0
  397. package/dist/tools/barDivergenceCheck.d.ts +120 -0
  398. package/dist/tools/barDivergenceCheck.d.ts.map +1 -0
  399. package/dist/tools/barDivergenceCheck.js +200 -0
  400. package/dist/tools/barDivergenceCheck.js.map +1 -0
  401. package/dist/trading/TradingOverlayStore.d.ts +86 -0
  402. package/dist/trading/TradingOverlayStore.d.ts.map +1 -0
  403. package/dist/trading/TradingOverlayStore.js +139 -0
  404. package/dist/trading/TradingOverlayStore.js.map +1 -0
  405. package/dist/trading/UnmanagedIngestion.d.ts +91 -0
  406. package/dist/trading/UnmanagedIngestion.d.ts.map +1 -0
  407. package/dist/trading/UnmanagedIngestion.js +114 -0
  408. package/dist/trading/UnmanagedIngestion.js.map +1 -0
  409. package/dist/trading/__tests__/ManagedTradingController.test.d.ts +18 -0
  410. package/dist/trading/__tests__/ManagedTradingController.test.d.ts.map +1 -0
  411. package/dist/trading/__tests__/ManagedTradingController.test.js +271 -0
  412. package/dist/trading/__tests__/ManagedTradingController.test.js.map +1 -0
  413. package/dist/trading/__tests__/TradingOverlayStore.test.d.ts +16 -0
  414. package/dist/trading/__tests__/TradingOverlayStore.test.d.ts.map +1 -0
  415. package/dist/trading/__tests__/TradingOverlayStore.test.js +267 -0
  416. package/dist/trading/__tests__/TradingOverlayStore.test.js.map +1 -0
  417. package/dist/trading/__tests__/UnmanagedIngestion.test.d.ts +16 -0
  418. package/dist/trading/__tests__/UnmanagedIngestion.test.d.ts.map +1 -0
  419. package/dist/trading/__tests__/UnmanagedIngestion.test.js +170 -0
  420. package/dist/trading/__tests__/UnmanagedIngestion.test.js.map +1 -0
  421. package/dist/trading/managed/ManagedTradingController.d.ts +110 -0
  422. package/dist/trading/managed/ManagedTradingController.d.ts.map +1 -0
  423. package/dist/trading/managed/ManagedTradingController.js +247 -0
  424. package/dist/trading/managed/ManagedTradingController.js.map +1 -0
  425. package/dist/trading/managed/managedCapabilities.d.ts +45 -0
  426. package/dist/trading/managed/managedCapabilities.d.ts.map +1 -0
  427. package/dist/trading/managed/managedCapabilities.js +79 -0
  428. package/dist/trading/managed/managedCapabilities.js.map +1 -0
  429. package/dist/trading/managed/managedTypes.d.ts +122 -0
  430. package/dist/trading/managed/managedTypes.d.ts.map +1 -0
  431. package/dist/trading/managed/managedTypes.js +13 -0
  432. package/dist/trading/managed/managedTypes.js.map +1 -0
  433. package/dist/trading/tradingTypes.d.ts +89 -0
  434. package/dist/trading/tradingTypes.d.ts.map +1 -0
  435. package/dist/trading/tradingTypes.js +8 -0
  436. package/dist/trading/tradingTypes.js.map +1 -0
  437. package/dist/tscript/TScriptIndicator.d.ts +41 -0
  438. package/dist/tscript/TScriptIndicator.d.ts.map +1 -0
  439. package/dist/tscript/TScriptIndicator.js +47 -0
  440. package/dist/tscript/TScriptIndicator.js.map +1 -0
  441. package/dist/tscript/ast.d.ts +89 -0
  442. package/dist/tscript/ast.d.ts.map +1 -0
  443. package/dist/tscript/ast.js +22 -0
  444. package/dist/tscript/ast.js.map +1 -0
  445. package/dist/tscript/lexer.d.ts +36 -0
  446. package/dist/tscript/lexer.d.ts.map +1 -0
  447. package/dist/tscript/lexer.js +187 -0
  448. package/dist/tscript/lexer.js.map +1 -0
  449. package/dist/tscript/parser.d.ts +50 -0
  450. package/dist/tscript/parser.d.ts.map +1 -0
  451. package/dist/tscript/parser.js +318 -0
  452. package/dist/tscript/parser.js.map +1 -0
  453. package/dist/tscript/runtime.d.ts +123 -0
  454. package/dist/tscript/runtime.d.ts.map +1 -0
  455. package/dist/tscript/runtime.js +475 -0
  456. package/dist/tscript/runtime.js.map +1 -0
  457. package/dist/tscript/series.d.ts +49 -0
  458. package/dist/tscript/series.d.ts.map +1 -0
  459. package/dist/tscript/series.js +79 -0
  460. package/dist/tscript/series.js.map +1 -0
  461. package/dist/types/IChart.d.ts +48 -0
  462. package/dist/types/IChart.d.ts.map +1 -0
  463. package/dist/types/IChart.js +2 -0
  464. package/dist/types/IChart.js.map +1 -0
  465. package/{src/types/IRenderer.ts → dist/types/IRenderer.d.ts} +2 -8
  466. package/dist/types/IRenderer.d.ts.map +1 -0
  467. package/dist/types/IRenderer.js +2 -0
  468. package/dist/types/IRenderer.js.map +1 -0
  469. package/dist/types/ISeries.d.ts +26 -0
  470. package/dist/types/ISeries.d.ts.map +1 -0
  471. package/dist/types/ISeries.js +2 -0
  472. package/dist/types/ISeries.js.map +1 -0
  473. package/package.json +32 -4
  474. package/src/__tests__/backwardCompatibility.test.ts +0 -191
  475. package/src/__tests__/candleInvariant.test.ts +0 -500
  476. package/src/__tests__/timeframeBoundary.test.ts +0 -583
  477. package/src/api/DrawingManager.ts +0 -188
  478. package/src/api/EventBus.ts +0 -53
  479. package/src/api/IndicatorDAG.ts +0 -389
  480. package/src/api/IndicatorRegistry.ts +0 -47
  481. package/src/api/LayoutManager.ts +0 -72
  482. package/src/api/PaneManager.ts +0 -129
  483. package/src/api/ReferenceAPI.ts +0 -195
  484. package/src/api/TChart.ts +0 -881
  485. package/src/api/drawing tools/fib gann menu/fibRetracement.ts +0 -27
  486. package/src/api/drawing tools/lines menu/crossLine.ts +0 -21
  487. package/src/api/drawing tools/lines menu/disjointChannel.ts +0 -74
  488. package/src/api/drawing tools/lines menu/extendedLine.ts +0 -22
  489. package/src/api/drawing tools/lines menu/flatTopBottom.ts +0 -45
  490. package/src/api/drawing tools/lines menu/horizontal.ts +0 -24
  491. package/src/api/drawing tools/lines menu/horizontalRay.ts +0 -25
  492. package/src/api/drawing tools/lines menu/infoLine.ts +0 -127
  493. package/src/api/drawing tools/lines menu/insidePitchfork.ts +0 -21
  494. package/src/api/drawing tools/lines menu/modifiedSchiffPitchfork.ts +0 -18
  495. package/src/api/drawing tools/lines menu/parallelChannel.ts +0 -47
  496. package/src/api/drawing tools/lines menu/pitchfork.ts +0 -15
  497. package/src/api/drawing tools/lines menu/ray.ts +0 -28
  498. package/src/api/drawing tools/lines menu/regressionTrend.ts +0 -157
  499. package/src/api/drawing tools/lines menu/schiffPitchfork.ts +0 -18
  500. package/src/api/drawing tools/lines menu/trendAngle.ts +0 -64
  501. package/src/api/drawing tools/lines menu/trendline.ts +0 -16
  502. package/src/api/drawing tools/lines menu/vertical.ts +0 -16
  503. package/src/api/drawing tools/shapes menu/rectangle.ts +0 -24
  504. package/src/api/drawing tools/shapes menu/text.ts +0 -30
  505. package/src/api/drawingUtils.ts +0 -82
  506. package/src/core/CanvasLayer.ts +0 -77
  507. package/src/core/Chart.ts +0 -917
  508. package/src/core/CoordTransform.ts +0 -282
  509. package/src/core/Crosshair.ts +0 -207
  510. package/src/core/IndicatorEngine.ts +0 -216
  511. package/src/core/InteractionManager.ts +0 -899
  512. package/src/core/PriceScale.ts +0 -133
  513. package/src/core/Series.ts +0 -132
  514. package/src/core/TimeScale.ts +0 -175
  515. package/src/datafeed/DatafeedConnector.ts +0 -300
  516. package/src/engine/CandleEngine.ts +0 -458
  517. package/src/engine/__tests__/CandleEngine.test.ts +0 -402
  518. package/src/engine/candleInvariants.ts +0 -172
  519. package/src/index.ts +0 -190
  520. package/src/licensing/ChartRuntimeResolver.ts +0 -380
  521. package/src/licensing/LicenseManager.ts +0 -131
  522. package/src/licensing/__tests__/ChartRuntimeResolver.test.ts +0 -207
  523. package/src/licensing/__tests__/LicenseManager.test.ts +0 -180
  524. package/src/licensing/licenseTypes.ts +0 -19
  525. package/src/pine/PineCompiler.ts +0 -68
  526. package/src/pine/diagnostics.ts +0 -30
  527. package/src/pine/pine-ast.ts +0 -163
  528. package/src/pine/pine-lexer.ts +0 -265
  529. package/src/pine/pine-parser.ts +0 -439
  530. package/src/pine/pine-transpiler.ts +0 -301
  531. package/src/pixi/LayerName.ts +0 -35
  532. package/src/pixi/PixiCandlestickRenderer.ts +0 -125
  533. package/src/pixi/PixiChart.ts +0 -425
  534. package/src/pixi/PixiCrosshairRenderer.ts +0 -134
  535. package/src/pixi/PixiDrawingRenderer.ts +0 -121
  536. package/src/pixi/PixiGridRenderer.ts +0 -136
  537. package/src/pixi/PixiLayerManager.ts +0 -102
  538. package/src/renderers/CandlestickRenderer.ts +0 -130
  539. package/src/renderers/HistogramRenderer.ts +0 -63
  540. package/src/renderers/LineRenderer.ts +0 -77
  541. package/src/theme/colors.ts +0 -21
  542. package/src/tools/barDivergenceCheck.ts +0 -305
  543. package/src/trading/TradingOverlayStore.ts +0 -161
  544. package/src/trading/UnmanagedIngestion.ts +0 -156
  545. package/src/trading/__tests__/ManagedTradingController.test.ts +0 -338
  546. package/src/trading/__tests__/TradingOverlayStore.test.ts +0 -323
  547. package/src/trading/__tests__/UnmanagedIngestion.test.ts +0 -205
  548. package/src/trading/managed/ManagedTradingController.ts +0 -292
  549. package/src/trading/managed/managedCapabilities.ts +0 -98
  550. package/src/trading/managed/managedTypes.ts +0 -151
  551. package/src/trading/tradingTypes.ts +0 -135
  552. package/src/tscript/TScriptIndicator.ts +0 -54
  553. package/src/tscript/ast.ts +0 -105
  554. package/src/tscript/lexer.ts +0 -190
  555. package/src/tscript/parser.ts +0 -334
  556. package/src/tscript/runtime.ts +0 -525
  557. package/src/tscript/series.ts +0 -84
  558. package/src/types/IChart.ts +0 -56
  559. package/src/types/ISeries.ts +0 -30
  560. package/tsconfig.json +0 -22
  561. package/tsup.config.ts +0 -15
  562. package/vitest.config.ts +0 -25
@@ -0,0 +1,839 @@
1
+ import { CanvasLayer } from './CanvasLayer';
2
+ import { TimeScale } from './TimeScale';
3
+ import { PriceScale } from './PriceScale';
4
+ import { CoordTransform } from './CoordTransform';
5
+ import { Crosshair } from './Crosshair';
6
+ import { Series } from './Series';
7
+ import { InteractionManager } from './InteractionManager';
8
+ import { DrawingManager } from '../api/DrawingManager';
9
+ import { DARK_COLORS, LIGHT_COLORS } from '../theme/colors';
10
+ // ─── Last-price helpers (module-level) ────────────────────────────────────────
11
+ const _TF_SECONDS = {
12
+ '1s': 1, '5s': 5, '10s': 10, '30s': 30,
13
+ '1m': 60, '3m': 180, '5m': 300, '15m': 900, '30m': 1800,
14
+ '1h': 3600, '2h': 7200, '4h': 14400, '6h': 21600, '12h': 43200,
15
+ '1d': 86400, '3d': 259200, '1w': 604800, '1M': 2592000,
16
+ };
17
+ function _tfToSeconds(tf) {
18
+ return _TF_SECONDS[tf] ?? 3600;
19
+ }
20
+ function _formatLastPrice(price) {
21
+ const decimals = price < 1 ? 6 : price < 1000 ? 4 : 2;
22
+ return price.toFixed(decimals);
23
+ }
24
+ function _formatCountdown(secs) {
25
+ const h = Math.floor(secs / 3600);
26
+ const m = Math.floor((secs % 3600) / 60);
27
+ const s = secs % 60;
28
+ if (h > 0)
29
+ return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
30
+ return `${m}:${String(s).padStart(2, '0')}`;
31
+ }
32
+ /**
33
+ * Chart — entry point for the ForgeCharts SDK.
34
+ *
35
+ * Manages the canvas layer stack, time/price scales, all series,
36
+ * and the interaction model. Uses the browser Canvas 2D API directly;
37
+ * no third-party chart library dependencies.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * const chart = new Chart(containerEl, { theme: 'dark' });
42
+ * const series = chart.addSeries({ type: 'candlestick' });
43
+ * series.setData(ohlcvArray);
44
+ * ```
45
+ */
46
+ export class Chart {
47
+ _container;
48
+ _options;
49
+ _colors;
50
+ // Canvas layers (back → front): grid, series, overlay
51
+ _gridLayer;
52
+ _seriesLayer;
53
+ _overlayLayer;
54
+ _timeScale;
55
+ _priceScale;
56
+ _transform;
57
+ _crosshair;
58
+ _series = [];
59
+ _plugins = [];
60
+ _animationFrame = null;
61
+ _dirty = true;
62
+ _indicatorsVisible = true;
63
+ /** When true the user has manually adjusted the price scale; auto-fit is suspended. */
64
+ _priceScaleManual = false;
65
+ /** Active timeframe — used for last-price countdown. */
66
+ _interval = '1h';
67
+ /** Last second at which we ticked the countdown to force a re-render. */
68
+ _lastCountdownSec = 0;
69
+ _resizeObserver;
70
+ _interaction;
71
+ // ── Drawing system ───────────────────────────────────────────────────────────────
72
+ _drawingMgr;
73
+ _drawingTool = null;
74
+ _drawingState = 'idle';
75
+ _drawingP0 = null;
76
+ _drawingP1 = null;
77
+ _drawingCursorPt = null;
78
+ /** When false the crosshair is suppressed (e.g. Arrow/cursor mode). */
79
+ _crosshairEnabled = true;
80
+ /** Called whenever a drawing is committed (created or updated). */
81
+ onDrawingCommitted;
82
+ /** Called whenever a drawing is deleted. */
83
+ onDrawingDeleted;
84
+ /** Called when the user right-clicks a drawing. x/y are canvas-relative pixels. */
85
+ onDrawingContextMenu;
86
+ /**
87
+ * Called after every pan or zoom interaction so external code (e.g. TChart)
88
+ * can check whether the visible time range now extends past the oldest
89
+ * loaded bar and trigger a lazy history fetch.
90
+ */
91
+ onViewportChanged;
92
+ constructor(container, options = {}) {
93
+ this._container = container;
94
+ this._container.style.position = 'relative';
95
+ this._container.style.overflow = 'hidden';
96
+ this._options = this._resolveOptions(options);
97
+ this._colors = this._resolveColors(this._options.theme, this._options.colors);
98
+ const { width, height } = container.getBoundingClientRect();
99
+ const dpr = window.devicePixelRatio ?? 1;
100
+ this._gridLayer = new CanvasLayer(container, { width, height, dpr, zIndex: 1 });
101
+ this._seriesLayer = new CanvasLayer(container, { width, height, dpr, zIndex: 2 });
102
+ this._overlayLayer = new CanvasLayer(container, { width, height, dpr, zIndex: 3 });
103
+ this._timeScale = new TimeScale(this._gridLayer, this._colors, this._options.timeScale);
104
+ this._priceScale = new PriceScale(this._gridLayer, this._colors, this._options.priceScale);
105
+ // CoordTransform is the single source of truth for all pixel ↔ data conversions.
106
+ // Created after the scales so it can hold live references to them.
107
+ this._transform = new CoordTransform(this._timeScale, this._priceScale, this._priceScale.width, this._timeScale.height);
108
+ this._transform.update(width, height);
109
+ this._crosshair = new Crosshair(this._overlayLayer, this._colors, this._options, this._transform);
110
+ // Propagate initial timezone to time axis and crosshair
111
+ if (this._options.timezone) {
112
+ this._timeScale.timezone = this._options.timezone;
113
+ this._crosshair.timezone = this._options.timezone;
114
+ }
115
+ this._drawingMgr = new DrawingManager();
116
+ this._interaction = new InteractionManager(this._overlayLayer.canvas, this._transform, {
117
+ onPan: (dx, dy) => {
118
+ this._transform.pan(dx, dy);
119
+ this._dirty = true;
120
+ this.onViewportChanged?.();
121
+ },
122
+ onZoom: (factor, originX) => {
123
+ this._transform.zoomTime(factor, originX);
124
+ this._dirty = true;
125
+ this.onViewportChanged?.();
126
+ },
127
+ onCrosshairMove: (x, y) => {
128
+ if (!this._crosshairEnabled)
129
+ return;
130
+ // Snap the vertical line to the nearest bar's timestamp so it always
131
+ // sits centred on a candle rather than floating between candles.
132
+ const { x: snappedX, time: snappedTime } = this._snapXToBar(x);
133
+ this._crosshair.update(snappedX, y, snappedTime);
134
+ this._dirty = true;
135
+ },
136
+ onCrosshairHide: () => {
137
+ this._crosshair.hide();
138
+ this._dirty = true;
139
+ },
140
+ onKeyAction: (action) => {
141
+ this._handleKeyAction(action);
142
+ },
143
+ onFitContent: () => {
144
+ this.scrollToEnd();
145
+ },
146
+ onPriceScaleZoom: (factor, originY) => {
147
+ this._priceScaleManual = true;
148
+ this._transform.zoomPrice(factor, originY);
149
+ this._dirty = true;
150
+ },
151
+ onPriceAxisDrag: (dy) => {
152
+ this._priceScaleManual = true;
153
+ // Exponential factor: drag down (dy > 0) = expand range, up = compress
154
+ this._transform.zoomPrice(Math.pow(1.005, dy), this._transform.plotHeight / 2);
155
+ this._dirty = true;
156
+ },
157
+ // Drawing tool callbacks
158
+ onDrawClick: (x, y) => {
159
+ this._handleDrawClick(x, y);
160
+ },
161
+ onDrawPointerMove: (x, y) => {
162
+ this._drawingCursorPt = {
163
+ time: this._transform.xToTime(x),
164
+ price: this._transform.yToPrice(y),
165
+ };
166
+ this._dirty = true;
167
+ },
168
+ onHandleDragStart: (_id, _hi) => {
169
+ this._dirty = true;
170
+ },
171
+ onHandleDragMove: (id, handleIndex, x, y) => {
172
+ const drawing = this._drawingMgr.get(id);
173
+ if (!drawing)
174
+ return;
175
+ const snapped = this._snapToBar(x, y);
176
+ const newPoints = [...drawing.points];
177
+ newPoints[handleIndex] = snapped;
178
+ this._drawingMgr.update(id, { points: newPoints });
179
+ this._dirty = true;
180
+ },
181
+ onHandleDragEnd: (id, _hi) => {
182
+ const drawing = this._drawingMgr.get(id);
183
+ if (drawing)
184
+ this.onDrawingCommitted?.(drawing);
185
+ this._dirty = true;
186
+ },
187
+ onBodyMoveStart: (_id) => {
188
+ this._dirty = true;
189
+ },
190
+ onBodyMoveMove: (id, dx, dy) => {
191
+ const drawing = this._drawingMgr.get(id);
192
+ if (!drawing)
193
+ return;
194
+ const t = this._transform;
195
+ const newPoints = drawing.points.map((p) => ({
196
+ time: t.xToTime(t.timeToX(p.time) + dx),
197
+ price: t.yToPrice(t.priceToY(p.price) + dy),
198
+ }));
199
+ this._drawingMgr.update(id, { points: newPoints });
200
+ this._dirty = true;
201
+ },
202
+ onBodyMoveEnd: (id) => {
203
+ const drawing = this._drawingMgr.get(id);
204
+ if (drawing)
205
+ this.onDrawingCommitted?.(drawing);
206
+ this._dirty = true;
207
+ },
208
+ onContextMenu: (x, y, hit) => {
209
+ // Right-click while a drawing tool is active cancels placement.
210
+ if (this._drawingTool !== null) {
211
+ this.cancelDrawingTool();
212
+ return;
213
+ }
214
+ if (hit.kind === 'drawing') {
215
+ this.onDrawingContextMenu?.(hit.id, x, y);
216
+ }
217
+ },
218
+ }, {
219
+ enablePan: this._options.handleScroll,
220
+ enableZoom: this._options.handleScale,
221
+ });
222
+ this._resizeObserver = new ResizeObserver(() => this._onResize());
223
+ this._resizeObserver.observe(container);
224
+ this._scheduleRender();
225
+ }
226
+ // ─── Public API ──────────────────────────────────────────────────────────────
227
+ addSeries(options) {
228
+ const series = new Series(options, this._colors);
229
+ // Wire live-tick repaints: whenever series data changes (WS tick calls
230
+ // series.update()), immediately mark the canvas dirty so the forming bar
231
+ // and last-price label repaint on the very next RAF frame — not once/second.
232
+ series.onDataChanged = () => { this._dirty = true; };
233
+ this._series.push(series);
234
+ this._dirty = true;
235
+ return series;
236
+ }
237
+ removeSeries(series) {
238
+ this._series = this._series.filter((s) => s !== series);
239
+ this._dirty = true;
240
+ }
241
+ addPlugin(plugin) {
242
+ this._plugins.push(plugin);
243
+ plugin.onAttach(this);
244
+ }
245
+ removePlugin(plugin) {
246
+ this._plugins = this._plugins.filter((p) => p !== plugin);
247
+ plugin.onDetach();
248
+ }
249
+ /** Set the active timeframe so the last-price countdown is accurate. */
250
+ setInterval(tf) {
251
+ this._interval = tf;
252
+ this._crosshair.interval = tf;
253
+ this._timeScale.setTimeframe(tf);
254
+ this._dirty = true;
255
+ }
256
+ timeScale() {
257
+ return this._timeScale;
258
+ }
259
+ priceScale() {
260
+ return this._priceScale;
261
+ }
262
+ applyOptions(options) {
263
+ Object.assign(this._options, options);
264
+ if (options.timezone !== undefined) {
265
+ this._timeScale.timezone = options.timezone;
266
+ this._crosshair.timezone = options.timezone;
267
+ }
268
+ if (options.colors !== undefined || options.theme !== undefined) {
269
+ const fresh = this._resolveColors(this._options.theme, this._options.colors);
270
+ Object.assign(this._colors, fresh);
271
+ }
272
+ this._dirty = true;
273
+ }
274
+ /** Pans the viewport so the latest bar is visible at the right edge. */
275
+ scrollToEnd() {
276
+ this._scrollToLatestBar();
277
+ this._dirty = true;
278
+ }
279
+ /** Returns the coordinate transform for this chart. */
280
+ transform() {
281
+ return this._transform;
282
+ }
283
+ resize(width, height) {
284
+ const dpr = window.devicePixelRatio ?? 1;
285
+ this._gridLayer.resize(width, height, dpr);
286
+ this._seriesLayer.resize(width, height, dpr);
287
+ this._overlayLayer.resize(width, height, dpr);
288
+ this._transform.update(width, height);
289
+ // Repaint synchronously so the canvas is never left blank between the
290
+ // clear (caused by assigning canvas.width/height) and the next RAF tick.
291
+ this._dirty = true;
292
+ this._render();
293
+ }
294
+ destroy() {
295
+ if (this._animationFrame !== null)
296
+ cancelAnimationFrame(this._animationFrame);
297
+ this._resizeObserver.disconnect();
298
+ this._interaction.destroy();
299
+ this._gridLayer.destroy();
300
+ this._seriesLayer.destroy();
301
+ this._overlayLayer.destroy();
302
+ this._crosshair.destroy();
303
+ this._plugins.forEach((p) => p.onDetach());
304
+ this._series = [];
305
+ this._plugins = [];
306
+ }
307
+ // ─── Rendering ───────────────────────────────────────────────────────────────
308
+ _scheduleRender() {
309
+ this._animationFrame = requestAnimationFrame(() => {
310
+ // Tick the countdown once per second so the label stays current.
311
+ const nowSec = Math.floor(Date.now() / 1000);
312
+ if (this._series.length > 0 && nowSec !== this._lastCountdownSec) {
313
+ this._lastCountdownSec = nowSec;
314
+ this._dirty = true;
315
+ }
316
+ this._render();
317
+ this._scheduleRender();
318
+ });
319
+ }
320
+ _render() {
321
+ if (!this._dirty)
322
+ return;
323
+ this._dirty = false;
324
+ // Auto-fit the price scale to the currently visible bars every frame.
325
+ // This keeps the candles in view after panning/zooming the time axis.
326
+ this._autoFitPriceToData();
327
+ this._renderGrid();
328
+ this._renderSeries();
329
+ this._renderOverlay();
330
+ this._plugins.forEach((p) => p.onRender());
331
+ }
332
+ _renderGrid() {
333
+ const ctx = this._gridLayer.context;
334
+ const { width, height } = this._gridLayer;
335
+ ctx.clearRect(0, 0, width, height);
336
+ // Background
337
+ ctx.fillStyle = this._colors.background;
338
+ ctx.fillRect(0, 0, width, height);
339
+ this._timeScale.render(ctx, width, height);
340
+ this._priceScale.render(ctx, width, height);
341
+ }
342
+ setAllDrawingsVisible(v) {
343
+ for (const d of this._drawingMgr.all()) {
344
+ this._drawingMgr.update(d.id, { visible: v });
345
+ }
346
+ this._dirty = true;
347
+ }
348
+ setIndicatorsVisible(v) {
349
+ this._indicatorsVisible = v;
350
+ this._dirty = true;
351
+ }
352
+ _renderSeries() {
353
+ const ctx = this._seriesLayer.context;
354
+ const { width, height } = this._seriesLayer;
355
+ ctx.clearRect(0, 0, width, height);
356
+ if (!this._indicatorsVisible)
357
+ return;
358
+ const viewport = this._computeViewport();
359
+ for (const series of this._series) {
360
+ series.render(ctx, viewport, { x: 0, y: 0, width, height });
361
+ }
362
+ }
363
+ _renderOverlay() {
364
+ const ctx = this._overlayLayer.context;
365
+ const { width, height } = this._overlayLayer;
366
+ ctx.clearRect(0, 0, width, height);
367
+ // Committed drawings
368
+ const selectedId = this._interaction.selectedDrawingId;
369
+ const candles = this._series[0]?.data() ?? [];
370
+ this._drawingMgr.render(ctx, this._transform, selectedId, this._interval, candles);
371
+ this._interaction.setDrawings(this._drawingMgr.all());
372
+ // In-progress placement preview
373
+ if (this._drawingTool !== null && this._drawingCursorPt !== null) {
374
+ const draft = this._buildDraftPreview();
375
+ if (draft)
376
+ this._drawingMgr.renderPreview(ctx, this._transform, draft, this._interval, candles);
377
+ }
378
+ // Last-price dotted line + countdown
379
+ this._renderLastPriceLine(ctx);
380
+ this._crosshair.render(ctx, width, height);
381
+ }
382
+ // ─── Private helpers ─────────────────────────────────────────────────────────
383
+ /**
384
+ * Snaps a pixel X coordinate to the nearest bar's centre pixel.
385
+ * If no bars are loaded, or the nearest bar is more than SNAP_PX pixels away,
386
+ * returns the original x so the crosshair always renders at the cursor position.
387
+ */
388
+ _snapXToBar(x) {
389
+ const SNAP_PX = 20; // only snap when within this many pixels of a bar
390
+ // Collect all bar timestamps from the first series that has data.
391
+ let times = null;
392
+ for (const s of this._series) {
393
+ const data = s.data();
394
+ if (data.length > 0) {
395
+ times = data.map((b) => b.time);
396
+ break;
397
+ }
398
+ }
399
+ if (!times || times.length === 0)
400
+ return { x, time: this._transform.xToTime(x) };
401
+ // Find the nearest bar in pixel space (not time space) so the snap radius is
402
+ // consistent regardless of timeframe or zoom level.
403
+ let nearestTime = times[0];
404
+ let minPixDist = Math.abs(this._transform.timeToX(nearestTime) - x);
405
+ for (let i = 1; i < times.length; i++) {
406
+ const px = this._transform.timeToX(times[i]);
407
+ const d = Math.abs(px - x);
408
+ if (d < minPixDist) {
409
+ minPixDist = d;
410
+ nearestTime = times[i];
411
+ }
412
+ }
413
+ // If the nearest bar is within SNAP_PX, snap to it; otherwise keep raw cursor x.
414
+ if (minPixDist <= SNAP_PX) {
415
+ return { x: this._transform.timeToX(nearestTime), time: nearestTime };
416
+ }
417
+ return { x, time: this._transform.xToTime(x) };
418
+ }
419
+ _computeViewport() {
420
+ return {
421
+ timeRange: this._timeScale.visibleRange,
422
+ priceRange: this._priceScale.visibleRange,
423
+ };
424
+ }
425
+ _onResize() {
426
+ const { width, height } = this._container.getBoundingClientRect();
427
+ this.resize(width, height);
428
+ }
429
+ _handleKeyAction(action) {
430
+ const step = 40;
431
+ const zf = 1.1;
432
+ const cx = this._transform.plotWidth / 2;
433
+ switch (action) {
434
+ case 'panLeft':
435
+ this._transform.pan(step, 0);
436
+ break;
437
+ case 'panRight':
438
+ this._transform.pan(-step, 0);
439
+ break;
440
+ case 'panUp':
441
+ this._transform.pan(0, step);
442
+ break;
443
+ case 'panDown':
444
+ this._transform.pan(0, -step);
445
+ break;
446
+ case 'zoomIn':
447
+ this._transform.zoomTime(1 / zf, cx);
448
+ break;
449
+ case 'zoomOut':
450
+ this._transform.zoomTime(zf, cx);
451
+ break;
452
+ case 'scrollToEnd':
453
+ this._scrollToLatestBar();
454
+ break;
455
+ case 'scrollToStart': break;
456
+ case 'deselect':
457
+ if (this._drawingTool !== null) {
458
+ this.cancelDrawingTool();
459
+ }
460
+ else {
461
+ this._interaction.clearSelection();
462
+ }
463
+ break;
464
+ case 'deleteSelection':
465
+ this.deleteSelectedDrawing();
466
+ break;
467
+ }
468
+ this._dirty = true;
469
+ }
470
+ /**
471
+ * Fits the price scale to the high/low range of bars visible in the current
472
+ * time window. Called every render frame so the scale tracks panning/zooming.
473
+ */
474
+ _autoFitPriceToData() {
475
+ if (this._priceScaleManual)
476
+ return;
477
+ const { from, to } = this._timeScale.visibleRange;
478
+ let low = Infinity, high = -Infinity;
479
+ for (const series of this._series) {
480
+ for (const bar of series.data()) {
481
+ if (bar.time < from || bar.time > to)
482
+ continue;
483
+ if (bar.low < low)
484
+ low = bar.low;
485
+ if (bar.high > high)
486
+ high = bar.high;
487
+ }
488
+ }
489
+ if (!isFinite(low) || !isFinite(high))
490
+ return;
491
+ const pad = (high - low) * 0.05;
492
+ this._priceScale.setVisibleRange({ min: low - pad, max: high + pad });
493
+ }
494
+ /**
495
+ * Renders the last-price dotted line, price label, and countdown timer.
496
+ * Drawn on the overlay canvas above all series but below the crosshair.
497
+ */
498
+ _renderLastPriceLine(ctx) {
499
+ if (this._series.length === 0)
500
+ return;
501
+ const data = this._series[0].data();
502
+ if (data.length === 0)
503
+ return;
504
+ const lastBar = data[data.length - 1];
505
+ const plotWidth = this._transform.plotWidth;
506
+ const plotHeight = this._transform.plotHeight;
507
+ const psWidth = this._transform.priceScaleWidth;
508
+ const price = lastBar.close;
509
+ const y = this._transform.priceToY(price);
510
+ if (y < 0 || y > plotHeight)
511
+ return;
512
+ const isUp = lastBar.close >= lastBar.open;
513
+ const lineColor = isUp ? '#26a641' : '#f85149';
514
+ ctx.save();
515
+ // Dotted horizontal line across the plot area
516
+ ctx.beginPath();
517
+ ctx.strokeStyle = lineColor;
518
+ ctx.lineWidth = 1;
519
+ ctx.setLineDash([2, 3]);
520
+ ctx.moveTo(0, y);
521
+ ctx.lineTo(plotWidth, y);
522
+ ctx.stroke();
523
+ ctx.setLineDash([]);
524
+ // Countdown calculation
525
+ const tfSecs = _tfToSeconds(this._interval);
526
+ const now = Math.floor(Date.now() / 1000);
527
+ const remaining = lastBar.time + tfSecs - now;
528
+ const showCd = remaining > 0 && remaining <= tfSecs;
529
+ // Label box — taller when countdown is shown
530
+ const priceLabel = _formatLastPrice(price);
531
+ const lineH = 15;
532
+ const boxH = showCd ? lineH * 2 + 1 : lineH;
533
+ const boxY = y - lineH / 2;
534
+ ctx.fillStyle = lineColor;
535
+ ctx.fillRect(plotWidth, boxY, psWidth, boxH);
536
+ ctx.fillStyle = '#ffffff';
537
+ ctx.textAlign = 'left';
538
+ ctx.textBaseline = 'middle';
539
+ ctx.font = 'bold 11px system-ui, sans-serif';
540
+ ctx.fillText(priceLabel, plotWidth + 5, boxY + lineH / 2);
541
+ if (showCd) {
542
+ ctx.font = '10px system-ui, sans-serif';
543
+ ctx.fillStyle = 'rgba(255,255,255,0.85)';
544
+ ctx.fillText(_formatCountdown(remaining), plotWidth + 5, boxY + lineH + 1 + lineH / 2);
545
+ }
546
+ ctx.restore();
547
+ }
548
+ /** Pans the viewport so the latest bar sits near the right edge. */
549
+ _scrollToLatestBar() {
550
+ let latestTime = -Infinity;
551
+ for (const s of this._series) {
552
+ const data = s.data();
553
+ const last = data[data.length - 1];
554
+ if (last && last.time > latestTime)
555
+ latestTime = last.time;
556
+ }
557
+ if (!isFinite(latestTime))
558
+ return;
559
+ const pad = this._transform.plotWidth * 0.05;
560
+ const px = this._transform.timeToX(latestTime);
561
+ this._transform.pan(-(px - (this._transform.plotWidth - pad)), 0);
562
+ }
563
+ /**
564
+ * Returns the current visible time and price ranges.
565
+ */
566
+ getViewport() {
567
+ return {
568
+ timeRange: this._timeScale.visibleRange,
569
+ priceRange: this._priceScale.visibleRange,
570
+ };
571
+ }
572
+ /**
573
+ * Restores a previously saved viewport (time range + manual price range).
574
+ */
575
+ restoreViewport(v) {
576
+ this._timeScale.setVisibleRange(v.timeRange);
577
+ this._priceScale.setVisibleRange(v.priceRange);
578
+ this._priceScaleManual = true;
579
+ this._dirty = true;
580
+ }
581
+ /**
582
+ * Clears the manual-price-scale flag so the price axis returns to auto-fit mode.
583
+ * Call this after restoring a saved viewport so stale price ranges don't persist.
584
+ */
585
+ resetPriceScale() {
586
+ this._priceScaleManual = false;
587
+ this._dirty = true;
588
+ }
589
+ /**
590
+ * Sets the default viewport: shows 10 days of price history with the latest
591
+ * bar positioned near the right edge (5% right margin for breathing room).
592
+ * Also resets the price scale to auto-fit so prices center vertically.
593
+ * Called on initial data load and when the user double-clicks either axis.
594
+ */
595
+ fitDefaultView() {
596
+ let latestTime = -Infinity;
597
+ for (const s of this._series) {
598
+ const data = s.data();
599
+ const last = data[data.length - 1];
600
+ if (last && last.time > latestTime)
601
+ latestTime = last.time;
602
+ }
603
+ if (!isFinite(latestTime))
604
+ return;
605
+ // Show ~150 candles worth of history, scaled to the current timeframe.
606
+ // Latest bar sits at the 90% position (10% breathing room on the right).
607
+ const tfSec = _tfToSeconds(this._interval);
608
+ const WINDOW = tfSec * 150;
609
+ this._timeScale.setVisibleRange({
610
+ from: latestTime - WINDOW * 0.9,
611
+ to: latestTime + WINDOW * 0.1,
612
+ });
613
+ // Reset manual price scale so prices auto-fit to visible bars
614
+ this._priceScaleManual = false;
615
+ this._dirty = true;
616
+ }
617
+ // ─── Drawing tool API ──────────────────────────────────────────────────────
618
+ /** Returns the DrawingManager owned by this chart. */
619
+ drawingManager() {
620
+ return this._drawingMgr;
621
+ }
622
+ /** Force a redraw on the next animation frame. */
623
+ markDirty() {
624
+ this._dirty = true;
625
+ }
626
+ /**
627
+ * Activates a drawing tool. While active, mouse clicks place anchors.
628
+ * The tool auto-cancels after each commit. Press Escape to cancel mid-placement.
629
+ */
630
+ startDrawingTool(type) {
631
+ this._drawingTool = type;
632
+ this._drawingState = 'idle';
633
+ this._drawingP0 = null;
634
+ this._drawingP1 = null;
635
+ this._drawingCursorPt = null;
636
+ this._interaction.setDrawingMode(true);
637
+ this._dirty = true;
638
+ }
639
+ /** Cancels any in-progress drawing and returns to cursor mode. */
640
+ cancelDrawingTool() {
641
+ this._drawingTool = null;
642
+ this._drawingState = 'idle';
643
+ this._drawingP0 = null;
644
+ this._drawingP1 = null;
645
+ this._drawingCursorPt = null;
646
+ this._interaction.setDrawingMode(false);
647
+ this._dirty = true;
648
+ }
649
+ /**
650
+ * Show or hide the interactive crosshair lines.
651
+ * Pass `false` for Arrow/cursor mode; `true` for crosshair / dot / demonstration.
652
+ */
653
+ setCrosshairEnabled(enabled) {
654
+ this._crosshairEnabled = enabled;
655
+ this._interaction.setHideCursor(enabled);
656
+ if (!enabled) {
657
+ this._crosshair.hide();
658
+ this._dirty = true;
659
+ }
660
+ }
661
+ /**
662
+ * Hides (`true`) or restores (`false`) the native OS cursor.
663
+ * Call with `true` for dot and demonstration pointer modes whose visuals
664
+ * come from PointerOverlay rather than the SDK crosshair.
665
+ */
666
+ setNativeCursorHidden(hidden) {
667
+ this._interaction.setHideCursor(hidden);
668
+ }
669
+ /** Deletes the currently selected drawing (if any). */
670
+ deleteSelectedDrawing() {
671
+ const id = this._interaction.selectedDrawingId;
672
+ if (!id)
673
+ return;
674
+ this._drawingMgr.remove(id);
675
+ this._interaction.clearSelection();
676
+ this.onDrawingDeleted?.(id);
677
+ this._dirty = true;
678
+ }
679
+ // ─── Drawing placement state machine ──────────────────────────────────────
680
+ _handleDrawClick(x, y) {
681
+ const tool = this._drawingTool;
682
+ if (!tool)
683
+ return;
684
+ const snapped = this._snapToBar(x, y);
685
+ const isSingleAnchor = tool === 'horizontal' || tool === 'vertical' || tool === 'text' ||
686
+ tool === 'horizontalRay' || tool === 'crossLine';
687
+ if (isSingleAnchor) {
688
+ let label;
689
+ if (tool === 'text') {
690
+ const input = window.prompt('Enter text:');
691
+ if (input === null)
692
+ return; // cancelled
693
+ label = input || 'Text';
694
+ }
695
+ const id = this._drawingMgr.add({
696
+ type: tool,
697
+ points: [snapped],
698
+ color: this._colors.crosshair,
699
+ ...(label !== undefined ? { text: label } : {}),
700
+ });
701
+ const drawing = this._drawingMgr.get(id);
702
+ this.onDrawingCommitted?.(drawing);
703
+ this.cancelDrawingTool();
704
+ return;
705
+ }
706
+ const isThreeAnchor = tool === 'parallelChannel' || tool === 'flatTopBottom' ||
707
+ tool === 'pitchfork' || tool === 'schiffPitchfork' ||
708
+ tool === 'modifiedSchiffPitchfork' || tool === 'insidePitchfork';
709
+ if (isThreeAnchor) {
710
+ if (this._drawingState === 'idle') {
711
+ this._drawingP0 = snapped;
712
+ this._drawingState = 'placing_second';
713
+ this._dirty = true;
714
+ }
715
+ else if (this._drawingState === 'placing_second') {
716
+ this._drawingP1 = snapped;
717
+ this._drawingState = 'placing_third';
718
+ this._dirty = true;
719
+ }
720
+ else {
721
+ // For parallel channel, only the cursor's Y/price matters for the offset;
722
+ // lock p2.time to p1.time so the handle sits at the channel corner.
723
+ const p2 = tool === 'parallelChannel'
724
+ ? { time: this._drawingP1.time, price: snapped.price }
725
+ : snapped;
726
+ const id = this._drawingMgr.add({
727
+ type: tool,
728
+ points: [this._drawingP0, this._drawingP1, p2],
729
+ color: this._colors.crosshair,
730
+ });
731
+ const drawing = this._drawingMgr.get(id);
732
+ this.onDrawingCommitted?.(drawing);
733
+ this.cancelDrawingTool();
734
+ }
735
+ return;
736
+ }
737
+ // Two-anchor tools
738
+ if (this._drawingState === 'idle') {
739
+ this._drawingP0 = snapped;
740
+ this._drawingState = 'placing_second';
741
+ this._dirty = true;
742
+ }
743
+ else {
744
+ const p0 = this._drawingP0;
745
+ if (tool === 'disjointChannel') {
746
+ // Auto-place the second line below the first by a default pixel offset.
747
+ // This gives an immediate wedge shape the user can then drag to reshape.
748
+ const DEFAULT_OFFSET_PX = 60;
749
+ const p2 = {
750
+ time: p0.time,
751
+ price: this._transform.yToPrice(this._transform.priceToY(p0.price) + DEFAULT_OFFSET_PX),
752
+ };
753
+ const p3 = {
754
+ time: snapped.time,
755
+ price: this._transform.yToPrice(this._transform.priceToY(snapped.price) + DEFAULT_OFFSET_PX),
756
+ };
757
+ const id = this._drawingMgr.add({
758
+ type: tool,
759
+ points: [p0, snapped, p2, p3],
760
+ color: this._colors.crosshair,
761
+ });
762
+ const drawing = this._drawingMgr.get(id);
763
+ this.onDrawingCommitted?.(drawing);
764
+ this.cancelDrawingTool();
765
+ }
766
+ else {
767
+ const id = this._drawingMgr.add({ type: tool, points: [p0, snapped], color: this._colors.crosshair });
768
+ const drawing = this._drawingMgr.get(id);
769
+ this.onDrawingCommitted?.(drawing);
770
+ this.cancelDrawingTool();
771
+ }
772
+ }
773
+ }
774
+ _buildDraftPreview() {
775
+ const tool = this._drawingTool;
776
+ const cursor = this._drawingCursorPt;
777
+ if (!tool || !cursor)
778
+ return null;
779
+ const isSingleAnchor = tool === 'horizontal' || tool === 'vertical' || tool === 'text' ||
780
+ tool === 'horizontalRay' || tool === 'crossLine';
781
+ if (isSingleAnchor) {
782
+ return { type: tool, points: [cursor], color: this._colors.crosshair };
783
+ }
784
+ if (this._drawingState === 'placing_third' && this._drawingP0 && this._drawingP1) {
785
+ // For parallel channel, lock p2 to p1's time so the cursor tracks the channel corner
786
+ const p2 = tool === 'parallelChannel'
787
+ ? { time: this._drawingP1.time, price: cursor.price }
788
+ : cursor;
789
+ return { type: tool, points: [this._drawingP0, this._drawingP1, p2], color: this._colors.crosshair };
790
+ }
791
+ if (this._drawingState === 'placing_second' && this._drawingP0) {
792
+ return { type: tool, points: [this._drawingP0, cursor], color: this._colors.crosshair };
793
+ }
794
+ if (this._drawingP0 === null) {
795
+ return { type: tool, points: [cursor], color: this._colors.crosshair };
796
+ }
797
+ return null;
798
+ }
799
+ /**
800
+ * Snaps the pixel position to the nearest bar's time within SNAP_PX.
801
+ * Returns a DrawingPoint with the snapped time and the raw price at y.
802
+ */
803
+ _snapToBar(x, y) {
804
+ const SNAP_PX = 10;
805
+ const t = this._transform;
806
+ const price = t.yToPrice(y);
807
+ const time = t.xToTime(x);
808
+ let bestBar = null;
809
+ let bestDist = SNAP_PX;
810
+ for (const series of this._series) {
811
+ for (const bar of series.data()) {
812
+ const bx = t.timeToX(bar.time);
813
+ const dist = Math.abs(bx - x);
814
+ if (dist < bestDist) {
815
+ bestDist = dist;
816
+ bestBar = bar;
817
+ }
818
+ }
819
+ }
820
+ return { time: bestBar ? bestBar.time : time, price };
821
+ }
822
+ _resolveOptions(opts) {
823
+ return {
824
+ theme: opts.theme ?? 'dark',
825
+ colors: opts.colors ?? {},
826
+ timeScale: opts.timeScale ?? {},
827
+ priceScale: opts.priceScale ?? {},
828
+ crosshair: opts.crosshair ?? {},
829
+ handleScroll: opts.handleScroll ?? true,
830
+ handleScale: opts.handleScale ?? true,
831
+ timezone: opts.timezone ?? 'UTC',
832
+ };
833
+ }
834
+ _resolveColors(theme, overrides) {
835
+ const base = theme === 'dark' ? DARK_COLORS : LIGHT_COLORS;
836
+ return { ...base, ...overrides };
837
+ }
838
+ }
839
+ //# sourceMappingURL=Chart.js.map