@forgecharts/sdk 1.1.27 → 1.1.29

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 (356) 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__/candleInvariant.test.d.ts +20 -0
  4. package/dist/__tests__/candleInvariant.test.d.ts.map +1 -0
  5. package/dist/__tests__/public-api-surface.d.ts +13 -0
  6. package/dist/__tests__/public-api-surface.d.ts.map +1 -0
  7. package/dist/__tests__/timeframeBoundary.test.d.ts +17 -0
  8. package/dist/__tests__/timeframeBoundary.test.d.ts.map +1 -0
  9. package/dist/api/DrawingManager.d.ts +20 -0
  10. package/dist/api/DrawingManager.d.ts.map +1 -0
  11. package/dist/api/EventBus.d.ts +19 -0
  12. package/dist/api/EventBus.d.ts.map +1 -0
  13. package/dist/api/IndicatorDAG.d.ts +85 -0
  14. package/dist/api/IndicatorDAG.d.ts.map +1 -0
  15. package/dist/api/IndicatorRegistry.d.ts +22 -0
  16. package/dist/api/IndicatorRegistry.d.ts.map +1 -0
  17. package/dist/api/LayoutManager.d.ts +30 -0
  18. package/dist/api/LayoutManager.d.ts.map +1 -0
  19. package/dist/api/PaneManager.d.ts +42 -0
  20. package/dist/api/PaneManager.d.ts.map +1 -0
  21. package/dist/api/ReferenceAPI.d.ts +78 -0
  22. package/dist/api/ReferenceAPI.d.ts.map +1 -0
  23. package/dist/api/TChart.d.ts +345 -0
  24. package/dist/api/TChart.d.ts.map +1 -0
  25. package/{src/api/createChart.ts → dist/api/createChart.d.ts} +2 -7
  26. package/dist/api/createChart.d.ts.map +1 -0
  27. package/dist/api/drawing tools/fib gann menu/fibRetracement.d.ts +4 -0
  28. package/dist/api/drawing tools/fib gann menu/fibRetracement.d.ts.map +1 -0
  29. package/dist/api/drawing tools/lines menu/crossLine.d.ts +4 -0
  30. package/dist/api/drawing tools/lines menu/crossLine.d.ts.map +1 -0
  31. package/dist/api/drawing tools/lines menu/disjointChannel.d.ts +17 -0
  32. package/dist/api/drawing tools/lines menu/disjointChannel.d.ts.map +1 -0
  33. package/dist/api/drawing tools/lines menu/extendedLine.d.ts +4 -0
  34. package/dist/api/drawing tools/lines menu/extendedLine.d.ts.map +1 -0
  35. package/dist/api/drawing tools/lines menu/flatTopBottom.d.ts +4 -0
  36. package/dist/api/drawing tools/lines menu/flatTopBottom.d.ts.map +1 -0
  37. package/dist/api/drawing tools/lines menu/horizontal.d.ts +4 -0
  38. package/dist/api/drawing tools/lines menu/horizontal.d.ts.map +1 -0
  39. package/dist/api/drawing tools/lines menu/horizontalRay.d.ts +4 -0
  40. package/dist/api/drawing tools/lines menu/horizontalRay.d.ts.map +1 -0
  41. package/dist/api/drawing tools/lines menu/infoLine.d.ts +4 -0
  42. package/dist/api/drawing tools/lines menu/infoLine.d.ts.map +1 -0
  43. package/dist/api/drawing tools/lines menu/insidePitchfork.d.ts +4 -0
  44. package/dist/api/drawing tools/lines menu/insidePitchfork.d.ts.map +1 -0
  45. package/dist/api/drawing tools/lines menu/modifiedSchiffPitchfork.d.ts +4 -0
  46. package/dist/api/drawing tools/lines menu/modifiedSchiffPitchfork.d.ts.map +1 -0
  47. package/dist/api/drawing tools/lines menu/parallelChannel.d.ts +4 -0
  48. package/dist/api/drawing tools/lines menu/parallelChannel.d.ts.map +1 -0
  49. package/dist/api/drawing tools/lines menu/pitchfork.d.ts +4 -0
  50. package/dist/api/drawing tools/lines menu/pitchfork.d.ts.map +1 -0
  51. package/dist/api/drawing tools/lines menu/ray.d.ts +4 -0
  52. package/dist/api/drawing tools/lines menu/ray.d.ts.map +1 -0
  53. package/dist/api/drawing tools/lines menu/regressionTrend.d.ts +4 -0
  54. package/dist/api/drawing tools/lines menu/regressionTrend.d.ts.map +1 -0
  55. package/dist/api/drawing tools/lines menu/schiffPitchfork.d.ts +4 -0
  56. package/dist/api/drawing tools/lines menu/schiffPitchfork.d.ts.map +1 -0
  57. package/dist/api/drawing tools/lines menu/trendAngle.d.ts +4 -0
  58. package/dist/api/drawing tools/lines menu/trendAngle.d.ts.map +1 -0
  59. package/dist/api/drawing tools/lines menu/trendline.d.ts +4 -0
  60. package/dist/api/drawing tools/lines menu/trendline.d.ts.map +1 -0
  61. package/dist/api/drawing tools/lines menu/vertical.d.ts +4 -0
  62. package/dist/api/drawing tools/lines menu/vertical.d.ts.map +1 -0
  63. package/{src/api/drawing tools/pointers menu/crosshair.ts → dist/api/drawing tools/pointers menu/crosshair.d.ts } +8 -9
  64. package/dist/api/drawing tools/pointers menu/crosshair.d.ts.map +1 -0
  65. package/dist/api/drawing tools/pointers menu/cursor.d.ts +15 -0
  66. package/dist/api/drawing tools/pointers menu/cursor.d.ts.map +1 -0
  67. package/{src/api/drawing tools/pointers menu/demonstration.ts → dist/api/drawing tools/pointers menu/demonstration.d.ts } +12 -17
  68. package/dist/api/drawing tools/pointers menu/demonstration.d.ts.map +1 -0
  69. package/{src/api/drawing tools/pointers menu/dot.ts → dist/api/drawing tools/pointers menu/dot.d.ts } +10 -13
  70. package/dist/api/drawing tools/pointers menu/dot.d.ts.map +1 -0
  71. package/dist/api/drawing tools/shapes menu/rectangle.d.ts +4 -0
  72. package/dist/api/drawing tools/shapes menu/rectangle.d.ts.map +1 -0
  73. package/dist/api/drawing tools/shapes menu/text.d.ts +4 -0
  74. package/dist/api/drawing tools/shapes menu/text.d.ts.map +1 -0
  75. package/dist/api/drawingUtils.d.ts +22 -0
  76. package/dist/api/drawingUtils.d.ts.map +1 -0
  77. package/dist/core/CanvasLayer.d.ts +26 -0
  78. package/dist/core/CanvasLayer.d.ts.map +1 -0
  79. package/dist/core/Chart.d.ts +164 -0
  80. package/dist/core/Chart.d.ts.map +1 -0
  81. package/dist/core/CoordTransform.d.ts +168 -0
  82. package/dist/core/CoordTransform.d.ts.map +1 -0
  83. package/dist/core/Crosshair.d.ts +30 -0
  84. package/dist/core/Crosshair.d.ts.map +1 -0
  85. package/dist/core/IndicatorEngine.d.ts +51 -0
  86. package/dist/core/IndicatorEngine.d.ts.map +1 -0
  87. package/dist/core/InteractionManager.d.ts +197 -0
  88. package/dist/core/InteractionManager.d.ts.map +1 -0
  89. package/dist/core/PriceScale.d.ts +27 -0
  90. package/dist/core/PriceScale.d.ts.map +1 -0
  91. package/dist/core/Series.d.ts +40 -0
  92. package/dist/core/Series.d.ts.map +1 -0
  93. package/dist/core/TimeScale.d.ts +43 -0
  94. package/dist/core/TimeScale.d.ts.map +1 -0
  95. package/dist/datafeed/DatafeedConnector.d.ts +89 -0
  96. package/dist/datafeed/DatafeedConnector.d.ts.map +1 -0
  97. package/dist/engine/CandleEngine.d.ts +207 -0
  98. package/dist/engine/CandleEngine.d.ts.map +1 -0
  99. package/dist/engine/__tests__/CandleEngine.test.d.ts +2 -0
  100. package/dist/engine/__tests__/CandleEngine.test.d.ts.map +1 -0
  101. package/dist/engine/candleInvariants.d.ts +66 -0
  102. package/dist/engine/candleInvariants.d.ts.map +1 -0
  103. package/{src/engine/mergeUtils.ts → dist/engine/mergeUtils.d.ts} +15 -52
  104. package/dist/engine/mergeUtils.d.ts.map +1 -0
  105. package/dist/engine/timeframeUtils.d.ts +80 -0
  106. package/dist/engine/timeframeUtils.d.ts.map +1 -0
  107. package/dist/index.d.ts +40 -0
  108. package/dist/index.d.ts.map +1 -0
  109. package/dist/index.js +8101 -0
  110. package/dist/index.js.map +1 -0
  111. package/{src/internal.ts → dist/internal.d.ts} +1 -13
  112. package/dist/internal.d.ts.map +1 -0
  113. package/dist/internal.js +8852 -0
  114. package/dist/internal.js.map +1 -0
  115. package/dist/licensing/ChartRuntimeResolver.d.ts +233 -0
  116. package/dist/licensing/ChartRuntimeResolver.d.ts.map +1 -0
  117. package/dist/licensing/LicenseManager.d.ts +55 -0
  118. package/dist/licensing/LicenseManager.d.ts.map +1 -0
  119. package/dist/licensing/__tests__/ChartRuntimeResolver.test.d.ts +13 -0
  120. package/dist/licensing/__tests__/ChartRuntimeResolver.test.d.ts.map +1 -0
  121. package/dist/licensing/__tests__/LicenseManager.test.d.ts +12 -0
  122. package/dist/licensing/__tests__/LicenseManager.test.d.ts.map +1 -0
  123. package/dist/licensing/licenseTypes.d.ts +18 -0
  124. package/dist/licensing/licenseTypes.d.ts.map +1 -0
  125. package/dist/pine/PineCompiler.d.ts +35 -0
  126. package/dist/pine/PineCompiler.d.ts.map +1 -0
  127. package/dist/pine/diagnostics.d.ts +20 -0
  128. package/dist/pine/diagnostics.d.ts.map +1 -0
  129. package/{src/pine/index.ts → dist/pine/index.d.ts} +4 -3
  130. package/dist/pine/index.d.ts.map +1 -0
  131. package/dist/pine/pine-ast.d.ts +142 -0
  132. package/dist/pine/pine-ast.d.ts.map +1 -0
  133. package/dist/pine/pine-lexer.d.ts +41 -0
  134. package/dist/pine/pine-lexer.d.ts.map +1 -0
  135. package/dist/pine/pine-parser.d.ts +51 -0
  136. package/dist/pine/pine-parser.d.ts.map +1 -0
  137. package/dist/pine/pine-transpiler.d.ts +33 -0
  138. package/dist/pine/pine-transpiler.d.ts.map +1 -0
  139. package/dist/pixi/LayerName.d.ts +18 -0
  140. package/dist/pixi/LayerName.d.ts.map +1 -0
  141. package/dist/pixi/PixiCandlestickRenderer.d.ts +23 -0
  142. package/dist/pixi/PixiCandlestickRenderer.d.ts.map +1 -0
  143. package/dist/pixi/PixiChart.d.ts +72 -0
  144. package/dist/pixi/PixiChart.d.ts.map +1 -0
  145. package/dist/pixi/PixiCrosshairRenderer.d.ts +29 -0
  146. package/dist/pixi/PixiCrosshairRenderer.d.ts.map +1 -0
  147. package/dist/pixi/PixiDrawingRenderer.d.ts +17 -0
  148. package/dist/pixi/PixiDrawingRenderer.d.ts.map +1 -0
  149. package/dist/pixi/PixiGridRenderer.d.ts +22 -0
  150. package/dist/pixi/PixiGridRenderer.d.ts.map +1 -0
  151. package/dist/pixi/PixiLayerManager.d.ts +56 -0
  152. package/dist/pixi/PixiLayerManager.d.ts.map +1 -0
  153. package/dist/react/canvas/ChartCanvas.d.ts +85 -0
  154. package/dist/react/canvas/ChartCanvas.d.ts.map +1 -0
  155. package/dist/react/canvas/ChartContextMenu.d.ts +18 -0
  156. package/dist/react/canvas/ChartContextMenu.d.ts.map +1 -0
  157. package/dist/react/canvas/ChartSettingsDialog.d.ts +25 -0
  158. package/dist/react/canvas/ChartSettingsDialog.d.ts.map +1 -0
  159. package/dist/react/canvas/IndicatorLabel.d.ts +21 -0
  160. package/dist/react/canvas/IndicatorLabel.d.ts.map +1 -0
  161. package/dist/react/canvas/IndicatorPane.d.ts +32 -0
  162. package/dist/react/canvas/IndicatorPane.d.ts.map +1 -0
  163. package/dist/react/canvas/PointerOverlay.d.ts +23 -0
  164. package/dist/react/canvas/PointerOverlay.d.ts.map +1 -0
  165. package/dist/react/canvas/toolbars/LeftToolbar.d.ts +19 -0
  166. package/dist/react/canvas/toolbars/LeftToolbar.d.ts.map +1 -0
  167. package/dist/react/hooks/useChartCapabilities.d.ts +21 -0
  168. package/dist/react/hooks/useChartCapabilities.d.ts.map +1 -0
  169. package/{src/react/index.ts → dist/react/index.d.ts} +2 -23
  170. package/dist/react/index.d.ts.map +1 -0
  171. package/dist/react/index.js +11559 -0
  172. package/dist/react/index.js.map +1 -0
  173. package/{src/react/internal.ts → dist/react/internal.d.ts} +2 -26
  174. package/dist/react/internal.d.ts.map +1 -0
  175. package/dist/react/internal.js +12148 -0
  176. package/dist/react/internal.js.map +1 -0
  177. package/dist/react/shell/ManagedAppShell.d.ts +91 -0
  178. package/dist/react/shell/ManagedAppShell.d.ts.map +1 -0
  179. package/dist/react/trading/TradingBridge.d.ts +86 -0
  180. package/dist/react/trading/TradingBridge.d.ts.map +1 -0
  181. package/dist/react/workspace/ChartWorkspace.d.ts +73 -0
  182. package/dist/react/workspace/ChartWorkspace.d.ts.map +1 -0
  183. package/dist/react/workspace/FloatingPanel.d.ts +18 -0
  184. package/dist/react/workspace/FloatingPanel.d.ts.map +1 -0
  185. package/dist/react/workspace/IndicatorsDialog.d.ts +8 -0
  186. package/dist/react/workspace/IndicatorsDialog.d.ts.map +1 -0
  187. package/dist/react/workspace/LayoutMenu.d.ts +33 -0
  188. package/dist/react/workspace/LayoutMenu.d.ts.map +1 -0
  189. package/dist/react/workspace/SymbolSearchDialog.d.ts +10 -0
  190. package/dist/react/workspace/SymbolSearchDialog.d.ts.map +1 -0
  191. package/dist/react/workspace/TabBar.d.ts +17 -0
  192. package/dist/react/workspace/TabBar.d.ts.map +1 -0
  193. package/dist/react/workspace/toolbars/BottomToolbar.d.ts +19 -0
  194. package/dist/react/workspace/toolbars/BottomToolbar.d.ts.map +1 -0
  195. package/dist/react/workspace/toolbars/RightToolbar.d.ts +8 -0
  196. package/dist/react/workspace/toolbars/RightToolbar.d.ts.map +1 -0
  197. package/dist/react/workspace/toolbars/TopToolbar.d.ts +41 -0
  198. package/dist/react/workspace/toolbars/TopToolbar.d.ts.map +1 -0
  199. package/dist/renderers/CandlestickRenderer.d.ts +13 -0
  200. package/dist/renderers/CandlestickRenderer.d.ts.map +1 -0
  201. package/dist/renderers/HistogramRenderer.d.ts +11 -0
  202. package/dist/renderers/HistogramRenderer.d.ts.map +1 -0
  203. package/dist/renderers/LineRenderer.d.ts +12 -0
  204. package/dist/renderers/LineRenderer.d.ts.map +1 -0
  205. package/dist/theme/colors.d.ts +4 -0
  206. package/dist/theme/colors.d.ts.map +1 -0
  207. package/dist/tools/barDivergenceCheck.d.ts +120 -0
  208. package/dist/tools/barDivergenceCheck.d.ts.map +1 -0
  209. package/dist/trading/TradingOverlayStore.d.ts +86 -0
  210. package/dist/trading/TradingOverlayStore.d.ts.map +1 -0
  211. package/dist/trading/UnmanagedIngestion.d.ts +91 -0
  212. package/dist/trading/UnmanagedIngestion.d.ts.map +1 -0
  213. package/dist/trading/__tests__/ManagedTradingController.test.d.ts +18 -0
  214. package/dist/trading/__tests__/ManagedTradingController.test.d.ts.map +1 -0
  215. package/dist/trading/__tests__/TradingOverlayStore.test.d.ts +16 -0
  216. package/dist/trading/__tests__/TradingOverlayStore.test.d.ts.map +1 -0
  217. package/dist/trading/__tests__/UnmanagedIngestion.test.d.ts +16 -0
  218. package/dist/trading/__tests__/UnmanagedIngestion.test.d.ts.map +1 -0
  219. package/dist/trading/managed/ManagedTradingController.d.ts +110 -0
  220. package/dist/trading/managed/ManagedTradingController.d.ts.map +1 -0
  221. package/dist/trading/managed/managedCapabilities.d.ts +45 -0
  222. package/dist/trading/managed/managedCapabilities.d.ts.map +1 -0
  223. package/dist/trading/managed/managedTypes.d.ts +122 -0
  224. package/dist/trading/managed/managedTypes.d.ts.map +1 -0
  225. package/dist/trading/tradingTypes.d.ts +89 -0
  226. package/dist/trading/tradingTypes.d.ts.map +1 -0
  227. package/dist/tscript/TScriptIndicator.d.ts +41 -0
  228. package/dist/tscript/TScriptIndicator.d.ts.map +1 -0
  229. package/dist/tscript/ast.d.ts +89 -0
  230. package/dist/tscript/ast.d.ts.map +1 -0
  231. package/dist/tscript/lexer.d.ts +36 -0
  232. package/dist/tscript/lexer.d.ts.map +1 -0
  233. package/dist/tscript/parser.d.ts +50 -0
  234. package/dist/tscript/parser.d.ts.map +1 -0
  235. package/dist/tscript/runtime.d.ts +123 -0
  236. package/dist/tscript/runtime.d.ts.map +1 -0
  237. package/dist/tscript/series.d.ts +49 -0
  238. package/dist/tscript/series.d.ts.map +1 -0
  239. package/dist/types/IChart.d.ts +48 -0
  240. package/dist/types/IChart.d.ts.map +1 -0
  241. package/{src/types/IRenderer.ts → dist/types/IRenderer.d.ts} +2 -8
  242. package/dist/types/IRenderer.d.ts.map +1 -0
  243. package/dist/types/ISeries.d.ts +26 -0
  244. package/dist/types/ISeries.d.ts.map +1 -0
  245. package/package.json +5 -1
  246. package/src/__tests__/backwardCompatibility.test.ts +0 -191
  247. package/src/__tests__/candleInvariant.test.ts +0 -500
  248. package/src/__tests__/public-api-surface.ts +0 -76
  249. package/src/__tests__/timeframeBoundary.test.ts +0 -583
  250. package/src/api/DrawingManager.ts +0 -188
  251. package/src/api/EventBus.ts +0 -53
  252. package/src/api/IndicatorDAG.ts +0 -389
  253. package/src/api/IndicatorRegistry.ts +0 -47
  254. package/src/api/LayoutManager.ts +0 -72
  255. package/src/api/PaneManager.ts +0 -129
  256. package/src/api/ReferenceAPI.ts +0 -195
  257. package/src/api/TChart.ts +0 -881
  258. package/src/api/drawing tools/fib gann menu/fibRetracement.ts +0 -27
  259. package/src/api/drawing tools/lines menu/crossLine.ts +0 -21
  260. package/src/api/drawing tools/lines menu/disjointChannel.ts +0 -74
  261. package/src/api/drawing tools/lines menu/extendedLine.ts +0 -22
  262. package/src/api/drawing tools/lines menu/flatTopBottom.ts +0 -45
  263. package/src/api/drawing tools/lines menu/horizontal.ts +0 -24
  264. package/src/api/drawing tools/lines menu/horizontalRay.ts +0 -25
  265. package/src/api/drawing tools/lines menu/infoLine.ts +0 -127
  266. package/src/api/drawing tools/lines menu/insidePitchfork.ts +0 -21
  267. package/src/api/drawing tools/lines menu/modifiedSchiffPitchfork.ts +0 -18
  268. package/src/api/drawing tools/lines menu/parallelChannel.ts +0 -47
  269. package/src/api/drawing tools/lines menu/pitchfork.ts +0 -15
  270. package/src/api/drawing tools/lines menu/ray.ts +0 -28
  271. package/src/api/drawing tools/lines menu/regressionTrend.ts +0 -157
  272. package/src/api/drawing tools/lines menu/schiffPitchfork.ts +0 -18
  273. package/src/api/drawing tools/lines menu/trendAngle.ts +0 -64
  274. package/src/api/drawing tools/lines menu/trendline.ts +0 -16
  275. package/src/api/drawing tools/lines menu/vertical.ts +0 -16
  276. package/src/api/drawing tools/pointers menu/cursor.ts +0 -16
  277. package/src/api/drawing tools/shapes menu/rectangle.ts +0 -24
  278. package/src/api/drawing tools/shapes menu/text.ts +0 -30
  279. package/src/api/drawingUtils.ts +0 -82
  280. package/src/core/CanvasLayer.ts +0 -77
  281. package/src/core/Chart.ts +0 -917
  282. package/src/core/CoordTransform.ts +0 -282
  283. package/src/core/Crosshair.ts +0 -207
  284. package/src/core/IndicatorEngine.ts +0 -216
  285. package/src/core/InteractionManager.ts +0 -899
  286. package/src/core/PriceScale.ts +0 -133
  287. package/src/core/Series.ts +0 -132
  288. package/src/core/TimeScale.ts +0 -175
  289. package/src/datafeed/DatafeedConnector.ts +0 -300
  290. package/src/engine/CandleEngine.ts +0 -458
  291. package/src/engine/__tests__/CandleEngine.test.ts +0 -402
  292. package/src/engine/candleInvariants.ts +0 -172
  293. package/src/engine/timeframeUtils.ts +0 -118
  294. package/src/index.ts +0 -190
  295. package/src/licensing/ChartRuntimeResolver.ts +0 -380
  296. package/src/licensing/LicenseManager.ts +0 -131
  297. package/src/licensing/__tests__/ChartRuntimeResolver.test.ts +0 -207
  298. package/src/licensing/__tests__/LicenseManager.test.ts +0 -180
  299. package/src/licensing/licenseTypes.ts +0 -19
  300. package/src/pine/PineCompiler.ts +0 -68
  301. package/src/pine/diagnostics.ts +0 -30
  302. package/src/pine/pine-ast.ts +0 -163
  303. package/src/pine/pine-lexer.ts +0 -265
  304. package/src/pine/pine-parser.ts +0 -439
  305. package/src/pine/pine-transpiler.ts +0 -301
  306. package/src/pixi/LayerName.ts +0 -35
  307. package/src/pixi/PixiCandlestickRenderer.ts +0 -125
  308. package/src/pixi/PixiChart.ts +0 -425
  309. package/src/pixi/PixiCrosshairRenderer.ts +0 -134
  310. package/src/pixi/PixiDrawingRenderer.ts +0 -121
  311. package/src/pixi/PixiGridRenderer.ts +0 -136
  312. package/src/pixi/PixiLayerManager.ts +0 -102
  313. package/src/react/canvas/ChartCanvas.tsx +0 -984
  314. package/src/react/canvas/ChartContextMenu.tsx +0 -60
  315. package/src/react/canvas/ChartSettingsDialog.tsx +0 -133
  316. package/src/react/canvas/IndicatorLabel.tsx +0 -347
  317. package/src/react/canvas/IndicatorPane.tsx +0 -503
  318. package/src/react/canvas/PointerOverlay.tsx +0 -126
  319. package/src/react/canvas/toolbars/LeftToolbar.tsx +0 -1096
  320. package/src/react/hooks/useChartCapabilities.ts +0 -76
  321. package/src/react/shell/ManagedAppShell.tsx +0 -699
  322. package/src/react/trading/TradingBridge.ts +0 -156
  323. package/src/react/workspace/ChartWorkspace.tsx +0 -228
  324. package/src/react/workspace/FloatingPanel.tsx +0 -131
  325. package/src/react/workspace/IndicatorsDialog.tsx +0 -246
  326. package/src/react/workspace/LayoutMenu.tsx +0 -345
  327. package/src/react/workspace/SymbolSearchDialog.tsx +0 -377
  328. package/src/react/workspace/TabBar.tsx +0 -87
  329. package/src/react/workspace/toolbars/BottomToolbar.tsx +0 -372
  330. package/src/react/workspace/toolbars/RightToolbar.tsx +0 -46
  331. package/src/react/workspace/toolbars/TopToolbar.tsx +0 -431
  332. package/src/renderers/CandlestickRenderer.ts +0 -130
  333. package/src/renderers/HistogramRenderer.ts +0 -63
  334. package/src/renderers/LineRenderer.ts +0 -77
  335. package/src/theme/colors.ts +0 -21
  336. package/src/tools/barDivergenceCheck.ts +0 -305
  337. package/src/trading/TradingOverlayStore.ts +0 -161
  338. package/src/trading/UnmanagedIngestion.ts +0 -156
  339. package/src/trading/__tests__/ManagedTradingController.test.ts +0 -338
  340. package/src/trading/__tests__/TradingOverlayStore.test.ts +0 -323
  341. package/src/trading/__tests__/UnmanagedIngestion.test.ts +0 -205
  342. package/src/trading/managed/ManagedTradingController.ts +0 -292
  343. package/src/trading/managed/managedCapabilities.ts +0 -98
  344. package/src/trading/managed/managedTypes.ts +0 -151
  345. package/src/trading/tradingTypes.ts +0 -135
  346. package/src/tscript/TScriptIndicator.ts +0 -54
  347. package/src/tscript/ast.ts +0 -105
  348. package/src/tscript/lexer.ts +0 -190
  349. package/src/tscript/parser.ts +0 -334
  350. package/src/tscript/runtime.ts +0 -525
  351. package/src/tscript/series.ts +0 -84
  352. package/src/types/IChart.ts +0 -56
  353. package/src/types/ISeries.ts +0 -30
  354. package/tsconfig.json +0 -23
  355. package/tsup.config.ts +0 -16
  356. package/vitest.config.ts +0 -25
@@ -1,503 +0,0 @@
1
- /**
2
- * IndicatorPane — Canvas 2D rendering of a single indicator sub-pane.
3
- *
4
- * Uses the main chart's CoordTransform for x-axis alignment, then computes
5
- * its own per-pane y-axis from indicator value ranges.
6
- */
7
-
8
- import { useEffect, useRef } from 'react';
9
- import type { OHLCV, IndicatorInstance, ChartTheme } from '@forgecharts/types';
10
- import type { CoordTransform, DAGResult } from '../../';
11
- import type { IndicatorPoint, MACDPoint } from '../../';
12
- import { IndicatorLabel } from './IndicatorLabel';
13
-
14
- // ─── Constants ────────────────────────────────────────────────────────────────
15
-
16
- /** Width of the right-side price axis — must match the main chart's AXIS_WIDTH. */
17
- const AXIS_W = 70;
18
- /** Vertical padding inside the pane (logical pixels). */
19
- const PAD_T = 8;
20
- const PAD_B = 8;
21
-
22
- // ─── Theme palettes ───────────────────────────────────────────────────────────
23
-
24
- const PALETTE = {
25
- dark: {
26
- bg: '#131722',
27
- text: '#d1d4dc',
28
- muted: '#787b86',
29
- border: '#2a2e39',
30
- up: '#26a69a',
31
- down: '#ef5350',
32
- macdLine: '#2196f3',
33
- signalLine: '#ff9800',
34
- },
35
- light: {
36
- bg: '#ffffff',
37
- text: '#131722',
38
- muted: '#9098a1',
39
- border: '#e0e3eb',
40
- up: '#26a69a',
41
- down: '#ef5350',
42
- macdLine: '#1565c0',
43
- signalLine: '#e65100',
44
- },
45
- } as const;
46
-
47
- type Pal = (typeof PALETTE)[keyof typeof PALETTE];
48
-
49
- // ─── Low-level draw helpers ───────────────────────────────────────────────────
50
-
51
- function _vy(value: number, min: number, max: number, topPad: number, plotH: number): number {
52
- if (max === min) return topPad + plotH / 2;
53
- return topPad + plotH * (1 - (value - min) / (max - min));
54
- }
55
-
56
- function _hline(
57
- ctx: CanvasRenderingContext2D,
58
- y: number,
59
- plotW: number,
60
- color: string,
61
- dash: number[] = [],
62
- ): void {
63
- ctx.strokeStyle = color;
64
- ctx.lineWidth = 0.5;
65
- ctx.setLineDash(dash);
66
- ctx.beginPath();
67
- ctx.moveTo(0, y + 0.5);
68
- ctx.lineTo(plotW, y + 0.5);
69
- ctx.stroke();
70
- ctx.setLineDash([]);
71
- }
72
-
73
- function _axisLabels(
74
- ctx: CanvasRenderingContext2D,
75
- ticks: number[],
76
- min: number,
77
- max: number,
78
- topPad: number,
79
- plotH: number,
80
- canvasH: number,
81
- plotW: number,
82
- color: string,
83
- decimals = 0,
84
- ): void {
85
- ctx.font = '9px -apple-system, BlinkMacSystemFont, sans-serif';
86
- ctx.fillStyle = color;
87
- ctx.textAlign = 'left';
88
- ctx.textBaseline = 'middle';
89
- for (const tick of ticks) {
90
- const y = _vy(tick, min, max, topPad, plotH);
91
- if (y < 2 || y > canvasH - 2) continue;
92
- ctx.fillText(tick.toFixed(decimals), plotW + 4, y);
93
- }
94
- }
95
-
96
- // ─── Per-indicator renderers ──────────────────────────────────────────────────
97
-
98
- function _renderRSI(
99
- ctx: CanvasRenderingContext2D,
100
- points: readonly IndicatorPoint[],
101
- transform: CoordTransform,
102
- plotW: number,
103
- h: number,
104
- lineColor: string,
105
- pal: Pal,
106
- ): void {
107
- const plotH = h - PAD_T - PAD_B;
108
- const min = 0;
109
- const max = 100;
110
- const y70 = _vy(70, min, max, PAD_T, plotH);
111
- const y50 = _vy(50, min, max, PAD_T, plotH);
112
- const y30 = _vy(30, min, max, PAD_T, plotH);
113
-
114
- // Zone fills
115
- ctx.fillStyle = 'rgba(239,83,80,0.06)';
116
- ctx.fillRect(0, PAD_T, plotW, y70 - PAD_T);
117
- ctx.fillStyle = 'rgba(38,166,154,0.06)';
118
- ctx.fillRect(0, y30, plotW, h - PAD_B - y30);
119
-
120
- // Reference lines
121
- _hline(ctx, y70, plotW, pal.muted, [3, 3]);
122
- _hline(ctx, y50, plotW, pal.border);
123
- _hline(ctx, y30, plotW, pal.muted, [3, 3]);
124
-
125
- // Level labels inside plot area
126
- ctx.font = '9px sans-serif';
127
- ctx.fillStyle = pal.muted;
128
- ctx.textAlign = 'left';
129
- ctx.textBaseline = 'bottom';
130
- ctx.fillText('70', 2, y70);
131
- ctx.textBaseline = 'top';
132
- ctx.fillText('30', 2, y30);
133
-
134
- // RSI line
135
- if (points.length > 0) {
136
- ctx.strokeStyle = lineColor;
137
- ctx.lineWidth = 1.5;
138
- ctx.beginPath();
139
- let started = false;
140
- for (const p of points) {
141
- const x = transform.timeToX(p.time);
142
- if (x < -20 || x > plotW + 20) { started = false; continue; }
143
- const y = _vy(p.value, min, max, PAD_T, plotH);
144
- if (!started) { ctx.moveTo(x, y); started = true; } else { ctx.lineTo(x, y); }
145
- }
146
- ctx.stroke();
147
- }
148
-
149
- _axisLabels(ctx, [0, 30, 50, 70, 100], min, max, PAD_T, plotH, h, plotW, pal.muted);
150
- }
151
-
152
- function _renderMACD(
153
- ctx: CanvasRenderingContext2D,
154
- points: readonly MACDPoint[],
155
- transform: CoordTransform,
156
- plotW: number,
157
- h: number,
158
- pal: Pal,
159
- ): void {
160
- if (points.length === 0) return;
161
- const plotH = h - PAD_T - PAD_B;
162
-
163
- // Auto-scale to visible values
164
- let min = Infinity;
165
- let max = -Infinity;
166
- for (const p of points) {
167
- const x = transform.timeToX(p.time);
168
- if (x < -20 || x > plotW + 20) continue;
169
- min = Math.min(min, p.histogram, p.macd, p.signal);
170
- max = Math.max(max, p.histogram, p.macd, p.signal);
171
- }
172
- if (!isFinite(min)) { min = -0.01; max = 0.01; }
173
- const rangePad = (max - min) * 0.1 || 0.001;
174
- min -= rangePad; max += rangePad;
175
-
176
- // Zero line
177
- _hline(ctx, _vy(0, min, max, PAD_T, plotH), plotW, pal.border, [2, 2]);
178
-
179
- // Compute bar pixel width from consecutive timestamps
180
- let barPx = 5;
181
- if (points.length >= 2) {
182
- barPx = Math.max(1, Math.abs(transform.timeToX(points[1]!.time) - transform.timeToX(points[0]!.time)) * 0.7);
183
- }
184
-
185
- // Histogram bars
186
- const y0 = _vy(0, min, max, PAD_T, plotH);
187
- for (const p of points) {
188
- const x = transform.timeToX(p.time);
189
- if (x < -barPx || x > plotW + barPx) continue;
190
- const yH = _vy(p.histogram, min, max, PAD_T, plotH);
191
- ctx.fillStyle = p.histogram >= 0 ? `${pal.up}99` : `${pal.down}99`;
192
- ctx.fillRect(x - barPx / 2, Math.min(y0, yH), barPx, Math.abs(y0 - yH) || 1);
193
- }
194
-
195
- // MACD line
196
- ctx.strokeStyle = pal.macdLine;
197
- ctx.lineWidth = 1.5;
198
- ctx.beginPath();
199
- let started = false;
200
- for (const p of points) {
201
- const x = transform.timeToX(p.time);
202
- if (x < -20 || x > plotW + 20) { started = false; continue; }
203
- const y = _vy(p.macd, min, max, PAD_T, plotH);
204
- if (!started) { ctx.moveTo(x, y); started = true; } else { ctx.lineTo(x, y); }
205
- }
206
- ctx.stroke();
207
-
208
- // Signal line
209
- ctx.strokeStyle = pal.signalLine;
210
- ctx.lineWidth = 1;
211
- ctx.beginPath();
212
- started = false;
213
- for (const p of points) {
214
- const x = transform.timeToX(p.time);
215
- if (x < -20 || x > plotW + 20) { started = false; continue; }
216
- const y = _vy(p.signal, min, max, PAD_T, plotH);
217
- if (!started) { ctx.moveTo(x, y); started = true; } else { ctx.lineTo(x, y); }
218
- }
219
- ctx.stroke();
220
-
221
- const range = max - min;
222
- const dec = range < 0.1 ? 4 : range < 10 ? 2 : 0;
223
- _axisLabels(
224
- ctx,
225
- [min + range * 0.1, min + range * 0.5, min + range * 0.9],
226
- min, max, PAD_T, plotH, h, plotW, pal.muted, dec,
227
- );
228
- }
229
-
230
- function _renderVolume(
231
- ctx: CanvasRenderingContext2D,
232
- bars: readonly OHLCV[],
233
- points: readonly IndicatorPoint[],
234
- transform: CoordTransform,
235
- plotW: number,
236
- h: number,
237
- pal: Pal,
238
- ): void {
239
- if (points.length === 0) return;
240
- const plotH = h - PAD_T - PAD_B;
241
- const min = 0;
242
- const max = Math.max(...points.map((p) => p.value));
243
- if (max === 0) return;
244
-
245
- const barMap = new Map(bars.map((b) => [b.time, b]));
246
- let barPx = 5;
247
- if (points.length >= 2) {
248
- barPx = Math.max(1, Math.abs(transform.timeToX(points[1]!.time) - transform.timeToX(points[0]!.time)) * 0.8);
249
- }
250
-
251
- const yBase = _vy(0, min, max, PAD_T, plotH);
252
- for (const p of points) {
253
- const x = transform.timeToX(p.time);
254
- if (x < -barPx || x > plotW + barPx) continue;
255
- const bar = barMap.get(p.time);
256
- const isUp = bar !== undefined ? bar.close >= bar.open : true;
257
- const yTop = _vy(p.value, min, max, PAD_T, plotH);
258
- ctx.fillStyle = isUp ? `${pal.up}99` : `${pal.down}99`;
259
- ctx.fillRect(x - barPx / 2, yTop, barPx, Math.abs(yBase - yTop) || 1);
260
- }
261
-
262
- _axisLabels(ctx, [max], min, max, PAD_T, plotH, h, plotW, pal.muted, 0);
263
- }
264
-
265
- function _renderLineIndicator(
266
- ctx: CanvasRenderingContext2D,
267
- points: readonly IndicatorPoint[],
268
- transform: CoordTransform,
269
- plotW: number,
270
- h: number,
271
- lineColor: string,
272
- pal: Pal,
273
- ): void {
274
- if (points.length === 0) return;
275
- const plotH = h - PAD_T - PAD_B;
276
-
277
- // Auto-scale to visible values
278
- let min = Infinity;
279
- let max = -Infinity;
280
- for (const p of points) {
281
- const x = transform.timeToX(p.time);
282
- if (x < -20 || x > plotW + 20) continue;
283
- min = Math.min(min, p.value);
284
- max = Math.max(max, p.value);
285
- }
286
- if (!isFinite(min)) return;
287
- const rangePad = (max - min) * 0.1 || 1;
288
- min -= rangePad; max += rangePad;
289
-
290
- ctx.strokeStyle = lineColor;
291
- ctx.lineWidth = 1.5;
292
- ctx.beginPath();
293
- let started = false;
294
- for (const p of points) {
295
- const x = transform.timeToX(p.time);
296
- if (x < -20 || x > plotW + 20) { started = false; continue; }
297
- const y = _vy(p.value, min, max, PAD_T, plotH);
298
- if (!started) { ctx.moveTo(x, y); started = true; } else { ctx.lineTo(x, y); }
299
- }
300
- ctx.stroke();
301
-
302
- const range = max - min;
303
- const dec = range < 0.1 ? 4 : range < 10 ? 2 : 0;
304
- _axisLabels(ctx, [min + range * 0.25, min + range * 0.75], min, max, PAD_T, plotH, h, plotW, pal.muted, dec);
305
- }
306
-
307
- // ─── Label helper ─────────────────────────────────────────────────────────────
308
-
309
- function _indicatorLabel(type: string, params: Record<string, unknown> = {}): string {
310
- switch (type) {
311
- case 'rsi': return `RSI(${params['period'] ?? 14})`;
312
- case 'macd': return `MACD(${params['fast'] ?? 12},${params['slow'] ?? 26},${params['signal'] ?? 9})`;
313
- case 'volume': return 'Volume';
314
- case 'sma': return `SMA(${params['period'] ?? 20})`;
315
- case 'ema': return `EMA(${params['period'] ?? 20})`;
316
- case 'wma': return `WMA(${params['period'] ?? 20})`;
317
- default: return type.toUpperCase();
318
- }
319
- }
320
-
321
- // ─── Component ────────────────────────────────────────────────────────────────
322
-
323
- export type IndicatorPaneProps = {
324
- /** Indicators to render in this pane. */
325
- indicators: readonly IndicatorInstance[];
326
- /** Full bar dataset — still needed for volume bar up/down colouring. */
327
- bars: readonly OHLCV[];
328
- /** Shared coordinate transform from the main price chart. Null until chart mounts. */
329
- transform: CoordTransform | null;
330
- /** CSS height of this pane in pixels. */
331
- height: number;
332
- /** Colour theme — must match the main chart. */
333
- theme: ChartTheme;
334
- /** Pre-computed DAG results — keyed by indicator id. */
335
- computedResults: ReadonlyMap<string, DAGResult>;
336
- /** Called when the user clicks the × button on an indicator label. */
337
- onRemove?: (id: string) => void;
338
- /** Called when the user clicks the ⚙ button on an indicator label. */
339
- onConfigure?: (indicator: IndicatorInstance) => void;
340
- /** Ref to the current crosshair X pixel (from the price pane). Drawn as a synced vertical line. */
341
- crosshairXRef?: { current: number | null };
342
- };
343
-
344
- export function IndicatorPane({
345
- indicators,
346
- bars,
347
- transform,
348
- height,
349
- theme,
350
- computedResults,
351
- crosshairXRef,
352
- onRemove,
353
- onConfigure,
354
- }: IndicatorPaneProps) {
355
- const canvasRef = useRef<HTMLCanvasElement>(null);
356
- // Stable ref to the draw function — rebuilt whenever data changes,
357
- // called each RAF frame to stay in sync with the candle layer.
358
- const drawFnRef = useRef<(() => void) | null>(null);
359
-
360
- useEffect(() => {
361
- drawFnRef.current = () => {
362
- const canvas = canvasRef.current;
363
- if (!canvas || !transform || indicators.length === 0) return;
364
-
365
- const dpr = window.devicePixelRatio ?? 1;
366
- const cssW = canvas.offsetWidth || (canvas.parentElement?.clientWidth ?? 800);
367
- const cssH = height;
368
- const physW = Math.round(cssW * dpr);
369
- const physH = Math.round(cssH * dpr);
370
-
371
- if (canvas.width !== physW || canvas.height !== physH) {
372
- canvas.width = physW;
373
- canvas.height = physH;
374
- }
375
-
376
- const ctx = canvas.getContext('2d');
377
- if (!ctx) return;
378
-
379
- const pal = PALETTE[theme];
380
-
381
- ctx.save();
382
- ctx.scale(dpr, dpr);
383
-
384
- const w = cssW;
385
- const h = cssH;
386
- const plotW = w - AXIS_W;
387
-
388
- // Background
389
- ctx.fillStyle = pal.bg;
390
- ctx.fillRect(0, 0, w, h);
391
-
392
- // Top separator
393
- ctx.strokeStyle = pal.border;
394
- ctx.lineWidth = 1;
395
- ctx.beginPath();
396
- ctx.moveTo(0, 0.5);
397
- ctx.lineTo(w, 0.5);
398
- ctx.stroke();
399
-
400
- // Axis divider
401
- ctx.beginPath();
402
- ctx.moveTo(plotW + 0.5, 0);
403
- ctx.lineTo(plotW + 0.5, h);
404
- ctx.stroke();
405
-
406
- // Clip plot area so indicator lines don't bleed into axis
407
- ctx.save();
408
- ctx.beginPath();
409
- ctx.rect(0, 0, plotW, h);
410
- ctx.clip();
411
-
412
- for (const indicator of indicators) {
413
- const result = computedResults.get(indicator.id);
414
- if (!result) continue;
415
- const color = indicator.config.color;
416
-
417
- switch (indicator.config.type) {
418
- case 'rsi':
419
- if (result.kind === 'series')
420
- _renderRSI(ctx, result.points, transform, plotW, h, color ?? '#7c4dff', pal);
421
- break;
422
- case 'macd':
423
- if (result.kind === 'macd')
424
- _renderMACD(ctx, result.points, transform, plotW, h, pal);
425
- break;
426
- case 'volume':
427
- if (result.kind === 'series')
428
- _renderVolume(ctx, bars, result.points, transform, plotW, h, pal);
429
- break;
430
- default:
431
- // sma, ema, wma, bbands, and any chained / custom indicators
432
- if (result.kind === 'series')
433
- _renderLineIndicator(ctx, result.points, transform, plotW, h, color ?? '#ffb300', pal);
434
- }
435
- }
436
-
437
- // ── Crosshair vertical line (synced from price pane) ────────────────
438
- const xhair = crosshairXRef?.current ?? null;
439
- if (xhair !== null && xhair >= 0 && xhair <= plotW) {
440
- ctx.strokeStyle = theme === 'dark' ? 'rgba(255,255,255,0.4)' : 'rgba(0,0,0,0.4)';
441
- ctx.lineWidth = 0.5;
442
- ctx.setLineDash([3, 3]);
443
- ctx.beginPath();
444
- ctx.moveTo(xhair + 0.5, 0);
445
- ctx.lineTo(xhair + 0.5, h);
446
- ctx.stroke();
447
- ctx.setLineDash([]);
448
- }
449
-
450
- ctx.restore(); // clip
451
-
452
- ctx.restore(); // dpr scale
453
- };
454
- // Draw immediately when data (not viewport) changes.
455
- drawFnRef.current();
456
- }, [computedResults, bars, height, indicators, transform, theme]);
457
-
458
- // RAF loop: redraw every frame so the pane tracks pan/zoom in the same
459
- // animation frame as the candle layer — no React state update needed.
460
- useEffect(() => {
461
- let rafId: number;
462
- const tick = () => {
463
- drawFnRef.current?.();
464
- rafId = requestAnimationFrame(tick);
465
- };
466
- rafId = requestAnimationFrame(tick);
467
- return () => cancelAnimationFrame(rafId);
468
- }, []);
469
-
470
- const pal = PALETTE[theme];
471
-
472
- return (
473
- <div style={{ position: 'relative', width: '100%', height: `${height}px` }}>
474
- <canvas
475
- ref={canvasRef}
476
- style={{ width: '100%', height: `${height}px`, display: 'block' }}
477
- />
478
- {/* Indicator name labels — one per indicator in this pane */}
479
- <div
480
- style={{
481
- position: 'absolute',
482
- top: 4,
483
- left: 4,
484
- display: 'flex',
485
- flexDirection: 'column',
486
- gap: 2,
487
- pointerEvents: 'auto',
488
- zIndex: 2,
489
- }}
490
- >
491
- {indicators.map((ind) => (
492
- <IndicatorLabel
493
- key={ind.id}
494
- indicator={ind}
495
- color={pal.text}
496
- onRemove={() => onRemove?.(ind.id)}
497
- onConfigure={() => onConfigure?.(ind)}
498
- />
499
- ))}
500
- </div>
501
- </div>
502
- );
503
- }
@@ -1,126 +0,0 @@
1
- import React, { useEffect, useRef } from 'react';
2
- import type { PointerToolType } from '../../';
3
- import {
4
- DOT_RADIUS,
5
- DOT_COLOR,
6
- DEMONSTRATION_RADIUS,
7
- DEMONSTRATION_FILL,
8
- DEMONSTRATION_STROKE,
9
- DEMONSTRATION_COLOR,
10
- } from '../../';
11
-
12
- /**
13
- * PointerOverlay — a transparent `<div>` that covers the entire chart area and
14
- * renders tool-specific cursor visuals for the `dot` and `demonstration` modes.
15
- *
16
- * - **dot**: SVG crosshair lines + small filled circle at the intersection.
17
- * - **demonstration**: SVG crosshair + semi-transparent filled circle centred
18
- * on the cursor.
19
- *
20
- * The component does NOT intercept pointer events (`pointerEvents: none`), so
21
- * all mouse interactions pass through to the canvas layers beneath it.
22
- */
23
-
24
- type Props = {
25
- mode: PointerToolType;
26
- /** Width of the container to size the SVG overlay. */
27
- width: number;
28
- /** Height of the container to size the SVG overlay. */
29
- height: number;
30
- };
31
-
32
- const CROSSHAIR_COLOR = DEMONSTRATION_COLOR;
33
-
34
- export function PointerOverlay({ mode, width, height }: Props): React.ReactElement | null {
35
- const svgRef = useRef<SVGSVGElement>(null);
36
- const hGroupRef = useRef<SVGGElement>(null); // translateY group → horizontal line
37
- const vGroupRef = useRef<SVGGElement>(null); // translateX group → vertical line
38
- const cursorGroup = useRef<SVGGElement>(null); // translate(x,y) group → dot/circle
39
-
40
- useEffect(() => {
41
- const svg = svgRef.current;
42
- if (!svg) return;
43
- const container = svg.parentElement;
44
- if (!container) return;
45
-
46
- // Cache the bounding rect so we never call getBoundingClientRect() inside the
47
- // hot move handler (it forces a synchronous reflow on every event).
48
- let cachedRect = container.getBoundingClientRect();
49
- const ro = new ResizeObserver(() => { cachedRect = container.getBoundingClientRect(); });
50
- ro.observe(container);
51
-
52
- const onMove = (e: MouseEvent) => {
53
- const x = e.clientX - cachedRect.left;
54
- const y = e.clientY - cachedRect.top;
55
-
56
- if (x < 0 || y < 0 || x > cachedRect.width || y > cachedRect.height) {
57
- svg.style.opacity = '0';
58
- return;
59
- }
60
-
61
- svg.style.opacity = '1';
62
-
63
- // CSS transforms are GPU-composited — no layout reflow, no paint.
64
- if (hGroupRef.current) hGroupRef.current.style.transform = `translateY(${y}px)`;
65
- if (vGroupRef.current) vGroupRef.current.style.transform = `translateX(${x}px)`;
66
- if (cursorGroup.current) cursorGroup.current.style.transform = `translate(${x}px,${y}px)`;
67
- };
68
-
69
- const hide = () => { svg.style.opacity = '0'; };
70
-
71
- // passive:true lets the browser skip asking us about preventDefault → lower latency
72
- container.addEventListener('mousemove', onMove, { passive: true });
73
- container.addEventListener('mouseleave', hide, { passive: true });
74
- return () => {
75
- container.removeEventListener('mousemove', onMove);
76
- container.removeEventListener('mouseleave', hide);
77
- ro.disconnect();
78
- };
79
- }, []);
80
-
81
- if (mode !== 'dot' && mode !== 'demonstration') return null;
82
-
83
- return (
84
- <svg
85
- ref={svgRef}
86
- width={width}
87
- height={height}
88
- style={{
89
- position: 'absolute',
90
- top: 0,
91
- left: 0,
92
- pointerEvents: 'none',
93
- zIndex: 5,
94
- opacity: 0,
95
- overflow: 'visible',
96
- willChange: 'opacity',
97
- }}
98
- >
99
- {/* Horizontal crosshair line — spans ±∞ so width never matters */}
100
- <g ref={hGroupRef}>
101
- <line x1="-9999" y1="0" x2="9999" y2="0"
102
- stroke={CROSSHAIR_COLOR} strokeWidth="1" strokeDasharray="4 3" />
103
- </g>
104
-
105
- {/* Vertical crosshair line — spans ±∞ so height never matters */}
106
- <g ref={vGroupRef}>
107
- <line x1="0" y1="-9999" x2="0" y2="9999"
108
- stroke={CROSSHAIR_COLOR} strokeWidth="1" strokeDasharray="4 3" />
109
- </g>
110
-
111
- {/* Cursor element translated to (x, y) */}
112
- <g ref={cursorGroup}>
113
- {mode === 'dot' && (
114
- <circle r={DOT_RADIUS} fill={DOT_COLOR} />
115
- )}
116
- {mode === 'demonstration' && (
117
- <circle r={DEMONSTRATION_RADIUS}
118
- fill={DEMONSTRATION_FILL}
119
- stroke={DEMONSTRATION_STROKE}
120
- strokeWidth="1.5"
121
- />
122
- )}
123
- </g>
124
- </svg>
125
- );
126
- }