@itssumitrai/fin-charter 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/README.md +96 -0
  2. package/dist/api/chart-api.d.ts +173 -0
  3. package/dist/api/export.d.ts +46 -0
  4. package/dist/api/indicator-api.d.ts +38 -0
  5. package/dist/api/options.d.ts +226 -0
  6. package/dist/api/pane-api.d.ts +28 -0
  7. package/dist/api/series-api.d.ts +115 -0
  8. package/dist/core/accessibility.d.ts +90 -0
  9. package/dist/core/alert-line.d.ts +49 -0
  10. package/dist/core/chart-state.d.ts +39 -0
  11. package/dist/core/chart-sync.d.ts +83 -0
  12. package/dist/core/crosshair.d.ts +28 -0
  13. package/dist/core/css-theme.d.ts +41 -0
  14. package/dist/core/custom-indicator.d.ts +70 -0
  15. package/dist/core/data-feed.d.ts +59 -0
  16. package/dist/core/data-layer.d.ts +38 -0
  17. package/dist/core/invalidation.d.ts +24 -0
  18. package/dist/core/market-session.d.ts +11 -0
  19. package/dist/core/order-line.d.ts +134 -0
  20. package/dist/core/pane-divider.d.ts +22 -0
  21. package/dist/core/pane.d.ts +32 -0
  22. package/dist/core/periodicity.d.ts +6 -0
  23. package/dist/core/plugin.d.ts +90 -0
  24. package/dist/core/price-line.d.ts +17 -0
  25. package/dist/core/price-scale.d.ts +74 -0
  26. package/dist/core/replay.d.ts +73 -0
  27. package/dist/core/rtl.d.ts +22 -0
  28. package/dist/core/segment-tree.d.ts +38 -0
  29. package/dist/core/series-markers.d.ts +18 -0
  30. package/dist/core/storage-adapter.d.ts +50 -0
  31. package/dist/core/streaming-adapter.d.ts +102 -0
  32. package/dist/core/symbol-resolver.d.ts +32 -0
  33. package/dist/core/text-label.d.ts +72 -0
  34. package/dist/core/time-scale.d.ts +109 -0
  35. package/dist/core/types.d.ts +144 -0
  36. package/dist/core/undo-redo.d.ts +46 -0
  37. package/dist/currency/currency.d.ts +8 -0
  38. package/dist/currency/index.d.ts +2 -0
  39. package/dist/drawings/arrow.d.ts +10 -0
  40. package/dist/drawings/base.d.ts +79 -0
  41. package/dist/drawings/channel.d.ts +10 -0
  42. package/dist/drawings/crossline.d.ts +10 -0
  43. package/dist/drawings/ellipse.d.ts +10 -0
  44. package/dist/drawings/fib-arc.d.ts +10 -0
  45. package/dist/drawings/fib-fan.d.ts +12 -0
  46. package/dist/drawings/fib-projection.d.ts +11 -0
  47. package/dist/drawings/fibonacci.d.ts +11 -0
  48. package/dist/drawings/horizontal-line.d.ts +10 -0
  49. package/dist/drawings/index.d.ts +7 -0
  50. package/dist/drawings/measurement.d.ts +11 -0
  51. package/dist/drawings/pitchfork.d.ts +12 -0
  52. package/dist/drawings/ray.d.ts +12 -0
  53. package/dist/drawings/rectangle.d.ts +10 -0
  54. package/dist/drawings/text-annotation.d.ts +11 -0
  55. package/dist/drawings/trendline.d.ts +10 -0
  56. package/dist/drawings/vertical-line.d.ts +10 -0
  57. package/dist/formatting/index.d.ts +5 -0
  58. package/dist/formatting/price-formatter.d.ts +6 -0
  59. package/dist/formatting/time-formatter.d.ts +7 -0
  60. package/dist/formatting/volume-formatter.d.ts +1 -0
  61. package/dist/i18n/i18n.d.ts +6 -0
  62. package/dist/i18n/index.d.ts +3 -0
  63. package/dist/i18n/locales/en.d.ts +3 -0
  64. package/dist/index.d.ts +63 -0
  65. package/dist/index.js +2 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/index10.js +2 -0
  68. package/dist/index10.js.map +1 -0
  69. package/dist/index100.js +2 -0
  70. package/dist/index100.js.map +1 -0
  71. package/dist/index101.js +2 -0
  72. package/dist/index101.js.map +1 -0
  73. package/dist/index102.js +2 -0
  74. package/dist/index102.js.map +1 -0
  75. package/dist/index103.js +2 -0
  76. package/dist/index103.js.map +1 -0
  77. package/dist/index104.js +2 -0
  78. package/dist/index104.js.map +1 -0
  79. package/dist/index105.js +2 -0
  80. package/dist/index105.js.map +1 -0
  81. package/dist/index106.js +2 -0
  82. package/dist/index106.js.map +1 -0
  83. package/dist/index107.js +2 -0
  84. package/dist/index107.js.map +1 -0
  85. package/dist/index108.js +2 -0
  86. package/dist/index108.js.map +1 -0
  87. package/dist/index109.js +2 -0
  88. package/dist/index109.js.map +1 -0
  89. package/dist/index11.js +2 -0
  90. package/dist/index11.js.map +1 -0
  91. package/dist/index110.js +2 -0
  92. package/dist/index110.js.map +1 -0
  93. package/dist/index111.js +2 -0
  94. package/dist/index111.js.map +1 -0
  95. package/dist/index112.js +2 -0
  96. package/dist/index112.js.map +1 -0
  97. package/dist/index113.js +2 -0
  98. package/dist/index113.js.map +1 -0
  99. package/dist/index114.js +2 -0
  100. package/dist/index114.js.map +1 -0
  101. package/dist/index115.js +2 -0
  102. package/dist/index115.js.map +1 -0
  103. package/dist/index116.js +2 -0
  104. package/dist/index116.js.map +1 -0
  105. package/dist/index117.js +2 -0
  106. package/dist/index117.js.map +1 -0
  107. package/dist/index118.js +2 -0
  108. package/dist/index118.js.map +1 -0
  109. package/dist/index119.js +2 -0
  110. package/dist/index119.js.map +1 -0
  111. package/dist/index12.js +2 -0
  112. package/dist/index12.js.map +1 -0
  113. package/dist/index120.js +2 -0
  114. package/dist/index120.js.map +1 -0
  115. package/dist/index121.js +2 -0
  116. package/dist/index121.js.map +1 -0
  117. package/dist/index122.js +2 -0
  118. package/dist/index122.js.map +1 -0
  119. package/dist/index123.js +2 -0
  120. package/dist/index123.js.map +1 -0
  121. package/dist/index124.js +2 -0
  122. package/dist/index124.js.map +1 -0
  123. package/dist/index13.js +2 -0
  124. package/dist/index13.js.map +1 -0
  125. package/dist/index14.js +2 -0
  126. package/dist/index14.js.map +1 -0
  127. package/dist/index15.js +2 -0
  128. package/dist/index15.js.map +1 -0
  129. package/dist/index16.js +2 -0
  130. package/dist/index16.js.map +1 -0
  131. package/dist/index17.js +2 -0
  132. package/dist/index17.js.map +1 -0
  133. package/dist/index18.js +2 -0
  134. package/dist/index18.js.map +1 -0
  135. package/dist/index19.js +2 -0
  136. package/dist/index19.js.map +1 -0
  137. package/dist/index2.js +2 -0
  138. package/dist/index2.js.map +1 -0
  139. package/dist/index20.js +2 -0
  140. package/dist/index20.js.map +1 -0
  141. package/dist/index21.js +2 -0
  142. package/dist/index21.js.map +1 -0
  143. package/dist/index22.js +2 -0
  144. package/dist/index22.js.map +1 -0
  145. package/dist/index23.js +2 -0
  146. package/dist/index23.js.map +1 -0
  147. package/dist/index24.js +2 -0
  148. package/dist/index24.js.map +1 -0
  149. package/dist/index25.js +2 -0
  150. package/dist/index25.js.map +1 -0
  151. package/dist/index26.js +2 -0
  152. package/dist/index26.js.map +1 -0
  153. package/dist/index27.js +2 -0
  154. package/dist/index27.js.map +1 -0
  155. package/dist/index28.js +2 -0
  156. package/dist/index28.js.map +1 -0
  157. package/dist/index29.js +2 -0
  158. package/dist/index29.js.map +1 -0
  159. package/dist/index3.js +2 -0
  160. package/dist/index3.js.map +1 -0
  161. package/dist/index30.js +2 -0
  162. package/dist/index30.js.map +1 -0
  163. package/dist/index31.js +2 -0
  164. package/dist/index31.js.map +1 -0
  165. package/dist/index32.js +2 -0
  166. package/dist/index32.js.map +1 -0
  167. package/dist/index33.js +2 -0
  168. package/dist/index33.js.map +1 -0
  169. package/dist/index34.js +2 -0
  170. package/dist/index34.js.map +1 -0
  171. package/dist/index35.js +2 -0
  172. package/dist/index35.js.map +1 -0
  173. package/dist/index36.js +2 -0
  174. package/dist/index36.js.map +1 -0
  175. package/dist/index37.js +2 -0
  176. package/dist/index37.js.map +1 -0
  177. package/dist/index38.js +2 -0
  178. package/dist/index38.js.map +1 -0
  179. package/dist/index39.js +2 -0
  180. package/dist/index39.js.map +1 -0
  181. package/dist/index4.js +2 -0
  182. package/dist/index4.js.map +1 -0
  183. package/dist/index40.js +2 -0
  184. package/dist/index40.js.map +1 -0
  185. package/dist/index41.js +2 -0
  186. package/dist/index41.js.map +1 -0
  187. package/dist/index42.js +2 -0
  188. package/dist/index42.js.map +1 -0
  189. package/dist/index43.js +2 -0
  190. package/dist/index43.js.map +1 -0
  191. package/dist/index44.js +2 -0
  192. package/dist/index44.js.map +1 -0
  193. package/dist/index45.js +2 -0
  194. package/dist/index45.js.map +1 -0
  195. package/dist/index46.js +2 -0
  196. package/dist/index46.js.map +1 -0
  197. package/dist/index47.js +2 -0
  198. package/dist/index47.js.map +1 -0
  199. package/dist/index48.js +2 -0
  200. package/dist/index48.js.map +1 -0
  201. package/dist/index49.js +2 -0
  202. package/dist/index49.js.map +1 -0
  203. package/dist/index5.js +2 -0
  204. package/dist/index5.js.map +1 -0
  205. package/dist/index50.js +2 -0
  206. package/dist/index50.js.map +1 -0
  207. package/dist/index51.js +2 -0
  208. package/dist/index51.js.map +1 -0
  209. package/dist/index52.js +2 -0
  210. package/dist/index52.js.map +1 -0
  211. package/dist/index53.js +2 -0
  212. package/dist/index53.js.map +1 -0
  213. package/dist/index54.js +2 -0
  214. package/dist/index54.js.map +1 -0
  215. package/dist/index55.js +2 -0
  216. package/dist/index55.js.map +1 -0
  217. package/dist/index56.js +2 -0
  218. package/dist/index56.js.map +1 -0
  219. package/dist/index57.js +2 -0
  220. package/dist/index57.js.map +1 -0
  221. package/dist/index58.js +2 -0
  222. package/dist/index58.js.map +1 -0
  223. package/dist/index59.js +2 -0
  224. package/dist/index59.js.map +1 -0
  225. package/dist/index6.js +2 -0
  226. package/dist/index6.js.map +1 -0
  227. package/dist/index60.js +2 -0
  228. package/dist/index60.js.map +1 -0
  229. package/dist/index61.js +2 -0
  230. package/dist/index61.js.map +1 -0
  231. package/dist/index62.js +2 -0
  232. package/dist/index62.js.map +1 -0
  233. package/dist/index63.js +2 -0
  234. package/dist/index63.js.map +1 -0
  235. package/dist/index64.js +2 -0
  236. package/dist/index64.js.map +1 -0
  237. package/dist/index65.js +3 -0
  238. package/dist/index65.js.map +1 -0
  239. package/dist/index66.js +2 -0
  240. package/dist/index66.js.map +1 -0
  241. package/dist/index67.js +2 -0
  242. package/dist/index67.js.map +1 -0
  243. package/dist/index68.js +2 -0
  244. package/dist/index68.js.map +1 -0
  245. package/dist/index69.js +2 -0
  246. package/dist/index69.js.map +1 -0
  247. package/dist/index7.js +2 -0
  248. package/dist/index7.js.map +1 -0
  249. package/dist/index70.js +2 -0
  250. package/dist/index70.js.map +1 -0
  251. package/dist/index71.js +2 -0
  252. package/dist/index71.js.map +1 -0
  253. package/dist/index72.js +2 -0
  254. package/dist/index72.js.map +1 -0
  255. package/dist/index73.js +2 -0
  256. package/dist/index73.js.map +1 -0
  257. package/dist/index74.js +2 -0
  258. package/dist/index74.js.map +1 -0
  259. package/dist/index75.js +2 -0
  260. package/dist/index75.js.map +1 -0
  261. package/dist/index76.js +2 -0
  262. package/dist/index76.js.map +1 -0
  263. package/dist/index77.js +2 -0
  264. package/dist/index77.js.map +1 -0
  265. package/dist/index78.js +2 -0
  266. package/dist/index78.js.map +1 -0
  267. package/dist/index79.js +2 -0
  268. package/dist/index79.js.map +1 -0
  269. package/dist/index8.js +2 -0
  270. package/dist/index8.js.map +1 -0
  271. package/dist/index80.js +2 -0
  272. package/dist/index80.js.map +1 -0
  273. package/dist/index81.js +2 -0
  274. package/dist/index81.js.map +1 -0
  275. package/dist/index82.js +2 -0
  276. package/dist/index82.js.map +1 -0
  277. package/dist/index83.js +2 -0
  278. package/dist/index83.js.map +1 -0
  279. package/dist/index84.js +2 -0
  280. package/dist/index84.js.map +1 -0
  281. package/dist/index85.js +2 -0
  282. package/dist/index85.js.map +1 -0
  283. package/dist/index86.js +2 -0
  284. package/dist/index86.js.map +1 -0
  285. package/dist/index87.js +2 -0
  286. package/dist/index87.js.map +1 -0
  287. package/dist/index88.js +2 -0
  288. package/dist/index88.js.map +1 -0
  289. package/dist/index89.js +2 -0
  290. package/dist/index89.js.map +1 -0
  291. package/dist/index9.js +2 -0
  292. package/dist/index9.js.map +1 -0
  293. package/dist/index90.js +2 -0
  294. package/dist/index90.js.map +1 -0
  295. package/dist/index91.js +2 -0
  296. package/dist/index91.js.map +1 -0
  297. package/dist/index92.js +2 -0
  298. package/dist/index92.js.map +1 -0
  299. package/dist/index93.js +2 -0
  300. package/dist/index93.js.map +1 -0
  301. package/dist/index94.js +2 -0
  302. package/dist/index94.js.map +1 -0
  303. package/dist/index95.js +2 -0
  304. package/dist/index95.js.map +1 -0
  305. package/dist/index96.js +2 -0
  306. package/dist/index96.js.map +1 -0
  307. package/dist/index97.js +2 -0
  308. package/dist/index97.js.map +1 -0
  309. package/dist/index98.js +2 -0
  310. package/dist/index98.js.map +1 -0
  311. package/dist/index99.js +2 -0
  312. package/dist/index99.js.map +1 -0
  313. package/dist/indicators/adx.d.ts +6 -0
  314. package/dist/indicators/aroon.d.ts +5 -0
  315. package/dist/indicators/atr.d.ts +1 -0
  316. package/dist/indicators/awesome-oscillator.d.ts +1 -0
  317. package/dist/indicators/bollinger.d.ts +6 -0
  318. package/dist/indicators/cci.d.ts +1 -0
  319. package/dist/indicators/chaikin-mf.d.ts +1 -0
  320. package/dist/indicators/choppiness.d.ts +1 -0
  321. package/dist/indicators/coppock.d.ts +1 -0
  322. package/dist/indicators/donchian.d.ts +6 -0
  323. package/dist/indicators/elder-force.d.ts +1 -0
  324. package/dist/indicators/ema.d.ts +1 -0
  325. package/dist/indicators/ichimoku.d.ts +8 -0
  326. package/dist/indicators/index.d.ts +31 -0
  327. package/dist/indicators/keltner.d.ts +6 -0
  328. package/dist/indicators/linear-regression.d.ts +1 -0
  329. package/dist/indicators/macd.d.ts +6 -0
  330. package/dist/indicators/mfi.d.ts +1 -0
  331. package/dist/indicators/obv.d.ts +1 -0
  332. package/dist/indicators/parabolic-sar.d.ts +1 -0
  333. package/dist/indicators/pivot-points.d.ts +10 -0
  334. package/dist/indicators/roc.d.ts +1 -0
  335. package/dist/indicators/rsi.d.ts +1 -0
  336. package/dist/indicators/sma.d.ts +1 -0
  337. package/dist/indicators/stochastic.d.ts +5 -0
  338. package/dist/indicators/supertrend.d.ts +5 -0
  339. package/dist/indicators/trix.d.ts +5 -0
  340. package/dist/indicators/utils.d.ts +20 -0
  341. package/dist/indicators/volume-profile.d.ts +37 -0
  342. package/dist/indicators/volume.d.ts +1 -0
  343. package/dist/indicators/vwap.d.ts +1 -0
  344. package/dist/indicators/vwma.d.ts +1 -0
  345. package/dist/indicators/williams-r.d.ts +1 -0
  346. package/dist/interactions/axis-drag.d.ts +24 -0
  347. package/dist/interactions/context-menu-handler.d.ts +42 -0
  348. package/dist/interactions/crosshair.d.ts +20 -0
  349. package/dist/interactions/drawing-handler.d.ts +39 -0
  350. package/dist/interactions/event-router.d.ts +37 -0
  351. package/dist/interactions/keyboard-nav.d.ts +11 -0
  352. package/dist/interactions/pan-zoom.d.ts +39 -0
  353. package/dist/interactions/range-selection.d.ts +103 -0
  354. package/dist/interactions/touch-gestures.d.ts +36 -0
  355. package/dist/logo.svg +40 -0
  356. package/dist/market/exchange-map.d.ts +3 -0
  357. package/dist/market/index.d.ts +4 -0
  358. package/dist/market/market-calendar.d.ts +4 -0
  359. package/dist/market/market-definition.d.ts +22 -0
  360. package/dist/mockServiceWorker.js +349 -0
  361. package/dist/renderers/area.d.ts +17 -0
  362. package/dist/renderers/bar-ohlc.d.ts +17 -0
  363. package/dist/renderers/baseline-delta-mountain.d.ts +22 -0
  364. package/dist/renderers/baseline.d.ts +19 -0
  365. package/dist/renderers/candlestick.d.ts +21 -0
  366. package/dist/renderers/canvas-renderer.d.ts +28 -0
  367. package/dist/renderers/colored-line.d.ts +15 -0
  368. package/dist/renderers/colored-mountain.d.ts +18 -0
  369. package/dist/renderers/column.d.ts +14 -0
  370. package/dist/renderers/high-low.d.ts +14 -0
  371. package/dist/renderers/histogram.d.ts +16 -0
  372. package/dist/renderers/hlc-area.d.ts +16 -0
  373. package/dist/renderers/hollow-candle.d.ts +18 -0
  374. package/dist/renderers/kagi.d.ts +22 -0
  375. package/dist/renderers/line-break.d.ts +20 -0
  376. package/dist/renderers/line.d.ts +17 -0
  377. package/dist/renderers/point-figure.d.ts +20 -0
  378. package/dist/renderers/renderer.d.ts +59 -0
  379. package/dist/renderers/renko.d.ts +24 -0
  380. package/dist/renderers/step-line.d.ts +14 -0
  381. package/dist/renderers/text-cache.d.ts +23 -0
  382. package/dist/renderers/volume-candle.d.ts +20 -0
  383. package/dist/renderers/webgl/area-webgl.d.ts +28 -0
  384. package/dist/renderers/webgl/candlestick-webgl.d.ts +30 -0
  385. package/dist/renderers/webgl/index.d.ts +7 -0
  386. package/dist/renderers/webgl/line-webgl.d.ts +23 -0
  387. package/dist/renderers/webgl/webgl-utils.d.ts +23 -0
  388. package/dist/timezone/index.d.ts +2 -0
  389. package/dist/timezone/timezone.d.ts +12 -0
  390. package/dist/transforms/aggregate.d.ts +2 -0
  391. package/dist/transforms/heikin-ashi.d.ts +2 -0
  392. package/dist/transforms/index.d.ts +2 -0
  393. package/dist/ui/context-menu.d.ts +14 -0
  394. package/dist/ui/hud.d.ts +43 -0
  395. package/dist/ui/settings-popup.d.ts +15 -0
  396. package/package.json +129 -0
@@ -0,0 +1,2 @@
1
+ var i=class{constructor(i,t){this._scrollStartX=0,this._savedRightOffset=0,this._isPanning=!1,this._activePointerId=-1,this._positions=[],this._kineticRafId=null,this._timeScale=i,this._requestInvalidation=t}onPointerDown(i,t,s){this._cancelKinetic(),this._isPanning=!0,this._activePointerId=s,this._scrollStartX=i,this._savedRightOffset=this._timeScale.rightOffset,this._positions=[{x:i,time:performance.now()}]}onPointerMove(i,t,s){if(!this._isPanning||s!==this._activePointerId)return;this._timeScale.scrollTo(this._scrollStartX,i,this._savedRightOffset);const n=performance.now();this._positions.push({x:i,time:n}),this._positions.length>4&&this._positions.shift(),this._requestInvalidation()}onPointerUp(i){if(i!==this._activePointerId||!this._isPanning)return;this._isPanning=!1,this._activePointerId=-1;const t=this._computeVelocity();Math.abs(t)>.5&&this._startKinetic(t)}onWheel(i,t,s){const n=-Math.sign(s);0!==n&&(this._timeScale.zoomAt(i,n),this._requestInvalidation())}destroy(){this._cancelKinetic(),this._isPanning=!1,this._activePointerId=-1,this._positions=[]}_computeVelocity(){if(this._positions.length<2)return 0;const i=this._positions[0],t=this._positions[this._positions.length-1],s=t.time-i.time;return 0===s?0:(t.x-i.x)/s*16}_startKinetic(i){let t=Math.max(-80,Math.min(80,i));const s=()=>{t*=.92,Math.abs(t)<.5?this._kineticRafId=null:(this._timeScale.scrollByPixels(-t),this._requestInvalidation(),this._kineticRafId=requestAnimationFrame(s))};this._kineticRafId=requestAnimationFrame(s)}_cancelKinetic(){null!==this._kineticRafId&&(cancelAnimationFrame(this._kineticRafId),this._kineticRafId=null)}};export{i as PanZoomHandler};
2
+ //# sourceMappingURL=index17.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index17.js","names":[],"sources":["../src/interactions/pan-zoom.ts"],"sourcesContent":["import type { EventHandler } from './event-router';\nimport type { TimeScale } from '../core/time-scale';\n\n/**\n * Kinetic scrolling constants.\n * TV uses 0.997 damping but measures velocity in bars/ms. We measure in px/frame (~16ms),\n * so we use a more aggressive damping to prevent excessively long scroll-after-release.\n */\nconst KINETIC_DAMPING = 0.92;\nconst KINETIC_MIN_VELOCITY = 0.5;\nconst KINETIC_MAX_VELOCITY = 80; // px per frame cap\n/** Number of recent positions to track for velocity calculation. */\nconst KINETIC_TRACK_COUNT = 4;\n\ninterface TrackedPosition {\n x: number;\n time: number;\n}\n\n/**\n * Pan and zoom handler for chart navigation.\n *\n * Pan:\n * - On pointer down: store scrollStartX and savedRightOffset\n * - On pointer move: timeScale.scrollTo(scrollStartX, currentX, savedRightOffset)\n * - Dragging right → x increases → shift is negative → rightOffset decreases\n * → chart moves toward future/recent data.\n *\n * Zoom (wheel):\n * - TV negates deltaY and clamps to ±1 for the zoom scale.\n * - timeScale.zoomAt(x, scale)\n */\nexport class PanZoomHandler implements EventHandler {\n private _timeScale: TimeScale;\n private _requestInvalidation: () => void;\n\n private _scrollStartX: number = 0;\n private _savedRightOffset: number = 0;\n private _isPanning: boolean = false;\n private _activePointerId: number = -1;\n\n /** Track last N positions for kinetic velocity calculation. */\n private _positions: TrackedPosition[] = [];\n\n private _kineticRafId: number | null = null;\n\n constructor(timeScale: TimeScale, requestInvalidation: () => void) {\n this._timeScale = timeScale;\n this._requestInvalidation = requestInvalidation;\n }\n\n onPointerDown(x: number, _y: number, pointerId: number): void {\n this._cancelKinetic();\n this._isPanning = true;\n this._activePointerId = pointerId;\n this._scrollStartX = x;\n this._savedRightOffset = this._timeScale.rightOffset;\n this._positions = [{ x, time: performance.now() }];\n }\n\n onPointerMove(x: number, _y: number, pointerId: number): void {\n if (!this._isPanning || pointerId !== this._activePointerId) return;\n\n this._timeScale.scrollTo(this._scrollStartX, x, this._savedRightOffset);\n\n // Track position for kinetic velocity\n const now = performance.now();\n this._positions.push({ x, time: now });\n if (this._positions.length > KINETIC_TRACK_COUNT) {\n this._positions.shift();\n }\n\n this._requestInvalidation();\n }\n\n onPointerUp(pointerId: number): void {\n if (pointerId !== this._activePointerId || !this._isPanning) return;\n this._isPanning = false;\n this._activePointerId = -1;\n\n // Compute velocity from tracked positions\n const velocity = this._computeVelocity();\n\n if (Math.abs(velocity) > KINETIC_MIN_VELOCITY) {\n this._startKinetic(velocity);\n }\n }\n\n onWheel(x: number, _y: number, deltaY: number): void {\n // Negate deltaY and clamp to ±1 for zoom scale\n const scale = -Math.sign(deltaY);\n if (scale === 0) return;\n this._timeScale.zoomAt(x, scale);\n this._requestInvalidation();\n }\n\n destroy(): void {\n this._cancelKinetic();\n this._isPanning = false;\n this._activePointerId = -1;\n this._positions = [];\n }\n\n // ── Private helpers ────────────────────────────────────────────────────────\n\n /**\n * Compute velocity (pixels per millisecond) from tracked positions,\n * then convert to pixels-per-frame (~16ms).\n */\n private _computeVelocity(): number {\n if (this._positions.length < 2) return 0;\n const first = this._positions[0];\n const last = this._positions[this._positions.length - 1];\n const dt = last.time - first.time;\n if (dt === 0) return 0;\n // pixels per ms, scaled to ~16ms frame\n return ((last.x - first.x) / dt) * 16;\n }\n\n private _startKinetic(initialVelocity: number): void {\n let velocity = Math.max(-KINETIC_MAX_VELOCITY, Math.min(KINETIC_MAX_VELOCITY, initialVelocity));\n\n const step = () => {\n velocity *= KINETIC_DAMPING;\n\n if (Math.abs(velocity) < KINETIC_MIN_VELOCITY) {\n this._kineticRafId = null;\n return;\n }\n\n // Negative velocity = dragging left = showing older data\n // scrollByPixels with negative = rightOffset decreases = showing newer data\n // We want kinetic to continue in the direction of the drag, so negate:\n this._timeScale.scrollByPixels(-velocity);\n this._requestInvalidation();\n this._kineticRafId = requestAnimationFrame(step);\n };\n\n this._kineticRafId = requestAnimationFrame(step);\n }\n\n private _cancelKinetic(): void {\n if (this._kineticRafId !== null) {\n cancelAnimationFrame(this._kineticRafId);\n this._kineticRafId = null;\n }\n }\n}\n"],"mappings":"AAQA,IAwBa,EAAb,MAcE,WAAA,CAAY,EAAsB,sBAVF,yBACI,mBACN,yBACK,kBAGK,sBAED,KAGrC,KAAK,WAAa,EAClB,KAAK,qBAAuB,EAG9B,aAAA,CAAc,EAAW,EAAY,GACnC,KAAK,iBACL,KAAK,YAAa,EAClB,KAAK,iBAAmB,EACxB,KAAK,cAAgB,EACrB,KAAK,kBAAoB,KAAK,WAAW,YACzC,KAAK,WAAa,CAAC,CAAE,IAAG,KAAM,YAAY,QAG5C,aAAA,CAAc,EAAW,EAAY,GACnC,IAAK,KAAK,YAAc,IAAc,KAAK,iBAAkB,OAE7D,KAAK,WAAW,SAAS,KAAK,cAAe,EAAG,KAAK,mBAGrD,MAAM,EAAM,YAAY,MACxB,KAAK,WAAW,KAAK,CAAE,IAAG,KAAM,IAC5B,KAAK,WAAW,OAxDI,GAyDtB,KAAK,WAAW,QAGlB,KAAK,uBAGP,WAAA,CAAY,GACV,GAAI,IAAc,KAAK,mBAAqB,KAAK,WAAY,OAC7D,KAAK,YAAa,EAClB,KAAK,kBAAmB,EAGxB,MAAM,EAAW,KAAK,mBAElB,KAAK,IAAI,GA1EY,IA2EvB,KAAK,cAAc,GAIvB,OAAA,CAAQ,EAAW,EAAY,GAE7B,MAAM,GAAS,KAAK,KAAK,GACX,IAAV,IACJ,KAAK,WAAW,OAAO,EAAG,GAC1B,KAAK,wBAGP,OAAA,GACE,KAAK,iBACL,KAAK,YAAa,EAClB,KAAK,kBAAmB,EACxB,KAAK,WAAa,GASpB,gBAAA,GACE,GAAI,KAAK,WAAW,OAAS,EAAG,OAAO,EACvC,MAAM,EAAQ,KAAK,WAAW,GACxB,EAAO,KAAK,WAAW,KAAK,WAAW,OAAS,GAChD,EAAK,EAAK,KAAO,EAAM,KAC7B,OAAW,IAAP,EAAiB,GAEZ,EAAK,EAAI,EAAM,GAAK,EAAM,GAGrC,aAAA,CAAsB,GACpB,IAAI,EAAW,KAAK,KA9GK,GA8GsB,KAAK,IA9G3B,GA8GqD,IAE9E,MAAM,EAAA,KACJ,GAnHkB,IAqHd,KAAK,IAAI,GApHU,GAqHrB,KAAK,cAAgB,MAOvB,KAAK,WAAW,gBAAgB,GAChC,KAAK,uBACL,KAAK,cAAgB,sBAAsB,KAG7C,KAAK,cAAgB,sBAAsB,GAG7C,cAAA,GAC6B,OAAvB,KAAK,gBACP,qBAAqB,KAAK,eAC1B,KAAK,cAAgB"}
@@ -0,0 +1,2 @@
1
+ var e=class{constructor(e,i,t,s,a,r=""){this._crosshair=e,this._dataLayer=i,this._timeScale=t,this._priceScale=s,this._requestInvalidation=a,this._sourcePaneId=r}setSourcePaneId(e){this._sourcePaneId=e}setPriceScale(e){this._priceScale=e}onPointerMove(e,i,t){const s=this._dataLayer.store;if(0===s.length)return this._crosshair.hide(),void this._requestInvalidation();const a=this._timeScale.xToIndex(e),r=Math.max(0,Math.min(s.length-1,a)),h=this._timeScale.indexToX(r),n=this._priceScale.yToPrice(i),o=s.time[r];this._crosshair.update({x:e,y:i,barIndex:r,price:n,time:o,snappedX:h,sourcePaneId:this._sourcePaneId}),this._requestInvalidation()}onPointerUp(e){this._crosshair.hide(),this._requestInvalidation()}};export{e as CrosshairHandler};
2
+ //# sourceMappingURL=index18.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index18.js","names":[],"sources":["../src/interactions/crosshair.ts"],"sourcesContent":["import type { EventHandler } from './event-router';\nimport type { Crosshair } from '../core/crosshair';\nimport type { DataLayer } from '../core/data-layer';\nimport type { TimeScale } from '../core/time-scale';\nimport type { PriceScale } from '../core/price-scale';\n\nexport class CrosshairHandler implements EventHandler {\n private _crosshair: Crosshair;\n private _dataLayer: DataLayer;\n private _timeScale: TimeScale;\n private _priceScale: PriceScale;\n private _requestInvalidation: () => void;\n private _sourcePaneId: string;\n\n constructor(\n crosshair: Crosshair,\n dataLayer: DataLayer,\n timeScale: TimeScale,\n priceScale: PriceScale,\n requestInvalidation: () => void,\n sourcePaneId: string = '',\n ) {\n this._crosshair = crosshair;\n this._dataLayer = dataLayer;\n this._timeScale = timeScale;\n this._priceScale = priceScale;\n this._requestInvalidation = requestInvalidation;\n this._sourcePaneId = sourcePaneId;\n }\n\n /** Update the source pane ID (used when pointer moves between panes). */\n setSourcePaneId(paneId: string): void {\n this._sourcePaneId = paneId;\n }\n\n /** Update the price scale (used when crosshair moves to a different pane). */\n setPriceScale(priceScale: PriceScale): void {\n this._priceScale = priceScale;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onPointerMove(x: number, y: number, _pointerId: number): void {\n const store = this._dataLayer.store;\n if (store.length === 0) {\n this._crosshair.hide();\n this._requestInvalidation();\n return;\n }\n\n // Convert x pixel to nearest bar index\n const rawIndex = this._timeScale.xToIndex(x);\n const barIndex = Math.max(0, Math.min(store.length - 1, rawIndex));\n\n // Snap x to the bar center\n const snappedX = this._timeScale.indexToX(barIndex);\n\n // Convert y pixel to price\n const price = this._priceScale.yToPrice(y);\n\n const time = store.time[barIndex];\n\n this._crosshair.update({\n x,\n y,\n barIndex,\n price,\n time,\n snappedX,\n sourcePaneId: this._sourcePaneId,\n });\n\n this._requestInvalidation();\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onPointerUp(_pointerId: number): void {\n this._crosshair.hide();\n this._requestInvalidation();\n }\n}\n"],"mappings":"AAMA,IAAa,EAAb,MAQE,WAAA,CACE,EACA,EACA,EACA,EACA,EACA,EAAuB,IAEvB,KAAK,WAAa,EAClB,KAAK,WAAa,EAClB,KAAK,WAAa,EAClB,KAAK,YAAc,EACnB,KAAK,qBAAuB,EAC5B,KAAK,cAAgB,EAIvB,eAAA,CAAgB,GACd,KAAK,cAAgB,EAIvB,aAAA,CAAc,GACZ,KAAK,YAAc,EAIrB,aAAA,CAAc,EAAW,EAAW,GAClC,MAAM,EAAQ,KAAK,WAAW,MAC9B,GAAqB,IAAjB,EAAM,OAGR,OAFA,KAAK,WAAW,YAChB,KAAK,uBAKP,MAAM,EAAW,KAAK,WAAW,SAAS,GACpC,EAAW,KAAK,IAAI,EAAG,KAAK,IAAI,EAAM,OAAS,EAAG,IAGlD,EAAW,KAAK,WAAW,SAAS,GAGpC,EAAQ,KAAK,YAAY,SAAS,GAElC,EAAO,EAAM,KAAK,GAExB,KAAK,WAAW,OAAO,CACrB,IACA,IACA,WACA,QACA,OACA,WACA,aAAc,KAAK,gBAGrB,KAAK,uBAIP,WAAA,CAAY,GACV,KAAK,WAAW,OAChB,KAAK"}
@@ -0,0 +1,2 @@
1
+ function e(e,t,n){const o=document.querySelector("[data-fin-charter-ctx-menu]");o&&o.remove();const r=document.createElement("div");r.setAttribute("data-fin-charter-ctx-menu",""),r.style.cssText=`position:fixed;left:${t.x}px;top:${t.y}px;z-index:1000;background:${n.bg};color:${n.text};border:1px solid ${n.border};border-radius:4px;box-shadow:0 4px 12px rgba(0,0,0,0.3);padding:4px 0;min-width:180px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,sans-serif;`;for(const a of e){if(a.separator){const e=document.createElement("div");e.style.cssText=`height:1px;background:${n.border};margin:4px 0;`,r.appendChild(e)}const e=document.createElement("div");if(e.style.cssText="padding:6px 12px;cursor:pointer;display:flex;align-items:center;gap:8px;white-space:nowrap;",e.addEventListener("mouseenter",()=>{e.style.background=n.border}),e.addEventListener("mouseleave",()=>{e.style.background="transparent"}),a.icon){const t=document.createElementNS("http://www.w3.org/2000/svg","svg");t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("width","14"),t.setAttribute("height","14"),t.style.cssText="fill:currentColor;flex-shrink:0;";const n=document.createElementNS("http://www.w3.org/2000/svg","path");n.setAttribute("d",a.icon),t.appendChild(n),e.appendChild(t)}const t=document.createElement("span");t.textContent=a.label,e.appendChild(t),e.addEventListener("click",()=>{a.action(),r.remove(),i()}),r.appendChild(e)}const d=e=>{r.contains(e.target)||(r.remove(),i())},s=e=>{"Escape"===e.key&&(r.remove(),i())},i=()=>{document.removeEventListener("mousedown",d,!0),document.removeEventListener("keydown",s,!0)};return requestAnimationFrame(()=>{document.addEventListener("mousedown",d,!0),document.addEventListener("keydown",s,!0)}),document.body.appendChild(r),r}export{e as createContextMenu};
2
+ //# sourceMappingURL=index19.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index19.js","names":[],"sources":["../src/ui/context-menu.ts"],"sourcesContent":["export interface ContextMenuItem {\n label: string;\n icon?: string; // SVG path data (MDI icon)\n action: () => void;\n separator?: boolean; // render a divider line before this item\n}\n\nexport function createContextMenu(\n items: ContextMenuItem[],\n position: { x: number; y: number },\n theme: { bg: string; text: string; border: string },\n): HTMLDivElement {\n // Remove any existing context menu to prevent stacking\n const existing = document.querySelector('[data-fin-charter-ctx-menu]');\n if (existing) existing.remove();\n\n const menu = document.createElement('div');\n menu.setAttribute('data-fin-charter-ctx-menu', '');\n menu.style.cssText =\n `position:fixed;left:${position.x}px;top:${position.y}px;z-index:1000;` +\n `background:${theme.bg};color:${theme.text};border:1px solid ${theme.border};` +\n `border-radius:4px;box-shadow:0 4px 12px rgba(0,0,0,0.3);padding:4px 0;` +\n `min-width:180px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,sans-serif;`;\n\n for (const item of items) {\n if (item.separator) {\n const sep = document.createElement('div');\n sep.style.cssText = `height:1px;background:${theme.border};margin:4px 0;`;\n menu.appendChild(sep);\n }\n\n const row = document.createElement('div');\n row.style.cssText =\n `padding:6px 12px;cursor:pointer;display:flex;align-items:center;gap:8px;white-space:nowrap;`;\n row.addEventListener('mouseenter', () => { row.style.background = theme.border; });\n row.addEventListener('mouseleave', () => { row.style.background = 'transparent'; });\n\n if (item.icon) {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('width', '14');\n svg.setAttribute('height', '14');\n svg.style.cssText = 'fill:currentColor;flex-shrink:0;';\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute('d', item.icon);\n svg.appendChild(path);\n row.appendChild(svg);\n }\n\n const label = document.createElement('span');\n label.textContent = item.label;\n row.appendChild(label);\n\n row.addEventListener('click', () => { item.action(); menu.remove(); cleanup(); });\n menu.appendChild(row);\n }\n\n // Close on outside click or Escape\n const onOutsideClick = (e: MouseEvent) => {\n if (!menu.contains(e.target as Node)) { menu.remove(); cleanup(); }\n };\n const onEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') { menu.remove(); cleanup(); }\n };\n const cleanup = () => {\n document.removeEventListener('mousedown', onOutsideClick, true);\n document.removeEventListener('keydown', onEscape, true);\n };\n requestAnimationFrame(() => {\n document.addEventListener('mousedown', onOutsideClick, true);\n document.addEventListener('keydown', onEscape, true);\n });\n\n document.body.appendChild(menu);\n return menu;\n}\n"],"mappings":"AAOA,SAAgB,EACd,EACA,EACA,GAGA,MAAM,EAAW,SAAS,cAAc,+BACpC,GAAU,EAAS,SAEvB,MAAM,EAAO,SAAS,cAAc,OACpC,EAAK,aAAa,4BAA6B,IAC/C,EAAK,MAAM,QACT,uBAAuB,EAAS,WAAW,EAAS,+BACtC,EAAM,YAAY,EAAM,yBAAyB,EAAM,uKAIvE,IAAK,MAAM,KAAQ,EAAO,CACxB,GAAI,EAAK,UAAW,CAClB,MAAM,EAAM,SAAS,cAAc,OACnC,EAAI,MAAM,QAAU,yBAAyB,EAAM,uBACnD,EAAK,YAAY,GAGnB,MAAM,EAAM,SAAS,cAAc,OAMnC,GALA,EAAI,MAAM,QACR,8FACF,EAAI,iBAAiB,aAAA,KAAsB,EAAI,MAAM,WAAa,EAAM,SACxE,EAAI,iBAAiB,aAAA,KAAsB,EAAI,MAAM,WAAa,gBAE9D,EAAK,KAAM,CACb,MAAM,EAAM,SAAS,gBAAgB,6BAA8B,OACnE,EAAI,aAAa,UAAW,aAC5B,EAAI,aAAa,QAAS,MAC1B,EAAI,aAAa,SAAU,MAC3B,EAAI,MAAM,QAAU,mCACpB,MAAM,EAAO,SAAS,gBAAgB,6BAA8B,QACpE,EAAK,aAAa,IAAK,EAAK,MAC5B,EAAI,YAAY,GAChB,EAAI,YAAY,GAGlB,MAAM,EAAQ,SAAS,cAAc,QACrC,EAAM,YAAc,EAAK,MACzB,EAAI,YAAY,GAEhB,EAAI,iBAAiB,QAAA,KAAiB,EAAK,SAAU,EAAK,SAAU,MACpE,EAAK,YAAY,GAInB,MAAM,EAAkB,IACjB,EAAK,SAAS,EAAE,UAAmB,EAAK,SAAU,MAEnD,EAAY,IACF,WAAV,EAAE,MAAoB,EAAK,SAAU,MAErC,EAAA,KACJ,SAAS,oBAAoB,YAAa,GAAgB,GAC1D,SAAS,oBAAoB,UAAW,GAAU,IAQpD,OANA,sBAAA,KACE,SAAS,iBAAiB,YAAa,GAAgB,GACvD,SAAS,iBAAiB,UAAW,GAAU,KAGjD,SAAS,KAAK,YAAY,GACnB"}
package/dist/index2.js ADDED
@@ -0,0 +1,2 @@
1
+ function e(e){return{time:new Float64Array(e),open:new Float64Array(e),high:new Float64Array(e),low:new Float64Array(e),close:new Float64Array(e),volume:new Float64Array(e),length:0,capacity:e}}function o(o){const t=e(Math.max(Math.ceil(1.5*o.length),2048));t.length=o.length;for(let e=0;e<o.length;e++){const l=o[e];t.time[e]=l.time,t.open[e]=l.open,t.high[e]=l.high,t.low[e]=l.low,t.close[e]=l.close,t.volume[e]=l.volume??0}return t}var t={None:0,Cursor:1,Light:2,Full:3};export{t as InvalidationLevel,o as barsToColumnStore,e as createColumnStore};
2
+ //# sourceMappingURL=index2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index2.js","names":[],"sources":["../src/core/types.ts"],"sourcesContent":["// ─── Bar & Column Store ──────────────────────────────────────────────────────\n\nexport interface Bar {\n time: number;\n open: number;\n high: number;\n low: number;\n close: number;\n volume?: number;\n}\n\n/** Same fields as Bar but stored as typed arrays (column-oriented). */\nexport interface ColumnData {\n time: Float64Array;\n open: Float64Array;\n high: Float64Array;\n low: Float64Array;\n close: Float64Array;\n volume: Float64Array;\n}\n\nexport interface ColumnStore {\n time: Float64Array;\n open: Float64Array;\n high: Float64Array;\n low: Float64Array;\n close: Float64Array;\n volume: Float64Array;\n length: number;\n capacity: number;\n}\n\nexport function createColumnStore(capacity: number): ColumnStore {\n return {\n time: new Float64Array(capacity),\n open: new Float64Array(capacity),\n high: new Float64Array(capacity),\n low: new Float64Array(capacity),\n close: new Float64Array(capacity),\n volume: new Float64Array(capacity),\n length: 0,\n capacity,\n };\n}\n\nexport function barsToColumnStore(bars: Bar[]): ColumnStore {\n const capacity = Math.max(Math.ceil(bars.length * 1.5), 2048);\n const store = createColumnStore(capacity);\n store.length = bars.length;\n for (let i = 0; i < bars.length; i++) {\n const b = bars[i];\n store.time[i] = b.time;\n store.open[i] = b.open;\n store.high[i] = b.high;\n store.low[i] = b.low;\n store.close[i] = b.close;\n store.volume[i] = b.volume ?? 0;\n }\n return store;\n}\n\n// ─── Invalidation ────────────────────────────────────────────────────────────\n\nexport const InvalidationLevel = {\n None: 0,\n Cursor: 1,\n Light: 2,\n Full: 3,\n} as const;\n\nexport type InvalidationLevelValue = (typeof InvalidationLevel)[keyof typeof InvalidationLevel];\n\n// ─── Range types ─────────────────────────────────────────────────────────────\n\nexport interface VisibleRange {\n fromIdx: number;\n toIdx: number;\n}\n\nexport interface TimeRange {\n from: number;\n to: number;\n}\n\n// ─── Rendering primitives ─────────────────────────────────────────────────────\n\nexport type PathCommand =\n | { cmd: 'M'; x: number; y: number }\n | { cmd: 'L'; x: number; y: number }\n | { cmd: 'Z' }\n | { cmd: 'Q'; cpx: number; cpy: number; x: number; y: number }\n | { cmd: 'C'; cp1x: number; cp1y: number; cp2x: number; cp2y: number; x: number; y: number };\n\nexport interface GradientStop {\n offset: number;\n color: string;\n}\n\nexport interface Gradient {\n type: 'linear' | 'radial';\n stops: GradientStop[];\n}\n\nexport type RenderStyle = string | Gradient;\n\nexport const PrimitiveZOrder = {\n Bottom: 0,\n Normal: 1,\n Top: 2,\n} as const;\n\nexport type PrimitiveZOrderValue = (typeof PrimitiveZOrder)[keyof typeof PrimitiveZOrder];\n\n// ─── Plugin / Primitive interfaces ───────────────────────────────────────────\n\nexport type DataUpdateScope = 'full' | 'update';\n\nexport interface AttachedParams {\n requestUpdate(): void;\n}\n\nexport interface IRenderTarget {\n readonly canvas: HTMLCanvasElement;\n readonly context: CanvasRenderingContext2D;\n readonly width: number;\n readonly height: number;\n readonly pixelRatio: number;\n}\n\nexport interface IPaneRenderer {\n draw(target: IRenderTarget): void;\n drawBackground?(target: IRenderTarget): void;\n}\n\nexport interface IPaneView {\n renderer(): IPaneRenderer | null;\n zOrder?(): PrimitiveZOrderValue;\n}\n\nexport interface IPriceAxisView {\n text(): string;\n textColor(): string;\n backColor(): string;\n coordinate(): number;\n}\n\nexport interface ITimeAxisView {\n text(): string;\n coordinate(): number;\n}\n\nexport interface PrimitiveHitTestResult {\n cursorStyle?: string;\n externalId?: string;\n}\n\nexport interface ISeriesPrimitive {\n /** Called when the primitive is attached to a series. */\n attached?(params: AttachedParams): void;\n /** Called when the primitive is detached. */\n detached?(): void;\n /** Notifies the primitive of a data scope update. */\n updateAllViews?(): void;\n /** Returns pane views for this primitive. */\n paneViews?(): readonly IPaneView[];\n /** Returns price axis views. */\n priceAxisViews?(): readonly IPriceAxisView[];\n /** Returns time axis views. */\n timeAxisViews?(): readonly ITimeAxisView[];\n /** Hit-test at the given canvas coordinate. */\n hitTest?(x: number, y: number): PrimitiveHitTestResult | null;\n}\n\nexport interface IPanePrimitive {\n attached?(params: AttachedParams): void;\n detached?(): void;\n updateAllViews?(): void;\n paneViews?(): readonly IPaneView[];\n hitTest?(x: number, y: number): PrimitiveHitTestResult | null;\n}\n\n// ─── Series ──────────────────────────────────────────────────────────────────\n\nexport type SeriesType =\n | 'candlestick' | 'bar' | 'line' | 'area' | 'histogram' | 'baseline' | 'hollow-candle' | 'heikin-ashi'\n | 'step-line' | 'colored-line' | 'colored-mountain' | 'hlc-area' | 'high-low' | 'column'\n | 'volume-candle' | 'baseline-delta-mountain'\n | 'renko' | 'kagi' | 'line-break' | 'point-figure';\n\n// ─── Utility types ───────────────────────────────────────────────────────────\n\nexport type DeepPartial<T> = {\n [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];\n};\n"],"mappings":"AAgCA,SAAgB,EAAkB,GAChC,MAAO,CACL,KAAM,IAAI,aAAa,GACvB,KAAM,IAAI,aAAa,GACvB,KAAM,IAAI,aAAa,GACvB,IAAK,IAAI,aAAa,GACtB,MAAO,IAAI,aAAa,GACxB,OAAQ,IAAI,aAAa,GACzB,OAAQ,EACR,YAIJ,SAAgB,EAAkB,GAEhC,MAAM,EAAQ,EADG,KAAK,IAAI,KAAK,KAAmB,IAAd,EAAK,QAAe,OAExD,EAAM,OAAS,EAAK,OACpB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,IAAK,CACpC,MAAM,EAAI,EAAK,GACf,EAAM,KAAK,GAAK,EAAE,KAClB,EAAM,KAAK,GAAK,EAAE,KAClB,EAAM,KAAK,GAAK,EAAE,KAClB,EAAM,IAAI,GAAK,EAAE,IACjB,EAAM,MAAM,GAAK,EAAE,MACnB,EAAM,OAAO,GAAK,EAAE,QAAU,EAEhC,OAAO,EAKT,IAAa,EAAoB,CAC/B,KAAM,EACN,OAAQ,EACR,MAAO,EACP,KAAM"}
@@ -0,0 +1,2 @@
1
+ import{createContextMenu as t}from"./index19.js";var a=class{constructor(t){this._callbacks=t}onContextMenu(t,a){const e=this._callbacks,o=e.localToScreen(t,a);for(const{drawing:i,id:r}of e.getDrawings())if(i._hitTestDrawing(t,a))return this._showDrawingMenu(r,o),!0;const n=e.getPaneAtY(a);if(n&&n!==e.mainPaneId){const t=e.getIndicatorAtPane(n);if(t)return this._showIndicatorMenu(t.id,o),!0}return this._showChartMenu(o),!0}_showDrawingMenu(a,e){const o=this._callbacks;t([{label:"Edit",action:()=>o.editDrawing(a)},{label:"Duplicate",action:()=>o.duplicateDrawing(a)},{label:"Remove",action:()=>o.removeDrawing(a)},{label:"Bring to Front",action:()=>o.bringDrawingToFront(a),separator:!0},{label:"Send to Back",action:()=>o.sendDrawingToBack(a)}],e,o.theme)}_showIndicatorMenu(a,e){const o=this._callbacks;t([{label:"Settings",action:()=>o.openIndicatorSettings(a)},{label:"Hide",action:()=>o.toggleIndicatorVisibility(a)},{label:"Remove",action:()=>o.removeIndicator(a)}],e,o.theme)}_showChartMenu(a){const e=this._callbacks;t([{label:"Reset Zoom",action:()=>e.fitContent()},{label:"Scroll to Latest",action:()=>e.scrollToRealTime()},{label:"Toggle Crosshair",action:()=>e.toggleCrosshair(),separator:!0}],a,e.theme)}};export{a as ContextMenuHandler};
2
+ //# sourceMappingURL=index20.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index20.js","names":[],"sources":["../src/interactions/context-menu-handler.ts"],"sourcesContent":["import type { EventHandler } from './event-router';\nimport type { ContextMenuItem } from '../ui/context-menu';\nimport { createContextMenu } from '../ui/context-menu';\nimport { BaseDrawing } from '../drawings/base';\n\nexport interface ContextMenuCallbacks {\n getDrawings(): { drawing: BaseDrawing; id: string }[];\n getIndicatorAtPane(paneId: string): { id: string; label: string } | null;\n getPaneAtY(y: number): string | null;\n mainPaneId: string;\n editDrawing(id: string): void;\n removeDrawing(id: string): void;\n duplicateDrawing(id: string): void;\n bringDrawingToFront(id: string): void;\n sendDrawingToBack(id: string): void;\n openIndicatorSettings(id: string): void;\n toggleIndicatorVisibility(id: string): void;\n removeIndicator(id: string): void;\n fitContent(): void;\n scrollToRealTime(): void;\n toggleCrosshair(): void;\n theme: { bg: string; text: string; border: string };\n localToScreen(x: number, y: number): { x: number; y: number };\n}\n\nexport class ContextMenuHandler implements EventHandler {\n private _callbacks: ContextMenuCallbacks;\n\n constructor(callbacks: ContextMenuCallbacks) {\n this._callbacks = callbacks;\n }\n\n onContextMenu(x: number, y: number): boolean {\n const cb = this._callbacks;\n const screenPos = cb.localToScreen(x, y);\n\n // 1. Check drawings\n for (const { drawing, id } of cb.getDrawings()) {\n const hit = drawing._hitTestDrawing(x, y);\n if (hit) { this._showDrawingMenu(id, screenPos); return true; }\n }\n\n // 2. Check indicator panes\n const paneId = cb.getPaneAtY(y);\n if (paneId && paneId !== cb.mainPaneId) {\n const indicator = cb.getIndicatorAtPane(paneId);\n if (indicator) { this._showIndicatorMenu(indicator.id, screenPos); return true; }\n }\n\n // 3. Empty chart area\n this._showChartMenu(screenPos);\n return true;\n }\n\n private _showDrawingMenu(id: string, pos: { x: number; y: number }): void {\n const cb = this._callbacks;\n createContextMenu([\n { label: 'Edit', action: () => cb.editDrawing(id) },\n { label: 'Duplicate', action: () => cb.duplicateDrawing(id) },\n { label: 'Remove', action: () => cb.removeDrawing(id) },\n { label: 'Bring to Front', action: () => cb.bringDrawingToFront(id), separator: true },\n { label: 'Send to Back', action: () => cb.sendDrawingToBack(id) },\n ], pos, cb.theme);\n }\n\n private _showIndicatorMenu(id: string, pos: { x: number; y: number }): void {\n const cb = this._callbacks;\n createContextMenu([\n { label: 'Settings', action: () => cb.openIndicatorSettings(id) },\n { label: 'Hide', action: () => cb.toggleIndicatorVisibility(id) },\n { label: 'Remove', action: () => cb.removeIndicator(id) },\n ], pos, cb.theme);\n }\n\n private _showChartMenu(pos: { x: number; y: number }): void {\n const cb = this._callbacks;\n createContextMenu([\n { label: 'Reset Zoom', action: () => cb.fitContent() },\n { label: 'Scroll to Latest', action: () => cb.scrollToRealTime() },\n { label: 'Toggle Crosshair', action: () => cb.toggleCrosshair(), separator: true },\n ], pos, cb.theme);\n }\n}\n"],"mappings":"iDAyBA,IAAa,EAAb,MAGE,WAAA,CAAY,GACV,KAAK,WAAa,EAGpB,aAAA,CAAc,EAAW,GACvB,MAAM,EAAK,KAAK,WACV,EAAY,EAAG,cAAc,EAAG,GAGtC,IAAK,MAAM,QAAE,EAAA,GAAS,KAAQ,EAAG,cAE/B,GADY,EAAQ,gBAAgB,EAAG,GACU,OAAtC,KAAK,iBAAiB,EAAI,IAAmB,EAI1D,MAAM,EAAS,EAAG,WAAW,GAC7B,GAAI,GAAU,IAAW,EAAG,WAAY,CACtC,MAAM,EAAY,EAAG,mBAAmB,GACxC,GAAI,EAA+D,OAAlD,KAAK,mBAAmB,EAAU,GAAI,IAAmB,EAK5E,OADA,KAAK,eAAe,IACb,EAGT,gBAAA,CAAyB,EAAY,GACnC,MAAM,EAAK,KAAK,WAChB,EAAkB,CAChB,CAAE,MAAO,OAAQ,OAAA,IAAc,EAAG,YAAY,IAC9C,CAAE,MAAO,YAAa,OAAA,IAAc,EAAG,iBAAiB,IACxD,CAAE,MAAO,SAAU,OAAA,IAAc,EAAG,cAAc,IAClD,CAAE,MAAO,iBAAkB,OAAA,IAAc,EAAG,oBAAoB,GAAK,WAAW,GAChF,CAAE,MAAO,eAAgB,OAAA,IAAc,EAAG,kBAAkB,KAC3D,EAAK,EAAG,OAGb,kBAAA,CAA2B,EAAY,GACrC,MAAM,EAAK,KAAK,WAChB,EAAkB,CAChB,CAAE,MAAO,WAAY,OAAA,IAAc,EAAG,sBAAsB,IAC5D,CAAE,MAAO,OAAQ,OAAA,IAAc,EAAG,0BAA0B,IAC5D,CAAE,MAAO,SAAU,OAAA,IAAc,EAAG,gBAAgB,KACnD,EAAK,EAAG,OAGb,cAAA,CAAuB,GACrB,MAAM,EAAK,KAAK,WAChB,EAAkB,CAChB,CAAE,MAAO,aAAc,OAAA,IAAc,EAAG,cACxC,CAAE,MAAO,mBAAoB,OAAA,IAAc,EAAG,oBAC9C,CAAE,MAAO,mBAAoB,OAAA,IAAc,EAAG,kBAAmB,WAAW,IAC3E,EAAK,EAAG"}
@@ -0,0 +1,2 @@
1
+ function t(t,i,e,s,n,h){const a=n-e,r=h-s,o=a*a+r*r;if(0===o)return Math.hypot(t-e,i-s);let l=((t-e)*a+(i-s)*r)/o;return l=Math.max(0,Math.min(1,l)),Math.hypot(t-(e+l*a),i-(s+l*r))}function i(t,i,e,s,n,h){return t>=Math.min(e,n)&&t<=Math.max(e,n)&&i>=Math.min(s,h)&&i<=Math.max(s,h)}function e(t,i){"dashed"===i?t.setLineDash([6,4]):"dotted"===i?t.setLineDash([2,3]):t.setLineDash([])}var s=class{constructor(t,i,e){this.selected=!1,this._ctx=null,this.id=t,this.points=i,this.options={color:"#2196F3",lineWidth:1,lineStyle:"solid",...e}}attached(t){}detached(){this._ctx=null}updateAllViews(){}paneViews(){return this._ctx?[this._createPaneView()]:[]}hitTest(t,i){const e=this._hitTestDrawing(t,i);return e?{cursorStyle:e.cursorStyle,externalId:e.drawingId}:null}drawingHitTest(t,i){return this._hitTestDrawing(t,i)}serialize(){return{type:this.drawingType,id:this.id,points:this.points.map(t=>({...t})),options:{...this.options}}}setContext(t){this._ctx=t}};export{s as BaseDrawing,e as applyLineStyle,t as distToSegment,i as pointInRect};
2
+ //# sourceMappingURL=index21.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index21.js","names":[],"sources":["../src/drawings/base.ts"],"sourcesContent":["import type { ISeriesPrimitive, IPaneView, IPaneRenderer, IRenderTarget, PrimitiveHitTestResult } from '../core/types';\nimport type { TimeScale } from '../core/time-scale';\nimport type { PriceScale } from '../core/price-scale';\n\n// ─── Hit-test threshold (CSS pixels) ────────────────────────────────────────\n\nexport const HIT_THRESHOLD = 6;\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport interface AnchorPoint {\n time: number;\n price: number;\n}\n\nexport interface DrawingOptions {\n color?: string;\n lineWidth?: number;\n lineStyle?: 'solid' | 'dashed' | 'dotted';\n fillColor?: string;\n text?: string;\n fontSize?: number;\n /** Whether to show labels on fibonacci and measurement tools. Defaults to true. */\n showLabels?: boolean;\n}\n\nexport interface SerializedDrawing {\n type: string;\n id: string;\n points: AnchorPoint[];\n options: DrawingOptions;\n}\n\nexport interface DrawingHitTestResult {\n drawingId: string;\n part: 'body' | 'handle1' | 'handle2' | 'handle3' | 'edge';\n cursorStyle: string;\n}\n\nexport interface DrawingPrimitive {\n readonly drawingType: string;\n readonly requiredPoints: number;\n points: AnchorPoint[];\n options: DrawingOptions;\n selected: boolean;\n serialize(): SerializedDrawing;\n drawingHitTest(x: number, y: number): DrawingHitTestResult | null;\n}\n\n/** Coordinate converters passed to drawings so they can map time/price to pixels. */\nexport interface DrawingContext {\n timeScale: TimeScale;\n priceScale: PriceScale;\n chartWidth: number;\n chartHeight: number;\n requestUpdate(): void;\n}\n\n// ─── Hit-test utilities ─────────────────────────────────────────────────────\n\n/** Distance from point (px,py) to the closest point on segment (x1,y1)-(x2,y2). */\nexport function distToSegment(\n px: number, py: number,\n x1: number, y1: number,\n x2: number, y2: number,\n): number {\n const dx = x2 - x1;\n const dy = y2 - y1;\n const lenSq = dx * dx + dy * dy;\n if (lenSq === 0) return Math.hypot(px - x1, py - y1);\n let t = ((px - x1) * dx + (py - y1) * dy) / lenSq;\n t = Math.max(0, Math.min(1, t));\n return Math.hypot(px - (x1 + t * dx), py - (y1 + t * dy));\n}\n\n/** Returns true if (px,py) is inside the axis-aligned rectangle defined by two corners. */\nexport function pointInRect(\n px: number, py: number,\n x1: number, y1: number,\n x2: number, y2: number,\n): boolean {\n const minX = Math.min(x1, x2);\n const maxX = Math.max(x1, x2);\n const minY = Math.min(y1, y2);\n const maxY = Math.max(y1, y2);\n return px >= minX && px <= maxX && py >= minY && py <= maxY;\n}\n\n// ─── Factory type ────────────────────────────────────────────────────────────\n\nexport type DrawingFactory = (\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n) => ISeriesPrimitive & DrawingPrimitive;\n\n// ─── Line-style helper ──────────────────────────────────────────────────────\n\nexport function applyLineStyle(ctx: CanvasRenderingContext2D, style: DrawingOptions['lineStyle']): void {\n if (style === 'dashed') {\n ctx.setLineDash([6, 4]);\n } else if (style === 'dotted') {\n ctx.setLineDash([2, 3]);\n } else {\n ctx.setLineDash([]);\n }\n}\n\n// ─── Base drawing class ─────────────────────────────────────────────────────\n\n/**\n * Abstract base that implements common ISeriesPrimitive + DrawingPrimitive plumbing.\n * Subclasses only override _createPaneView().\n */\nexport abstract class BaseDrawing implements ISeriesPrimitive, DrawingPrimitive {\n abstract readonly drawingType: string;\n abstract readonly requiredPoints: number;\n\n points: AnchorPoint[];\n options: DrawingOptions;\n selected: boolean = false;\n\n readonly id: string;\n protected _ctx: DrawingContext | null = null;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n this.id = id;\n this.points = points;\n this.options = { color: '#2196F3', lineWidth: 1, lineStyle: 'solid', ...options };\n }\n\n // ── ISeriesPrimitive ────────────────────────────────────────────────────\n\n attached(params: { requestUpdate(): void }): void {\n // DrawingContext is set externally via setContext()\n void params;\n }\n\n detached(): void {\n this._ctx = null;\n }\n\n updateAllViews(): void {\n // no-op; views re-read state each render\n }\n\n paneViews(): readonly IPaneView[] {\n if (!this._ctx) return [];\n return [this._createPaneView()];\n }\n\n hitTest(x: number, y: number): PrimitiveHitTestResult | null {\n const result = this._hitTestDrawing(x, y);\n if (!result) return null;\n return { cursorStyle: result.cursorStyle, externalId: result.drawingId };\n }\n\n // ── DrawingPrimitive ──────────────────────────────────────────────────\n\n drawingHitTest(x: number, y: number): DrawingHitTestResult | null {\n return this._hitTestDrawing(x, y);\n }\n\n serialize(): SerializedDrawing {\n return {\n type: this.drawingType,\n id: this.id,\n points: this.points.map(p => ({ ...p })),\n options: { ...this.options },\n };\n }\n\n /** Externally accessible hit-test returning DrawingHitTestResult. */\n abstract _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null;\n\n // ── Context setter ────────────────────────────────────────────────────\n\n setContext(ctx: DrawingContext): void {\n this._ctx = ctx;\n }\n\n // ── Abstract ──────────────────────────────────────────────────────────\n\n protected abstract _createPaneView(): IPaneView;\n}\n"],"mappings":"AA6DA,SAAgB,EACd,EAAY,EACZ,EAAY,EACZ,EAAY,GAEZ,MAAM,EAAK,EAAK,EACV,EAAK,EAAK,EACV,EAAQ,EAAK,EAAK,EAAK,EAC7B,GAAc,IAAV,EAAa,OAAO,KAAK,MAAM,EAAK,EAAI,EAAK,GACjD,IAAI,IAAM,EAAK,GAAM,GAAM,EAAK,GAAM,GAAM,EAE5C,OADA,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,IACrB,KAAK,MAAM,GAAM,EAAK,EAAI,GAAK,GAAM,EAAK,EAAI,IAIvD,SAAgB,EACd,EAAY,EACZ,EAAY,EACZ,EAAY,GAMZ,OAAO,GAJM,KAAK,IAAI,EAAI,IAIL,GAHR,KAAK,IAAI,EAAI,IAGS,GAFtB,KAAK,IAAI,EAAI,IAEuB,GADpC,KAAK,IAAI,EAAI,GAc5B,SAAgB,EAAe,EAA+B,GAC9C,WAAV,EACF,EAAI,YAAY,CAAC,EAAG,IACD,WAAV,EACT,EAAI,YAAY,CAAC,EAAG,IAEpB,EAAI,YAAY,IAUpB,IAAsB,EAAtB,MAWE,WAAA,CAAY,EAAY,EAAuB,kBAL3B,YAGoB,KAGtC,KAAK,GAAK,EACV,KAAK,OAAS,EACd,KAAK,QAAU,CAAE,MAAO,UAAW,UAAW,EAAG,UAAW,WAAY,GAK1E,QAAA,CAAS,GAAyC,CAKlD,QAAA,GACE,KAAK,KAAO,KAGd,cAAA,GAAuB,CAIvB,SAAA,GACE,OAAK,KAAK,KACH,CAAC,KAAK,mBADU,GAIzB,OAAA,CAAQ,EAAW,GACjB,MAAM,EAAS,KAAK,gBAAgB,EAAG,GACvC,OAAK,EACE,CAAE,YAAa,EAAO,YAAa,WAAY,EAAO,WADzC,KAMtB,cAAA,CAAe,EAAW,GACxB,OAAO,KAAK,gBAAgB,EAAG,GAGjC,SAAA,GACE,MAAO,CACL,KAAM,KAAK,YACX,GAAI,KAAK,GACT,OAAQ,KAAK,OAAO,IAAI,IAAA,IAAW,KACnC,QAAS,IAAK,KAAK,UASvB,UAAA,CAAW,GACT,KAAK,KAAO"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,applyLineStyle as e}from"./index21.js";var i=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="horizontal-line",this.requiredPoints=1}_hitTestDrawing(t,e){const i=this._ctx;if(!i||this.points.length<1)return null;const n=i.priceScale.priceToY(this.points[0].price);return Math.abs(e-n)<6?{drawingId:this.id,part:"body",cursorStyle:"ns-resize"}:null}_createPaneView(){const t=this;return{renderer(){const i=t._ctx;return!i||t.points.length<1?null:{draw(n){const{context:r,pixelRatio:o}=n,s=Math.round(i.priceScale.priceToY(t.points[0].price)*o),l=t.options.color??"#2196F3",c=(t.options.lineWidth??1)*o;if(r.save(),r.strokeStyle=l,r.lineWidth=c,e(r,t.options.lineStyle),r.beginPath(),r.moveTo(0,s),r.lineTo(n.width,s),r.stroke(),t.selected){r.fillStyle=l;const t=4*o;r.fillRect(n.width/2-t,s-t,2*t,2*t)}r.restore()}}}}}};function n(t,e,n){return new i(t,e,n)}export{n as createHorizontalLine};
2
+ //# sourceMappingURL=index22.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index22.js","names":[],"sources":["../src/drawings/horizontal-line.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nexport class HorizontalLineDrawing extends BaseDrawing {\n readonly drawingType = 'horizontal-line';\n readonly requiredPoints = 1;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 1) return null;\n const lineY = ctx.priceScale.priceToY(this.points[0].price);\n if (Math.abs(y - lineY) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'ns-resize' };\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 1) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const y = Math.round(ctx.priceScale.priceToY(self.points[0].price) * r);\n const color = self.options.color ?? '#2196F3';\n const lw = (self.options.lineWidth ?? 1) * r;\n\n c.save();\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n c.beginPath();\n c.moveTo(0, y);\n c.lineTo(target.width, y);\n c.stroke();\n\n if (self.selected) {\n c.fillStyle = color;\n const hs = 4 * r;\n c.fillRect(target.width / 2 - hs, y - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createHorizontalLine(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): HorizontalLineDrawing {\n return new HorizontalLineDrawing(id, points, options);\n}\n"],"mappings":"+DAUA,IAAa,EAAb,cAA2C,EAIzC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,oBAJG,sCACG,EAM1B,eAAA,CAAgB,EAAW,GACzB,MAAM,EAAM,KAAK,KACjB,IAAK,GAAO,KAAK,OAAO,OAAS,EAAG,OAAO,KAC3C,MAAM,EAAQ,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OACrD,OAAI,KAAK,IAAI,EAAI,GAAM,EACd,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,aAEnD,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,GAAM,EAChC,EAAI,KAAK,MAAM,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,GAC/D,EAAQ,EAAK,QAAQ,OAAS,UAC9B,GAAM,EAAK,QAAQ,WAAa,GAAK,EAW3C,GATA,EAAE,OACF,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAe,EAAG,EAAK,QAAQ,WAC/B,EAAE,YACF,EAAE,OAAO,EAAG,GACZ,EAAE,OAAO,EAAO,MAAO,GACvB,EAAE,SAEE,EAAK,SAAU,CACjB,EAAE,UAAY,EACd,MAAM,EAAK,EAAI,EACf,EAAE,SAAS,EAAO,MAAQ,EAAI,EAAI,EAAI,EAAS,EAAL,EAAa,EAAL,GAGpD,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAsB,EAAI,EAAQ"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,applyLineStyle as e}from"./index21.js";var i=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="vertical-line",this.requiredPoints=1}_hitTestDrawing(t,e){const i=this._ctx;if(!i||this.points.length<1)return null;const n=i.timeScale.indexToX(this.points[0].time);return Math.abs(t-n)<6?{drawingId:this.id,part:"body",cursorStyle:"ew-resize"}:null}_createPaneView(){const t=this;return{renderer(){const i=t._ctx;return!i||t.points.length<1?null:{draw(n){const{context:o,pixelRatio:r}=n,s=Math.round(i.timeScale.indexToX(t.points[0].time)*r),l=t.options.color??"#2196F3",c=(t.options.lineWidth??1)*r;if(o.save(),o.strokeStyle=l,o.lineWidth=c,e(o,t.options.lineStyle),o.beginPath(),o.moveTo(s,0),o.lineTo(s,n.height),o.stroke(),t.selected){o.fillStyle=l;const t=4*r;o.fillRect(s-t,n.height/2-t,2*t,2*t)}o.restore()}}}}}};function n(t,e,n){return new i(t,e,n)}export{n as createVerticalLine};
2
+ //# sourceMappingURL=index23.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index23.js","names":[],"sources":["../src/drawings/vertical-line.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nexport class VerticalLineDrawing extends BaseDrawing {\n readonly drawingType = 'vertical-line';\n readonly requiredPoints = 1;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 1) return null;\n const lineX = ctx.timeScale.indexToX(this.points[0].time);\n if (Math.abs(x - lineX) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'ew-resize' };\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 1) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const x = Math.round(ctx.timeScale.indexToX(self.points[0].time) * r);\n const color = self.options.color ?? '#2196F3';\n const lw = (self.options.lineWidth ?? 1) * r;\n\n c.save();\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n c.beginPath();\n c.moveTo(x, 0);\n c.lineTo(x, target.height);\n c.stroke();\n\n if (self.selected) {\n c.fillStyle = color;\n const hs = 4 * r;\n c.fillRect(x - hs, target.height / 2 - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createVerticalLine(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): VerticalLineDrawing {\n return new VerticalLineDrawing(id, points, options);\n}\n"],"mappings":"+DAUA,IAAa,EAAb,cAAyC,EAIvC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,oBAJG,oCACG,EAM1B,eAAA,CAAgB,EAAW,GACzB,MAAM,EAAM,KAAK,KACjB,IAAK,GAAO,KAAK,OAAO,OAAS,EAAG,OAAO,KAC3C,MAAM,EAAQ,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MACpD,OAAI,KAAK,IAAI,EAAI,GAAM,EACd,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,aAEnD,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,GAAM,EAChC,EAAI,KAAK,MAAM,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,GAC7D,EAAQ,EAAK,QAAQ,OAAS,UAC9B,GAAM,EAAK,QAAQ,WAAa,GAAK,EAW3C,GATA,EAAE,OACF,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAe,EAAG,EAAK,QAAQ,WAC/B,EAAE,YACF,EAAE,OAAO,EAAG,GACZ,EAAE,OAAO,EAAG,EAAO,QACnB,EAAE,SAEE,EAAK,SAAU,CACjB,EAAE,UAAY,EACd,MAAM,EAAK,EAAI,EACf,EAAE,SAAS,EAAI,EAAI,EAAO,OAAS,EAAI,EAAS,EAAL,EAAa,EAAL,GAGrD,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAoB,EAAI,EAAQ"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as e,applyLineStyle as t,distToSegment as i}from"./index21.js";var r=class extends e{constructor(e,t,i){super(e,t,i),this.drawingType="trendline",this.requiredPoints=2}_hitTestDrawing(e,t){const r=this._ctx;if(!r||this.points.length<2)return null;const n=r.timeScale.indexToX(this.points[0].time),o=r.priceScale.priceToY(this.points[0].price),s=r.timeScale.indexToX(this.points[1].time),c=r.priceScale.priceToY(this.points[1].price);return Math.hypot(e-n,t-o)<6?{drawingId:this.id,part:"handle1",cursorStyle:"grab"}:Math.hypot(e-s,t-c)<6?{drawingId:this.id,part:"handle2",cursorStyle:"grab"}:i(e,t,n,o,s,c)<6?{drawingId:this.id,part:"body",cursorStyle:"move"}:null}_createPaneView(){const e=this;return{renderer(){const i=e._ctx;return!i||e.points.length<2?null:{draw(r){const{context:n,pixelRatio:o}=r,s=i.timeScale.indexToX(e.points[0].time)*o,c=i.priceScale.priceToY(e.points[0].price)*o,l=i.timeScale.indexToX(e.points[1].time)*o,p=i.priceScale.priceToY(e.points[1].price)*o,a=e.options.color??"#2196F3",d=(e.options.lineWidth??1)*o;if(n.save(),n.strokeStyle=a,n.lineWidth=d,t(n,e.options.lineStyle),n.beginPath(),n.moveTo(s,c),n.lineTo(l,p),n.stroke(),e.selected){n.fillStyle=a;const e=4*o;n.fillRect(s-e,c-e,2*e,2*e),n.fillRect(l-e,p-e,2*e,2*e)}n.restore()}}}}}};function n(e,t,i){return new r(e,t,i)}export{n as createTrendline};
2
+ //# sourceMappingURL=index24.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index24.js","names":[],"sources":["../src/drawings/trendline.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n distToSegment,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nexport class TrendlineDrawing extends BaseDrawing {\n readonly drawingType = 'trendline';\n readonly requiredPoints = 2;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 2) return null;\n\n const x1 = ctx.timeScale.indexToX(this.points[0].time);\n const y1 = ctx.priceScale.priceToY(this.points[0].price);\n const x2 = ctx.timeScale.indexToX(this.points[1].time);\n const y2 = ctx.priceScale.priceToY(this.points[1].price);\n\n // Check handles first\n if (Math.hypot(x - x1, y - y1) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle1', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - x2, y - y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle2', cursorStyle: 'grab' };\n }\n\n if (distToSegment(x, y, x1, y1, x2, y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 2) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const x1 = ctx.timeScale.indexToX(self.points[0].time) * r;\n const y1 = ctx.priceScale.priceToY(self.points[0].price) * r;\n const x2 = ctx.timeScale.indexToX(self.points[1].time) * r;\n const y2 = ctx.priceScale.priceToY(self.points[1].price) * r;\n const color = self.options.color ?? '#2196F3';\n const lw = (self.options.lineWidth ?? 1) * r;\n\n c.save();\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n c.beginPath();\n c.moveTo(x1, y1);\n c.lineTo(x2, y2);\n c.stroke();\n\n if (self.selected) {\n c.fillStyle = color;\n const hs = 4 * r;\n c.fillRect(x1 - hs, y1 - hs, hs * 2, hs * 2);\n c.fillRect(x2 - hs, y2 - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createTrendline(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): TrendlineDrawing {\n return new TrendlineDrawing(id, points, options);\n}\n"],"mappings":"kFAWA,IAAa,EAAb,cAAsC,EAIpC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,oBAJG,gCACG,EAM1B,eAAA,CAAgB,EAAW,GACzB,MAAM,EAAM,KAAK,KACjB,IAAK,GAAO,KAAK,OAAO,OAAS,EAAG,OAAO,KAE3C,MAAM,EAAK,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MAC3C,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAC5C,EAAK,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MAC3C,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAGlD,OAAI,KAAK,MAAM,EAAI,EAAI,EAAI,GAAG,EACrB,CAAE,UAAW,KAAK,GAAI,KAAM,UAAW,YAAa,QAEzD,KAAK,MAAM,EAAI,EAAI,EAAI,GAAG,EACrB,CAAE,UAAW,KAAK,GAAI,KAAM,UAAW,YAAa,QAGzD,EAAc,EAAG,EAAG,EAAI,EAAI,EAAI,GAAG,EAC9B,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,QAEnD,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,GAAM,EAChC,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EACrD,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EACrD,EAAQ,EAAK,QAAQ,OAAS,UAC9B,GAAM,EAAK,QAAQ,WAAa,GAAK,EAW3C,GATA,EAAE,OACF,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAe,EAAG,EAAK,QAAQ,WAC/B,EAAE,YACF,EAAE,OAAO,EAAI,GACb,EAAE,OAAO,EAAI,GACb,EAAE,SAEE,EAAK,SAAU,CACjB,EAAE,UAAY,EACd,MAAM,EAAK,EAAI,EACf,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GACrC,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GAGvC,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAiB,EAAI,EAAQ"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,applyLineStyle as e}from"./index21.js";var i=[0,.236,.382,.5,.618,.786,1],n=["0%","23.6%","38.2%","50%","61.8%","78.6%","100%"],o=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="fibonacci",this.requiredPoints=2}_getLevelYs(){const t=this._ctx;if(!t||this.points.length<2)return null;const e=t.priceScale.priceToY(this.points[0].price),n=t.priceScale.priceToY(this.points[1].price);return i.map(t=>e+(n-e)*t)}_hitTestDrawing(t,e){const i=this._getLevelYs();if(!i)return null;for(const n of i)if(Math.abs(e-n)<6)return{drawingId:this.id,part:"body",cursorStyle:"ns-resize"};return null}_createPaneView(){const t=this;return{renderer(){const o=t._ctx;return!o||t.points.length<2?null:{draw(r){const{context:s,pixelRatio:l,width:c}=r,p=o.priceScale.priceToY(t.points[0].price)*l,a=o.priceScale.priceToY(t.points[1].price)*l,h=t.options.color??"#FF9800",f=(t.options.lineWidth??1)*l,u=(t.options.fontSize??11)*l;s.save();const d=i.map(t=>p+(a-p)*t);for(let t=0;t<d.length-1;t++){s.fillStyle=h,s.globalAlpha=.06*(t%2==0?1:.5);const e=Math.min(d[t],d[t+1]),i=Math.max(d[t],d[t+1]);s.fillRect(0,e,c,i-e)}s.globalAlpha=1,s.strokeStyle=h,s.lineWidth=f,e(s,t.options.lineStyle),s.font=`${u}px sans-serif`,s.fillStyle=h,s.textBaseline="bottom";for(let t=0;t<d.length;t++){const e=d[t];s.beginPath(),s.moveTo(0,e),s.lineTo(c,e),s.stroke(),s.fillText(n[t],4*l,e-2*l)}s.restore()}}}}}};function r(t,e,i){return new o(t,e,i)}export{r as createFibonacci};
2
+ //# sourceMappingURL=index25.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index25.js","names":[],"sources":["../src/drawings/fibonacci.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nconst FIB_LEVELS = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1] as const;\nconst FIB_LABELS = ['0%', '23.6%', '38.2%', '50%', '61.8%', '78.6%', '100%'];\nconst FIB_FILL_ALPHA = 0.06;\n\nexport class FibonacciDrawing extends BaseDrawing {\n readonly drawingType = 'fibonacci';\n readonly requiredPoints = 2;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n private _getLevelYs(): number[] | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 2) return null;\n const p1 = ctx.priceScale.priceToY(this.points[0].price);\n const p2 = ctx.priceScale.priceToY(this.points[1].price);\n return FIB_LEVELS.map(l => p1 + (p2 - p1) * l);\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const levels = this._getLevelYs();\n if (!levels) return null;\n for (const ly of levels) {\n if (Math.abs(y - ly) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'ns-resize' };\n }\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 2) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r, width: w } = target;\n const p1y = ctx.priceScale.priceToY(self.points[0].price) * r;\n const p2y = ctx.priceScale.priceToY(self.points[1].price) * r;\n const color = self.options.color ?? '#FF9800';\n const lw = (self.options.lineWidth ?? 1) * r;\n const fontSize = (self.options.fontSize ?? 11) * r;\n\n c.save();\n\n // Compute level Y positions\n const levelYs = FIB_LEVELS.map(l => p1y + (p2y - p1y) * l);\n\n // Draw shaded zones between levels\n for (let i = 0; i < levelYs.length - 1; i++) {\n c.fillStyle = color;\n c.globalAlpha = FIB_FILL_ALPHA * (i % 2 === 0 ? 1 : 0.5);\n const top = Math.min(levelYs[i], levelYs[i + 1]);\n const bot = Math.max(levelYs[i], levelYs[i + 1]);\n c.fillRect(0, top, w, bot - top);\n }\n\n c.globalAlpha = 1;\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n c.font = `${fontSize}px sans-serif`;\n c.fillStyle = color;\n c.textBaseline = 'bottom';\n\n // Draw level lines and labels\n for (let i = 0; i < levelYs.length; i++) {\n const ly = levelYs[i];\n c.beginPath();\n c.moveTo(0, ly);\n c.lineTo(w, ly);\n c.stroke();\n c.fillText(FIB_LABELS[i], 4 * r, ly - 2 * r);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createFibonacci(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): FibonacciDrawing {\n return new FibonacciDrawing(id, points, options);\n}\n"],"mappings":"+DAUA,IAAM,EAAa,CAAC,EAAG,KAAO,KAAO,GAAK,KAAO,KAAO,GAClD,EAAa,CAAC,KAAM,QAAS,QAAS,MAAO,QAAS,QAAS,QAGxD,EAAb,cAAsC,EAIpC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,oBAJG,gCACG,EAM1B,WAAA,GACE,MAAM,EAAM,KAAK,KACjB,IAAK,GAAO,KAAK,OAAO,OAAS,EAAG,OAAO,KAC3C,MAAM,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAC5C,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAClD,OAAO,EAAW,IAAI,GAAK,GAAM,EAAK,GAAM,GAG9C,eAAA,CAAgB,EAAW,GACzB,MAAM,EAAS,KAAK,cACpB,IAAK,EAAQ,OAAO,KACpB,IAAK,MAAM,KAAM,EACf,GAAI,KAAK,IAAI,EAAI,GAAG,EAClB,MAAO,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,aAG5D,OAAO,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,EAAG,MAAO,GAAM,EAC1C,EAAM,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EACtD,EAAM,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EACtD,EAAQ,EAAK,QAAQ,OAAS,UAC9B,GAAM,EAAK,QAAQ,WAAa,GAAK,EACrC,GAAY,EAAK,QAAQ,UAAY,IAAM,EAEjD,EAAE,OAGF,MAAM,EAAU,EAAW,IAAI,GAAK,GAAO,EAAM,GAAO,GAGxD,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,OAAS,EAAG,IAAK,CAC3C,EAAE,UAAY,EACd,EAAE,YApDO,KAoDyB,EAAI,GAAM,EAAI,EAAI,IACpD,MAAM,EAAM,KAAK,IAAI,EAAQ,GAAI,EAAQ,EAAI,IACvC,EAAM,KAAK,IAAI,EAAQ,GAAI,EAAQ,EAAI,IAC7C,EAAE,SAAS,EAAG,EAAK,EAAG,EAAM,GAG9B,EAAE,YAAc,EAChB,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAe,EAAG,EAAK,QAAQ,WAC/B,EAAE,KAAO,GAAG,iBACZ,EAAE,UAAY,EACd,EAAE,aAAe,SAGjB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,OAAQ,IAAK,CACvC,MAAM,EAAK,EAAQ,GACnB,EAAE,YACF,EAAE,OAAO,EAAG,GACZ,EAAE,OAAO,EAAG,GACZ,EAAE,SACF,EAAE,SAAS,EAAW,GAAI,EAAI,EAAG,EAAK,EAAI,GAG5C,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAiB,EAAI,EAAQ"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as e,applyLineStyle as t,pointInRect as i}from"./index21.js";var o=class extends e{constructor(e,t,i){super(e,t,i),this.drawingType="rectangle",this.requiredPoints=2}_hitTestDrawing(e,t){const o=this._ctx;return!o||this.points.length<2?null:i(e,t,o.timeScale.indexToX(this.points[0].time),o.priceScale.priceToY(this.points[0].price),o.timeScale.indexToX(this.points[1].time),o.priceScale.priceToY(this.points[1].price))?{drawingId:this.id,part:"body",cursorStyle:"move"}:null}_createPaneView(){const e=this;return{renderer(){const i=e._ctx;return!i||e.points.length<2?null:{draw(o){const{context:n,pixelRatio:l}=o,r=i.timeScale.indexToX(e.points[0].time)*l,s=i.priceScale.priceToY(e.points[0].price)*l,c=i.timeScale.indexToX(e.points[1].time)*l,p=i.priceScale.priceToY(e.points[1].price)*l,a=e.options.color??"#2196F3",h=e.options.fillColor??a,d=(e.options.lineWidth??1)*l,m=Math.min(r,c),S=Math.min(s,p),u=Math.abs(c-r),x=Math.abs(p-s);if(n.save(),n.globalAlpha=.15,n.fillStyle=h,n.fillRect(m,S,u,x),n.globalAlpha=1,n.strokeStyle=a,n.lineWidth=d,t(n,e.options.lineStyle),n.strokeRect(m,S,u,x),e.selected){n.fillStyle=a;const e=4*l;n.fillRect(r-e,s-e,2*e,2*e),n.fillRect(c-e,p-e,2*e,2*e)}n.restore()}}}}}};function n(e,t,i){return new o(e,t,i)}export{n as createRectangle};
2
+ //# sourceMappingURL=index26.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index26.js","names":[],"sources":["../src/drawings/rectangle.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n pointInRect,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nconst FILL_ALPHA = 0.15;\n\nexport class RectangleDrawing extends BaseDrawing {\n readonly drawingType = 'rectangle';\n readonly requiredPoints = 2;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 2) return null;\n\n const x1 = ctx.timeScale.indexToX(this.points[0].time);\n const y1 = ctx.priceScale.priceToY(this.points[0].price);\n const x2 = ctx.timeScale.indexToX(this.points[1].time);\n const y2 = ctx.priceScale.priceToY(this.points[1].price);\n\n if (pointInRect(x, y, x1, y1, x2, y2)) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 2) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const x1 = ctx.timeScale.indexToX(self.points[0].time) * r;\n const y1 = ctx.priceScale.priceToY(self.points[0].price) * r;\n const x2 = ctx.timeScale.indexToX(self.points[1].time) * r;\n const y2 = ctx.priceScale.priceToY(self.points[1].price) * r;\n\n const color = self.options.color ?? '#2196F3';\n const fillColor = self.options.fillColor ?? color;\n const lw = (self.options.lineWidth ?? 1) * r;\n const rx = Math.min(x1, x2);\n const ry = Math.min(y1, y2);\n const rw = Math.abs(x2 - x1);\n const rh = Math.abs(y2 - y1);\n\n c.save();\n\n // Fill\n c.globalAlpha = FILL_ALPHA;\n c.fillStyle = fillColor;\n c.fillRect(rx, ry, rw, rh);\n\n // Stroke\n c.globalAlpha = 1;\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n c.strokeRect(rx, ry, rw, rh);\n\n // Selection handles\n if (self.selected) {\n c.fillStyle = color;\n const hs = 4 * r;\n c.fillRect(x1 - hs, y1 - hs, hs * 2, hs * 2);\n c.fillRect(x2 - hs, y2 - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createRectangle(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): RectangleDrawing {\n return new RectangleDrawing(id, points, options);\n}\n"],"mappings":"gFAUA,IAEa,EAAb,cAAsC,EAIpC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,oBAJG,gCACG,EAM1B,eAAA,CAAgB,EAAW,GACzB,MAAM,EAAM,KAAK,KACjB,OAAK,GAAO,KAAK,OAAO,OAAS,EAAU,KAOvC,EAAY,EAAG,EALR,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MACtC,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OACvC,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MACtC,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,QAGzC,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,QAEnD,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,GAAM,EAChC,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EACrD,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EAErD,EAAQ,EAAK,QAAQ,OAAS,UAC9B,EAAY,EAAK,QAAQ,WAAa,EACtC,GAAM,EAAK,QAAQ,WAAa,GAAK,EACrC,EAAK,KAAK,IAAI,EAAI,GAClB,EAAK,KAAK,IAAI,EAAI,GAClB,EAAK,KAAK,IAAI,EAAK,GACnB,EAAK,KAAK,IAAI,EAAK,GAiBzB,GAfA,EAAE,OAGF,EAAE,YAlDK,IAmDP,EAAE,UAAY,EACd,EAAE,SAAS,EAAI,EAAI,EAAI,GAGvB,EAAE,YAAc,EAChB,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAe,EAAG,EAAK,QAAQ,WAC/B,EAAE,WAAW,EAAI,EAAI,EAAI,GAGrB,EAAK,SAAU,CACjB,EAAE,UAAY,EACd,MAAM,EAAK,EAAI,EACf,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GACrC,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GAGvC,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAiB,EAAI,EAAQ"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,pointInRect as e}from"./index21.js";var o=class extends t{constructor(t,e,o){super(t,e,{fontSize:14,text:"",...o}),this.drawingType="text-annotation",this.requiredPoints=1,this._bbox=null}_hitTestDrawing(t,o){if(!this._bbox)return null;const{x:i,y:n,w:r,h:s}=this._bbox;return e(t,o,i,n,i+r,n+s)?{drawingId:this.id,part:"body",cursorStyle:"move"}:null}_createPaneView(){const t=this;return{renderer(){const e=t._ctx;return!e||t.points.length<1?null:{draw(o){const{context:i,pixelRatio:n}=o,r=t.options.text??"";if(!r)return;const s=t.options.fontSize??14,l=e.timeScale.indexToX(t.points[0].time),c=e.priceScale.priceToY(t.points[0].price);i.save(),i.font=s*n+"px sans-serif";const a=i.measureText(r),x=a.width/n,p=s;t._bbox={x:l-4,y:c-p-4,w:x+8,h:p+8};const h=l*n,u=c*n,d=4*n,f=a.width+2*d,b=s*n+2*d,w=t.options.color??"#2196F3",y=t.options.fillColor;y&&(i.globalAlpha=.85,i.fillStyle=y,i.fillRect(h-d,u-s*n-d,f,b),i.globalAlpha=1),i.fillStyle=w,i.textBaseline="bottom",i.fillText(r,h,u),t.selected&&(i.strokeStyle=w,i.lineWidth=n,i.setLineDash([3*n,2*n]),i.strokeRect(h-d,u-s*n-d,f,b)),i.restore()}}}}}};function i(t,e,i){return new o(t,e,i)}export{i as createTextAnnotation};
2
+ //# sourceMappingURL=index27.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index27.js","names":[],"sources":["../src/drawings/text-annotation.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n pointInRect,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nconst PADDING = 4;\nconst BG_ALPHA = 0.85;\n\nexport class TextAnnotationDrawing extends BaseDrawing {\n readonly drawingType = 'text-annotation';\n readonly requiredPoints = 1;\n\n // Cached bounding box in CSS pixels (updated each render)\n private _bbox: { x: number; y: number; w: number; h: number } | null = null;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, { fontSize: 14, text: '', ...options });\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n if (!this._bbox) return null;\n const { x: bx, y: by, w, h } = this._bbox;\n if (pointInRect(x, y, bx, by, bx + w, by + h)) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 1) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const text = self.options.text ?? '';\n if (!text) return;\n\n const fontSize = self.options.fontSize ?? 14;\n const anchorX = ctx.timeScale.indexToX(self.points[0].time);\n const anchorY = ctx.priceScale.priceToY(self.points[0].price);\n\n // Measure text in CSS pixels first\n c.save();\n c.font = `${fontSize * r}px sans-serif`;\n const metrics = c.measureText(text);\n const textW = metrics.width / r;\n const textH = fontSize;\n\n // Update bbox in CSS pixels for hit-testing\n self._bbox = {\n x: anchorX - PADDING,\n y: anchorY - textH - PADDING,\n w: textW + PADDING * 2,\n h: textH + PADDING * 2,\n };\n\n // Scaled coords\n const sx = anchorX * r;\n const sy = anchorY * r;\n const pad = PADDING * r;\n const bw = metrics.width + pad * 2;\n const bh = fontSize * r + pad * 2;\n\n // Background\n const color = self.options.color ?? '#2196F3';\n const fillColor = self.options.fillColor;\n if (fillColor) {\n c.globalAlpha = BG_ALPHA;\n c.fillStyle = fillColor;\n c.fillRect(sx - pad, sy - fontSize * r - pad, bw, bh);\n c.globalAlpha = 1;\n }\n\n // Text\n c.fillStyle = color;\n c.textBaseline = 'bottom';\n c.fillText(text, sx, sy);\n\n // Selection border\n if (self.selected) {\n c.strokeStyle = color;\n c.lineWidth = r;\n c.setLineDash([3 * r, 2 * r]);\n c.strokeRect(sx - pad, sy - fontSize * r - pad, bw, bh);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createTextAnnotation(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): TextAnnotationDrawing {\n return new TextAnnotationDrawing(id, points, options);\n}\n"],"mappings":"4DAUA,IAGa,EAAb,cAA2C,EAOzC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,CAAE,SAAU,GAAI,KAAM,MAAO,qBAP1B,sCACG,aAG6C,KAMvE,eAAA,CAAgB,EAAW,GACzB,IAAK,KAAK,MAAO,OAAO,KACxB,MAAQ,EAAG,EAAI,EAAG,EAAA,EAAI,EAAA,EAAG,GAAM,KAAK,MACpC,OAAI,EAAY,EAAG,EAAG,EAAI,EAAI,EAAK,EAAG,EAAK,GAClC,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,QAEnD,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,GAAM,EAChC,EAAO,EAAK,QAAQ,MAAQ,GAClC,IAAK,EAAM,OAEX,MAAM,EAAW,EAAK,QAAQ,UAAY,GACpC,EAAU,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAChD,EAAU,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAGvD,EAAE,OACF,EAAE,KAAU,EAAW,EAAd,gBACT,MAAM,EAAU,EAAE,YAAY,GACxB,EAAQ,EAAQ,MAAQ,EACxB,EAAQ,EAGd,EAAK,MAAQ,CACX,EAAG,EAhDD,EAiDF,EAAG,EAAU,EAjDX,EAkDF,EAAG,EAAQ,EACX,EAAG,EAAQ,GAIb,MAAM,EAAK,EAAU,EACf,EAAK,EAAU,EACf,EAzDF,EAyDkB,EAChB,EAAK,EAAQ,MAAc,EAAN,EACrB,EAAK,EAAW,EAAU,EAAN,EAGpB,EAAQ,EAAK,QAAQ,OAAS,UAC9B,EAAY,EAAK,QAAQ,UAC3B,IACF,EAAE,YAhEC,IAiEH,EAAE,UAAY,EACd,EAAE,SAAS,EAAK,EAAK,EAAK,EAAW,EAAI,EAAK,EAAI,GAClD,EAAE,YAAc,GAIlB,EAAE,UAAY,EACd,EAAE,aAAe,SACjB,EAAE,SAAS,EAAM,EAAI,GAGjB,EAAK,WACP,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAE,YAAY,CAAC,EAAI,EAAG,EAAI,IAC1B,EAAE,WAAW,EAAK,EAAK,EAAK,EAAW,EAAI,EAAK,EAAI,IAGtD,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAsB,EAAI,EAAQ"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,applyLineStyle as e,distToSegment as i}from"./index21.js";var n=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="ray",this.requiredPoints=2}_extendedEnd(t,e,i,n,r,o){const s=i-t,c=n-e;if(0===s&&0===c)return[i,n];let a=1e9;return s>0?a=Math.min(a,(r-t)/s):s<0&&(a=Math.min(a,-t/s)),c>0?a=Math.min(a,(o-e)/c):c<0&&(a=Math.min(a,-e/c)),[t+a*s,e+a*c]}_hitTestDrawing(t,e){const n=this._ctx;if(!n||this.points.length<2)return null;const r=n.timeScale.indexToX(this.points[0].time),o=n.priceScale.priceToY(this.points[0].price),s=n.timeScale.indexToX(this.points[1].time),c=n.priceScale.priceToY(this.points[1].price);if(Math.hypot(t-r,e-o)<6)return{drawingId:this.id,part:"handle1",cursorStyle:"grab"};if(Math.hypot(t-s,e-c)<6)return{drawingId:this.id,part:"handle2",cursorStyle:"grab"};const[a,h]=this._extendedEnd(r,o,s,c,n.chartWidth,n.chartHeight);return i(t,e,r,o,a,h)<6?{drawingId:this.id,part:"body",cursorStyle:"move"}:null}_createPaneView(){const t=this;return{renderer(){const i=t._ctx;return!i||t.points.length<2?null:{draw(n){const{context:r,pixelRatio:o}=n,s=i.timeScale.indexToX(t.points[0].time)*o,c=i.priceScale.priceToY(t.points[0].price)*o,a=i.timeScale.indexToX(t.points[1].time)*o,h=i.priceScale.priceToY(t.points[1].price)*o,l=n.width,p=n.height,d=t.options.color??"#2196F3",m=(t.options.lineWidth??1)*o,u=a-s,S=h-c;let x=1e9;u>0?x=Math.min(x,(l-s)/u):u<0&&(x=Math.min(x,-s/u)),S>0?x=Math.min(x,(p-c)/S):S<0&&(x=Math.min(x,-c/S));const g=s+x*u,T=c+x*S;if(r.save(),r.strokeStyle=d,r.lineWidth=m,e(r,t.options.lineStyle),r.beginPath(),r.moveTo(s,c),r.lineTo(g,T),r.stroke(),t.selected){r.fillStyle=d;const t=4*o;r.fillRect(s-t,c-t,2*t,2*t),r.fillRect(a-t,h-t,2*t,2*t)}r.restore()}}}}}};function r(t,e,i){return new n(t,e,i)}export{r as createRay};
2
+ //# sourceMappingURL=index28.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index28.js","names":[],"sources":["../src/drawings/ray.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n distToSegment,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nexport class RayDrawing extends BaseDrawing {\n readonly drawingType = 'ray';\n readonly requiredPoints = 2;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n /** Compute the point where the ray exits the chart bounds. */\n private _extendedEnd(\n x1: number, y1: number,\n x2: number, y2: number,\n w: number, h: number,\n ): [number, number] {\n const dx = x2 - x1;\n const dy = y2 - y1;\n if (dx === 0 && dy === 0) return [x2, y2];\n\n // Find the largest t such that p1 + t*(p2-p1) is still within [0,w] x [0,h]\n let tMax = 1e9;\n if (dx > 0) tMax = Math.min(tMax, (w - x1) / dx);\n else if (dx < 0) tMax = Math.min(tMax, -x1 / dx);\n if (dy > 0) tMax = Math.min(tMax, (h - y1) / dy);\n else if (dy < 0) tMax = Math.min(tMax, -y1 / dy);\n\n return [x1 + tMax * dx, y1 + tMax * dy];\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 2) return null;\n\n const x1 = ctx.timeScale.indexToX(this.points[0].time);\n const y1 = ctx.priceScale.priceToY(this.points[0].price);\n const x2 = ctx.timeScale.indexToX(this.points[1].time);\n const y2 = ctx.priceScale.priceToY(this.points[1].price);\n\n // Check handles first\n if (Math.hypot(x - x1, y - y1) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle1', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - x2, y - y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle2', cursorStyle: 'grab' };\n }\n\n const [ex, ey] = this._extendedEnd(x1, y1, x2, y2, ctx.chartWidth, ctx.chartHeight);\n if (distToSegment(x, y, x1, y1, ex, ey) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 2) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const x1 = ctx.timeScale.indexToX(self.points[0].time) * r;\n const y1 = ctx.priceScale.priceToY(self.points[0].price) * r;\n const x2 = ctx.timeScale.indexToX(self.points[1].time) * r;\n const y2 = ctx.priceScale.priceToY(self.points[1].price) * r;\n const w = target.width;\n const h = target.height;\n const color = self.options.color ?? '#2196F3';\n const lw = (self.options.lineWidth ?? 1) * r;\n\n const dx = x2 - x1;\n const dy = y2 - y1;\n let tMax = 1e9;\n if (dx > 0) tMax = Math.min(tMax, (w - x1) / dx);\n else if (dx < 0) tMax = Math.min(tMax, -x1 / dx);\n if (dy > 0) tMax = Math.min(tMax, (h - y1) / dy);\n else if (dy < 0) tMax = Math.min(tMax, -y1 / dy);\n const ex = x1 + tMax * dx;\n const ey = y1 + tMax * dy;\n\n c.save();\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n c.beginPath();\n c.moveTo(x1, y1);\n c.lineTo(ex, ey);\n c.stroke();\n\n if (self.selected) {\n c.fillStyle = color;\n const hs = 4 * r;\n c.fillRect(x1 - hs, y1 - hs, hs * 2, hs * 2);\n c.fillRect(x2 - hs, y2 - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createRay(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): RayDrawing {\n return new RayDrawing(id, points, options);\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,applyLineStyle as e,distToSegment as i}from"./index21.js";var n=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="arrow",this.requiredPoints=2}_hitTestDrawing(t,e){const n=this._ctx;if(!n||this.points.length<2)return null;const o=n.timeScale.indexToX(this.points[0].time),r=n.priceScale.priceToY(this.points[0].price),s=n.timeScale.indexToX(this.points[1].time),c=n.priceScale.priceToY(this.points[1].price);return Math.hypot(t-o,e-r)<6?{drawingId:this.id,part:"handle1",cursorStyle:"grab"}:Math.hypot(t-s,e-c)<6?{drawingId:this.id,part:"handle2",cursorStyle:"grab"}:i(t,e,o,r,s,c)<6?{drawingId:this.id,part:"body",cursorStyle:"move"}:null}_createPaneView(){const t=this;return{renderer(){const i=t._ctx;return!i||t.points.length<2?null:{draw(n){const{context:o,pixelRatio:r}=n,s=i.timeScale.indexToX(t.points[0].time)*r,c=i.priceScale.priceToY(t.points[0].price)*r,l=i.timeScale.indexToX(t.points[1].time)*r,a=i.priceScale.priceToY(t.points[1].price)*r,p=t.options.color??"#2196F3",h=(t.options.lineWidth??1)*r,d=10*r;o.save(),o.strokeStyle=p,o.fillStyle=p,o.lineWidth=h,e(o,t.options.lineStyle),o.beginPath(),o.moveTo(s,c),o.lineTo(l,a),o.stroke();const u=Math.atan2(a-c,l-s),T=Math.PI/6;if(o.setLineDash([]),o.beginPath(),o.moveTo(l,a),o.lineTo(l-d*Math.cos(u-T),a-d*Math.sin(u-T)),o.lineTo(l-d*Math.cos(u+T),a-d*Math.sin(u+T)),o.closePath(),o.fill(),t.selected){const t=4*r;o.fillRect(s-t,c-t,2*t,2*t),o.fillRect(l-t,a-t,2*t,2*t)}o.restore()}}}}}};function o(t,e,i){return new n(t,e,i)}export{o as createArrow};
2
+ //# sourceMappingURL=index29.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index29.js","names":[],"sources":["../src/drawings/arrow.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n distToSegment,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nexport class ArrowDrawing extends BaseDrawing {\n readonly drawingType = 'arrow';\n readonly requiredPoints = 2;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 2) return null;\n\n const x1 = ctx.timeScale.indexToX(this.points[0].time);\n const y1 = ctx.priceScale.priceToY(this.points[0].price);\n const x2 = ctx.timeScale.indexToX(this.points[1].time);\n const y2 = ctx.priceScale.priceToY(this.points[1].price);\n\n if (Math.hypot(x - x1, y - y1) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle1', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - x2, y - y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle2', cursorStyle: 'grab' };\n }\n\n if (distToSegment(x, y, x1, y1, x2, y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 2) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const x1 = ctx.timeScale.indexToX(self.points[0].time) * r;\n const y1 = ctx.priceScale.priceToY(self.points[0].price) * r;\n const x2 = ctx.timeScale.indexToX(self.points[1].time) * r;\n const y2 = ctx.priceScale.priceToY(self.points[1].price) * r;\n const color = self.options.color ?? '#2196F3';\n const lw = (self.options.lineWidth ?? 1) * r;\n const arrowSize = 10 * r;\n\n c.save();\n c.strokeStyle = color;\n c.fillStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n\n // Draw line\n c.beginPath();\n c.moveTo(x1, y1);\n c.lineTo(x2, y2);\n c.stroke();\n\n // Draw arrowhead at p2\n const angle = Math.atan2(y2 - y1, x2 - x1);\n const wingAngle = Math.PI / 6;\n c.setLineDash([]);\n c.beginPath();\n c.moveTo(x2, y2);\n c.lineTo(\n x2 - arrowSize * Math.cos(angle - wingAngle),\n y2 - arrowSize * Math.sin(angle - wingAngle),\n );\n c.lineTo(\n x2 - arrowSize * Math.cos(angle + wingAngle),\n y2 - arrowSize * Math.sin(angle + wingAngle),\n );\n c.closePath();\n c.fill();\n\n if (self.selected) {\n const hs = 4 * r;\n c.fillRect(x1 - hs, y1 - hs, hs * 2, hs * 2);\n c.fillRect(x2 - hs, y2 - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createArrow(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): ArrowDrawing {\n return new ArrowDrawing(id, points, options);\n}\n"],"mappings":"kFAWA,IAAa,EAAb,cAAkC,EAIhC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,oBAJG,4BACG,EAM1B,eAAA,CAAgB,EAAW,GACzB,MAAM,EAAM,KAAK,KACjB,IAAK,GAAO,KAAK,OAAO,OAAS,EAAG,OAAO,KAE3C,MAAM,EAAK,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MAC3C,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAC5C,EAAK,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MAC3C,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAElD,OAAI,KAAK,MAAM,EAAI,EAAI,EAAI,GAAG,EACrB,CAAE,UAAW,KAAK,GAAI,KAAM,UAAW,YAAa,QAEzD,KAAK,MAAM,EAAI,EAAI,EAAI,GAAG,EACrB,CAAE,UAAW,KAAK,GAAI,KAAM,UAAW,YAAa,QAGzD,EAAc,EAAG,EAAG,EAAI,EAAI,EAAI,GAAG,EAC9B,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,QAEnD,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,GAAM,EAChC,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EACrD,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EACrD,EAAQ,EAAK,QAAQ,OAAS,UAC9B,GAAM,EAAK,QAAQ,WAAa,GAAK,EACrC,EAAY,GAAK,EAEvB,EAAE,OACF,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAE,UAAY,EACd,EAAe,EAAG,EAAK,QAAQ,WAG/B,EAAE,YACF,EAAE,OAAO,EAAI,GACb,EAAE,OAAO,EAAI,GACb,EAAE,SAGF,MAAM,EAAQ,KAAK,MAAM,EAAK,EAAI,EAAK,GACjC,EAAY,KAAK,GAAK,EAe5B,GAdA,EAAE,YAAY,IACd,EAAE,YACF,EAAE,OAAO,EAAI,GACb,EAAE,OACA,EAAK,EAAY,KAAK,IAAI,EAAQ,GAClC,EAAK,EAAY,KAAK,IAAI,EAAQ,IAEpC,EAAE,OACA,EAAK,EAAY,KAAK,IAAI,EAAQ,GAClC,EAAK,EAAY,KAAK,IAAI,EAAQ,IAEpC,EAAE,YACF,EAAE,OAEE,EAAK,SAAU,CACjB,MAAM,EAAK,EAAI,EACf,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GACrC,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GAGvC,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAa,EAAI,EAAQ"}
package/dist/index3.js ADDED
@@ -0,0 +1,2 @@
1
+ var t={barSpacing:6,rightOffset:0,minBarSpacing:4,maxBarSpacing:50},i=class i{constructor(i){this._width=0,this._dataLength=0,this._rightOffset=0,this._options={...t,...i},this._barSpacing=this._options.barSpacing,this._rightOffset=this._options.rightOffset}get _baseIndex(){return this._dataLength-1}setOptions(t){this._options={...this._options,...t},void 0!==t.barSpacing&&(this._barSpacing=t.barSpacing),this._clampBarSpacing()}setWidth(t){this._width=t}setDataLength(t){this._dataLength=t}get barSpacing(){return this._barSpacing}get minBarSpacing(){return this._options.minBarSpacing}get maxBarSpacing(){return this._options.maxBarSpacing}setBarSpacing(t){this._barSpacing=Math.max(this._options.minBarSpacing,Math.min(this._options.maxBarSpacing,t)),this.correctOffset()}scrollBy(t){this.scrollByPixels(t)}get rightOffset(){return this._rightOffset}get dataLength(){return this._dataLength}visibleRange(){if(0===this._dataLength||0===this._width)return{fromIdx:0,toIdx:0};const t=this._width/this._barSpacing,i=this._baseIndex+this._rightOffset,s=i-t+1;return{fromIdx:Math.max(0,Math.ceil(s)),toIdx:Math.min(this._dataLength-1,Math.floor(i))}}indexToX(t){const i=this._baseIndex+this._rightOffset-t;return this._width-(i+.5)*this._barSpacing}xToIndex(t){const i=(this._width-t)/this._barSpacing-.5;return Math.round(this._baseIndex+this._rightOffset-i)}_floatIndexAtX(t){const i=(this._width-t)/this._barSpacing-.5;return this._baseIndex+this._rightOffset-i}scrollTo(t,i,s){this._rightOffset=s+(t-i)/this._barSpacing,this.correctOffset()}setRightOffset(t){this._rightOffset=t,this.correctOffset()}scrollToEnd(){this._rightOffset=this._options.rightOffset}scrollByPixels(t){this._rightOffset+=t/this._barSpacing,this.correctOffset()}scrollToPosition(t){this._rightOffset=t,this.correctOffset()}zoomAt(t,i){const s=this._floatIndexAtX(t),h=Math.max(this._options.minBarSpacing,Math.min(this._options.maxBarSpacing,this._barSpacing+i*(this._barSpacing/10)));if(h===this._barSpacing)return;this._barSpacing=h;const a=this._floatIndexAtX(t);this._rightOffset+=s-a,this.correctOffset()}fitContent(){0!==this._dataLength&&0!==this._width&&(this._barSpacing=Math.max(this._options.minBarSpacing,Math.min(this._options.maxBarSpacing,this._width/this._dataLength)),this._rightOffset=this._options.rightOffset)}correctOffset(){if(0===this._dataLength)return;const t=this._width/this._barSpacing-i.MIN_VISIBLE_BARS;this._rightOffset>t&&(this._rightOffset=t);const s=-(this._dataLength-i.MIN_VISIBLE_BARS);this._rightOffset<s&&(this._rightOffset=s)}_clampBarSpacing(){this._barSpacing=Math.min(this._options.maxBarSpacing,Math.max(this._options.minBarSpacing,this._barSpacing))}};i.MIN_VISIBLE_BARS=2;export{i as TimeScale};
2
+ //# sourceMappingURL=index3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index3.js","names":[],"sources":["../src/core/time-scale.ts"],"sourcesContent":["import type { VisibleRange } from './types';\n\nexport interface TimeScaleOptions {\n barSpacing: number;\n rightOffset: number;\n minBarSpacing: number;\n maxBarSpacing: number;\n}\n\nconst DEFAULT_OPTIONS: TimeScaleOptions = {\n barSpacing: 6,\n rightOffset: 0,\n minBarSpacing: 4,\n maxBarSpacing: 50,\n};\n\n/**\n * TimeScale managing horizontal bar layout and coordinate mapping.\n *\n * - `_rightOffset` = bars of empty space to the right of the last bar.\n * Default 0 means the last bar sits at the right edge.\n * - `_barSpacing` controls zoom level.\n * - Visible range: rightBorder = baseIndex + rightOffset,\n * leftBorder = rightBorder - width/barSpacing + 1\n * - indexToCoordinate: deltaFromRight = baseIndex + rightOffset - index;\n * x = width - (deltaFromRight + 0.5) * barSpacing\n * - Scrolling modifies rightOffset.\n * - Auto-scroll on new data: rightOffset stays constant, so new bars\n * naturally appear if the last bar was visible.\n */\nexport class TimeScale {\n // Minimum visible bars before can't scroll further\n private static readonly MIN_VISIBLE_BARS = 2;\n\n private _options: TimeScaleOptions;\n /** Canvas width in pixels. */\n private _width: number = 0;\n /** Total number of data bars. */\n private _dataLength: number = 0;\n /** Bars of space to the right of the last bar. */\n private _rightOffset: number = 0;\n /** Bar spacing (zoom level). Stored separately from options so zoomAt can mutate it without cloning options. */\n private _barSpacing: number;\n\n constructor(options?: Partial<TimeScaleOptions>) {\n this._options = { ...DEFAULT_OPTIONS, ...options };\n this._barSpacing = this._options.barSpacing;\n this._rightOffset = this._options.rightOffset;\n }\n\n // baseIndex = last bar index = dataLength - 1\n private get _baseIndex(): number {\n return this._dataLength - 1;\n }\n\n setOptions(options: Partial<TimeScaleOptions>): void {\n this._options = { ...this._options, ...options };\n if (options.barSpacing !== undefined) {\n this._barSpacing = options.barSpacing;\n }\n this._clampBarSpacing();\n }\n\n setWidth(width: number): void {\n this._width = width;\n }\n\n /**\n * Set data length.\n * Auto-scroll: rightOffset stays constant, so if the last bar was visible\n * before new data arrived, the new bar naturally appears.\n */\n setDataLength(length: number): void {\n this._dataLength = length;\n }\n\n get barSpacing(): number {\n return this._barSpacing;\n }\n\n get minBarSpacing(): number {\n return this._options.minBarSpacing;\n }\n\n get maxBarSpacing(): number {\n return this._options.maxBarSpacing;\n }\n\n /** Set bar spacing directly (clamped to min/max). */\n setBarSpacing(spacing: number): void {\n this._barSpacing = Math.max(\n this._options.minBarSpacing,\n Math.min(this._options.maxBarSpacing, spacing),\n );\n this.correctOffset();\n }\n\n /** Scroll by pixels (positive = scroll right, negative = scroll left). */\n scrollBy(deltaX: number): void {\n this.scrollByPixels(deltaX);\n }\n\n get rightOffset(): number {\n return this._rightOffset;\n }\n\n get dataLength(): number {\n return this._dataLength;\n }\n\n // ── Visible range ──────────────────────────────────────────────────────────\n\n /**\n * Compute the visible bar index range.\n * rightBorder = baseIndex + rightOffset\n * leftBorder = rightBorder - width/barSpacing + 1\n */\n visibleRange(): VisibleRange {\n if (this._dataLength === 0 || this._width === 0) {\n return { fromIdx: 0, toIdx: 0 };\n }\n\n const barsInView = this._width / this._barSpacing;\n const rightBorder = this._baseIndex + this._rightOffset;\n const leftBorder = rightBorder - barsInView + 1;\n\n return {\n fromIdx: Math.max(0, Math.ceil(leftBorder)),\n toIdx: Math.min(this._dataLength - 1, Math.floor(rightBorder)),\n };\n }\n\n // ── Coordinate conversion ─────────────────────────────────────────────────\n\n /**\n * Convert a bar index to the x-pixel of its center.\n * deltaFromRight = baseIndex + rightOffset - index\n * x = width - (deltaFromRight + 0.5) * barSpacing\n */\n indexToX(index: number): number {\n const deltaFromRight = this._baseIndex + this._rightOffset - index;\n return this._width - (deltaFromRight + 0.5) * this._barSpacing;\n }\n\n /**\n * Convert an x-pixel coordinate back to the nearest bar index (not clamped).\n * Inverse of indexToX.\n */\n xToIndex(x: number): number {\n const deltaFromRight = (this._width - x) / this._barSpacing - 0.5;\n return Math.round(this._baseIndex + this._rightOffset - deltaFromRight);\n }\n\n /**\n * Return the fractional (float) index at an x coordinate.\n * Used internally for zoom stabilization.\n */\n private _floatIndexAtX(x: number): number {\n const deltaFromRight = (this._width - x) / this._barSpacing - 0.5;\n return this._baseIndex + this._rightOffset - deltaFromRight;\n }\n\n // ── Scrolling ─────────────────────────────────────────────────────────────\n\n /**\n * Called by the pan handler. Computes the shift in logical bars from the\n * start position and applies it to the saved right offset.\n *\n * Dragging right → x increases → shift is negative → rightOffset decreases\n * → chart moves toward future/recent data.\n */\n scrollTo(startX: number, currentX: number, savedRightOffset: number): void {\n const shift = (startX - currentX) / this._barSpacing;\n this._rightOffset = savedRightOffset + shift;\n this.correctOffset();\n }\n\n /** Direct offset setter for kinetic scrolling etc. */\n setRightOffset(offset: number): void {\n this._rightOffset = offset;\n this.correctOffset();\n }\n\n /** Scroll so the last bar is visible at the right edge (reset to configured rightOffset). */\n scrollToEnd(): void {\n this._rightOffset = this._options.rightOffset;\n }\n\n /**\n * Scroll by pixel amount. Kept for backwards compatibility with\n * axis-drag, keyboard-nav, and kinetic scrolling.\n *\n * Positive deltaX → rightOffset increases → chart shifts to show older data.\n */\n scrollByPixels(deltaX: number): void {\n this._rightOffset += deltaX / this._barSpacing;\n this.correctOffset();\n }\n\n /**\n * Set scroll offset directly in bars.\n * Kept for backwards compatibility with keyboard-nav (Home key).\n */\n scrollToPosition(position: number): void {\n this._rightOffset = position;\n this.correctOffset();\n }\n\n // ── Zoom ──────────────────────────────────────────────────────────────────\n\n /**\n * Zoom keeping the point under cursor stable.\n * TV model: record float index under cursor, change barSpacing by\n * `scale * (barSpacing / 10)`, then adjust rightOffset so that index\n * stays at the same screen x.\n */\n zoomAt(x: number, scale: number): void {\n const oldIdx = this._floatIndexAtX(x);\n const newSpacing = Math.max(\n this._options.minBarSpacing,\n Math.min(this._options.maxBarSpacing, this._barSpacing + scale * (this._barSpacing / 10)),\n );\n if (newSpacing === this._barSpacing) return;\n this._barSpacing = newSpacing;\n const newIdx = this._floatIndexAtX(x);\n this._rightOffset += oldIdx - newIdx;\n this.correctOffset();\n }\n\n // ── Fit content ───────────────────────────────────────────────────────────\n\n /** Adjust barSpacing so all data bars fit exactly in the current width. */\n fitContent(): void {\n if (this._dataLength === 0 || this._width === 0) return;\n this._barSpacing = Math.max(\n this._options.minBarSpacing,\n Math.min(this._options.maxBarSpacing, this._width / this._dataLength),\n );\n this._rightOffset = this._options.rightOffset;\n }\n\n // ── Offset clamping ───────────────────────────────────────────────────────\n\n correctOffset(): void {\n if (this._dataLength === 0) return;\n\n const barsInView = this._width / this._barSpacing;\n\n // Max rightOffset: can't scroll so far left that fewer than MIN_VISIBLE_BARS are visible on the right\n const maxRightOffset = barsInView - TimeScale.MIN_VISIBLE_BARS;\n if (this._rightOffset > maxRightOffset) {\n this._rightOffset = maxRightOffset;\n }\n\n // Min rightOffset: can't scroll so far right that fewer than MIN_VISIBLE_BARS are visible on the left\n const minRightOffset = -(this._dataLength - TimeScale.MIN_VISIBLE_BARS);\n if (this._rightOffset < minRightOffset) {\n this._rightOffset = minRightOffset;\n }\n }\n\n // ── Private helpers ───────────────────────────────────────────────────────\n\n private _clampBarSpacing(): void {\n this._barSpacing = Math.min(\n this._options.maxBarSpacing,\n Math.max(this._options.minBarSpacing, this._barSpacing),\n );\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as e,applyLineStyle as i,distToSegment as t}from"./index21.js";var o=class extends e{constructor(e,i,t){super(e,i,t),this.drawingType="channel",this.requiredPoints=3}_hitTestDrawing(e,i){const o=this._ctx;if(!o||this.points.length<3)return null;const n=o.timeScale.indexToX(this.points[0].time),r=o.priceScale.priceToY(this.points[0].price),l=o.timeScale.indexToX(this.points[1].time),s=o.priceScale.priceToY(this.points[1].price),c=o.timeScale.indexToX(this.points[2].time),p=o.priceScale.priceToY(this.points[2].price),a=c-n,h=p-r,d=n+a,T=r+h,S=l+a,m=s+h;return Math.hypot(e-n,i-r)<6?{drawingId:this.id,part:"handle1",cursorStyle:"grab"}:Math.hypot(e-l,i-s)<6?{drawingId:this.id,part:"handle2",cursorStyle:"grab"}:Math.hypot(e-c,i-p)<6?{drawingId:this.id,part:"handle3",cursorStyle:"grab"}:t(e,i,n,r,l,s)<6||t(e,i,d,T,S,m)<6?{drawingId:this.id,part:"body",cursorStyle:"move"}:null}_createPaneView(){const e=this;return{renderer(){const t=e._ctx;return!t||e.points.length<3?null:{draw(o){const{context:n,pixelRatio:r}=o,l=t.timeScale.indexToX(e.points[0].time)*r,s=t.priceScale.priceToY(e.points[0].price)*r,c=t.timeScale.indexToX(e.points[1].time)*r,p=t.priceScale.priceToY(e.points[1].price)*r,a=t.timeScale.indexToX(e.points[2].time)*r,h=t.priceScale.priceToY(e.points[2].price)*r,d=a-l,T=h-s,S=l+d,m=s+T,g=c+d,u=p+T,x=e.options.color??"#2196F3",y=e.options.fillColor??x,f=(e.options.lineWidth??1)*r;if(n.save(),n.globalAlpha=.08,n.fillStyle=y,n.beginPath(),n.moveTo(l,s),n.lineTo(c,p),n.lineTo(g,u),n.lineTo(S,m),n.closePath(),n.fill(),n.globalAlpha=1,n.strokeStyle=x,n.lineWidth=f,i(n,e.options.lineStyle),n.beginPath(),n.moveTo(l,s),n.lineTo(c,p),n.stroke(),n.beginPath(),n.moveTo(S,m),n.lineTo(g,u),n.stroke(),e.selected){n.fillStyle=x;const e=4*r;n.fillRect(l-e,s-e,2*e,2*e),n.fillRect(c-e,p-e,2*e,2*e),n.fillRect(a-e,h-e,2*e,2*e)}n.restore()}}}}}};function n(e,i,t){return new o(e,i,t)}export{n as createChannel};
2
+ //# sourceMappingURL=index30.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index30.js","names":[],"sources":["../src/drawings/channel.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n distToSegment,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nconst FILL_ALPHA = 0.08;\n\nexport class ChannelDrawing extends BaseDrawing {\n readonly drawingType = 'channel';\n readonly requiredPoints = 3;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 3) return null;\n\n const x1 = ctx.timeScale.indexToX(this.points[0].time);\n const y1 = ctx.priceScale.priceToY(this.points[0].price);\n const x2 = ctx.timeScale.indexToX(this.points[1].time);\n const y2 = ctx.priceScale.priceToY(this.points[1].price);\n const x3 = ctx.timeScale.indexToX(this.points[2].time);\n const y3 = ctx.priceScale.priceToY(this.points[2].price);\n\n // Offset vector = p3 - p1\n const ox = x3 - x1;\n const oy = y3 - y1;\n\n // Second line: (p1+offset) -> (p2+offset)\n const sx1 = x1 + ox;\n const sy1 = y1 + oy;\n const sx2 = x2 + ox;\n const sy2 = y2 + oy;\n\n // Check handles\n if (Math.hypot(x - x1, y - y1) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle1', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - x2, y - y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle2', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - x3, y - y3) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle3', cursorStyle: 'grab' };\n }\n\n if (distToSegment(x, y, x1, y1, x2, y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n if (distToSegment(x, y, sx1, sy1, sx2, sy2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 3) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const x1 = ctx.timeScale.indexToX(self.points[0].time) * r;\n const y1 = ctx.priceScale.priceToY(self.points[0].price) * r;\n const x2 = ctx.timeScale.indexToX(self.points[1].time) * r;\n const y2 = ctx.priceScale.priceToY(self.points[1].price) * r;\n const x3 = ctx.timeScale.indexToX(self.points[2].time) * r;\n const y3 = ctx.priceScale.priceToY(self.points[2].price) * r;\n\n const ox = x3 - x1;\n const oy = y3 - y1;\n const sx1 = x1 + ox;\n const sy1 = y1 + oy;\n const sx2 = x2 + ox;\n const sy2 = y2 + oy;\n\n const color = self.options.color ?? '#2196F3';\n const fillColor = self.options.fillColor ?? color;\n const lw = (self.options.lineWidth ?? 1) * r;\n\n c.save();\n\n // Fill between lines\n c.globalAlpha = FILL_ALPHA;\n c.fillStyle = fillColor;\n c.beginPath();\n c.moveTo(x1, y1);\n c.lineTo(x2, y2);\n c.lineTo(sx2, sy2);\n c.lineTo(sx1, sy1);\n c.closePath();\n c.fill();\n\n // Draw both lines\n c.globalAlpha = 1;\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n\n c.beginPath();\n c.moveTo(x1, y1);\n c.lineTo(x2, y2);\n c.stroke();\n\n c.beginPath();\n c.moveTo(sx1, sy1);\n c.lineTo(sx2, sy2);\n c.stroke();\n\n // Selection handles\n if (self.selected) {\n c.fillStyle = color;\n const hs = 4 * r;\n c.fillRect(x1 - hs, y1 - hs, hs * 2, hs * 2);\n c.fillRect(x2 - hs, y2 - hs, hs * 2, hs * 2);\n c.fillRect(x3 - hs, y3 - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createChannel(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): ChannelDrawing {\n return new ChannelDrawing(id, points, options);\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,applyLineStyle as e}from"./index21.js";var i=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="ellipse",this.requiredPoints=2}_hitTestDrawing(t,e){const i=this._ctx;if(!i||this.points.length<2)return null;const r=i.timeScale.indexToX(this.points[0].time),n=i.priceScale.priceToY(this.points[0].price),o=i.timeScale.indexToX(this.points[1].time),l=i.priceScale.priceToY(this.points[1].price),s=(r+o)/2,a=(n+l)/2,c=Math.abs(o-r)/2,p=Math.abs(l-n)/2;if(c<1||p<1)return null;if(Math.hypot(t-r,e-n)<6)return{drawingId:this.id,part:"handle1",cursorStyle:"grab"};if(Math.hypot(t-o,e-l)<6)return{drawingId:this.id,part:"handle2",cursorStyle:"grab"};const h=c+6,d=p+6,u=t-s,S=e-a;return u*u/(h*h)+S*S/(d*d)<=1?{drawingId:this.id,part:"body",cursorStyle:"move"}:null}_createPaneView(){const t=this;return{renderer(){const i=t._ctx;return!i||t.points.length<2?null:{draw(r){const{context:n,pixelRatio:o}=r,l=i.timeScale.indexToX(t.points[0].time)*o,s=i.priceScale.priceToY(t.points[0].price)*o,a=i.timeScale.indexToX(t.points[1].time)*o,c=i.priceScale.priceToY(t.points[1].price)*o,p=(l+a)/2,h=(s+c)/2,d=Math.abs(a-l)/2,u=Math.abs(c-s)/2;if(d<1||u<1)return;const S=t.options.color??"#2196F3",f=t.options.fillColor??S,g=(t.options.lineWidth??1)*o;if(n.save(),n.beginPath(),n.ellipse(p,h,d,u,0,0,2*Math.PI),n.globalAlpha=.1,n.fillStyle=f,n.fill(),n.globalAlpha=1,n.strokeStyle=S,n.lineWidth=g,e(n,t.options.lineStyle),n.stroke(),t.selected){n.fillStyle=S;const t=4*o;n.fillRect(l-t,s-t,2*t,2*t),n.fillRect(a-t,c-t,2*t,2*t)}n.restore()}}}}}};function r(t,e,r){return new i(t,e,r)}export{r as createEllipse};
2
+ //# sourceMappingURL=index31.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index31.js","names":[],"sources":["../src/drawings/ellipse.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nconst FILL_ALPHA = 0.1;\n\nexport class EllipseDrawing extends BaseDrawing {\n readonly drawingType = 'ellipse';\n readonly requiredPoints = 2;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 2) return null;\n\n const x1 = ctx.timeScale.indexToX(this.points[0].time);\n const y1 = ctx.priceScale.priceToY(this.points[0].price);\n const x2 = ctx.timeScale.indexToX(this.points[1].time);\n const y2 = ctx.priceScale.priceToY(this.points[1].price);\n\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const rx = Math.abs(x2 - x1) / 2;\n const ry = Math.abs(y2 - y1) / 2;\n\n if (rx < 1 || ry < 1) return null;\n\n // Check handles\n if (Math.hypot(x - x1, y - y1) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle1', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - x2, y - y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle2', cursorStyle: 'grab' };\n }\n\n // Point-in-ellipse check (with threshold expansion)\n const rxT = rx + HIT_THRESHOLD;\n const ryT = ry + HIT_THRESHOLD;\n const dx = x - cx;\n const dy = y - cy;\n const distNorm = (dx * dx) / (rxT * rxT) + (dy * dy) / (ryT * ryT);\n if (distNorm <= 1) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 2) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const x1 = ctx.timeScale.indexToX(self.points[0].time) * r;\n const y1 = ctx.priceScale.priceToY(self.points[0].price) * r;\n const x2 = ctx.timeScale.indexToX(self.points[1].time) * r;\n const y2 = ctx.priceScale.priceToY(self.points[1].price) * r;\n\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const rx = Math.abs(x2 - x1) / 2;\n const ry = Math.abs(y2 - y1) / 2;\n\n if (rx < 1 || ry < 1) return;\n\n const color = self.options.color ?? '#2196F3';\n const fillColor = self.options.fillColor ?? color;\n const lw = (self.options.lineWidth ?? 1) * r;\n\n c.save();\n\n c.beginPath();\n c.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n\n // Fill\n c.globalAlpha = FILL_ALPHA;\n c.fillStyle = fillColor;\n c.fill();\n\n // Stroke\n c.globalAlpha = 1;\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n c.stroke();\n\n // Selection handles\n if (self.selected) {\n c.fillStyle = color;\n const hs = 4 * r;\n c.fillRect(x1 - hs, y1 - hs, hs * 2, hs * 2);\n c.fillRect(x2 - hs, y2 - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createEllipse(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): EllipseDrawing {\n return new EllipseDrawing(id, points, options);\n}\n"],"mappings":"+DAUA,IAEa,EAAb,cAAoC,EAIlC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,oBAJG,8BACG,EAM1B,eAAA,CAAgB,EAAW,GACzB,MAAM,EAAM,KAAK,KACjB,IAAK,GAAO,KAAK,OAAO,OAAS,EAAG,OAAO,KAE3C,MAAM,EAAK,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MAC3C,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAC5C,EAAK,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MAC3C,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAE5C,GAAM,EAAK,GAAM,EACjB,GAAM,EAAK,GAAM,EACjB,EAAK,KAAK,IAAI,EAAK,GAAM,EACzB,EAAK,KAAK,IAAI,EAAK,GAAM,EAE/B,GAAI,EAAK,GAAK,EAAK,EAAG,OAAO,KAG7B,GAAI,KAAK,MAAM,EAAI,EAAI,EAAI,GAAG,EAC5B,MAAO,CAAE,UAAW,KAAK,GAAI,KAAM,UAAW,YAAa,QAE7D,GAAI,KAAK,MAAM,EAAI,EAAI,EAAI,GAAG,EAC5B,MAAO,CAAE,UAAW,KAAK,GAAI,KAAM,UAAW,YAAa,QAI7D,MAAM,EAAM,EAAA,EACN,EAAM,EAAA,EACN,EAAK,EAAI,EACT,EAAK,EAAI,EAEf,OADkB,EAAK,GAAO,EAAM,GAAQ,EAAK,GAAO,EAAM,IAC9C,EACP,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,QAEnD,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,GAAM,EAChC,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EACrD,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EAErD,GAAM,EAAK,GAAM,EACjB,GAAM,EAAK,GAAM,EACjB,EAAK,KAAK,IAAI,EAAK,GAAM,EACzB,EAAK,KAAK,IAAI,EAAK,GAAM,EAE/B,GAAI,EAAK,GAAK,EAAK,EAAG,OAEtB,MAAM,EAAQ,EAAK,QAAQ,OAAS,UAC9B,EAAY,EAAK,QAAQ,WAAa,EACtC,GAAM,EAAK,QAAQ,WAAa,GAAK,EAoB3C,GAlBA,EAAE,OAEF,EAAE,YACF,EAAE,QAAQ,EAAI,EAAI,EAAI,EAAI,EAAG,EAAa,EAAV,KAAK,IAGrC,EAAE,YA7EK,GA8EP,EAAE,UAAY,EACd,EAAE,OAGF,EAAE,YAAc,EAChB,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAe,EAAG,EAAK,QAAQ,WAC/B,EAAE,SAGE,EAAK,SAAU,CACjB,EAAE,UAAY,EACd,MAAM,EAAK,EAAI,EACf,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GACrC,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GAGvC,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAe,EAAI,EAAQ"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as e,applyLineStyle as i,distToSegment as t}from"./index21.js";var o=class extends e{constructor(e,i,t){super(e,i,t),this.drawingType="pitchfork",this.requiredPoints=3}_extendLine(e,i,t,o,r){return[e+(t-e)*r,i+(o-i)*r]}_hitTestDrawing(e,i){const o=this._ctx;if(!o||this.points.length<3)return null;const r=o.timeScale.indexToX(this.points[0].time),n=o.priceScale.priceToY(this.points[0].price),s=o.timeScale.indexToX(this.points[1].time),c=o.priceScale.priceToY(this.points[1].price),l=o.timeScale.indexToX(this.points[2].time),p=o.priceScale.priceToY(this.points[2].price),a=(s+l)/2,h=(c+p)/2,[d,T]=this._extendLine(r,n,a,h,2),S=a-r,m=h-n,[u,x]=[s+S,c+m],[g,y]=[l+S,p+m];return Math.hypot(e-r,i-n)<6?{drawingId:this.id,part:"handle1",cursorStyle:"grab"}:Math.hypot(e-s,i-c)<6?{drawingId:this.id,part:"handle2",cursorStyle:"grab"}:Math.hypot(e-l,i-p)<6?{drawingId:this.id,part:"handle3",cursorStyle:"grab"}:t(e,i,r,n,d,T)<6||t(e,i,s,c,u,x)<6||t(e,i,l,p,g,y)<6?{drawingId:this.id,part:"body",cursorStyle:"move"}:null}_createPaneView(){const e=this;return{renderer(){const t=e._ctx;return!t||e.points.length<3?null:{draw(o){const{context:r,pixelRatio:n}=o,s=t.timeScale.indexToX(e.points[0].time)*n,c=t.priceScale.priceToY(e.points[0].price)*n,l=t.timeScale.indexToX(e.points[1].time)*n,p=t.priceScale.priceToY(e.points[1].price)*n,a=t.timeScale.indexToX(e.points[2].time)*n,h=t.priceScale.priceToY(e.points[2].price)*n,d=(l+a)/2-s,T=(p+h)/2-c,S=s+2*d,m=c+2*T,u=l+d,x=p+T,g=a+d,y=h+T,f=e.options.color??"#2196F3",w=(e.options.lineWidth??1)*n;if(r.save(),r.strokeStyle=f,r.lineWidth=w,i(r,e.options.lineStyle),r.beginPath(),r.moveTo(s,c),r.lineTo(S,m),r.stroke(),r.beginPath(),r.moveTo(l,p),r.lineTo(u,x),r.stroke(),r.beginPath(),r.moveTo(a,h),r.lineTo(g,y),r.stroke(),e.selected){r.fillStyle=f;const e=4*n;r.fillRect(s-e,c-e,2*e,2*e),r.fillRect(l-e,p-e,2*e,2*e),r.fillRect(a-e,h-e,2*e,2*e)}r.restore()}}}}}};function r(e,i,t){return new o(e,i,t)}export{r as createPitchfork};
2
+ //# sourceMappingURL=index32.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index32.js","names":[],"sources":["../src/drawings/pitchfork.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n distToSegment,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nexport class PitchforkDrawing extends BaseDrawing {\n readonly drawingType = 'pitchfork';\n readonly requiredPoints = 3;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n /** Given pivot (px,py), midpoint (mx,my), and extension factor, return end point. */\n private _extendLine(\n x1: number, y1: number,\n x2: number, y2: number,\n factor: number,\n ): [number, number] {\n return [x1 + (x2 - x1) * factor, y1 + (y2 - y1) * factor];\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 3) return null;\n\n const px = ctx.timeScale.indexToX(this.points[0].time);\n const py = ctx.priceScale.priceToY(this.points[0].price);\n const p2x = ctx.timeScale.indexToX(this.points[1].time);\n const p2y = ctx.priceScale.priceToY(this.points[1].price);\n const p3x = ctx.timeScale.indexToX(this.points[2].time);\n const p3y = ctx.priceScale.priceToY(this.points[2].price);\n\n // Midpoint of p2/p3\n const mx = (p2x + p3x) / 2;\n const my = (p2y + p3y) / 2;\n\n const [medEndX, medEndY] = this._extendLine(px, py, mx, my, 2);\n const dx = mx - px;\n const dy = my - py;\n const [upperEndX, upperEndY] = [p2x + dx, p2y + dy];\n const [lowerEndX, lowerEndY] = [p3x + dx, p3y + dy];\n\n // Check handles\n if (Math.hypot(x - px, y - py) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle1', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - p2x, y - p2y) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle2', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - p3x, y - p3y) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle3', cursorStyle: 'grab' };\n }\n\n if (distToSegment(x, y, px, py, medEndX, medEndY) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n if (distToSegment(x, y, p2x, p2y, upperEndX, upperEndY) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n if (distToSegment(x, y, p3x, p3y, lowerEndX, lowerEndY) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 3) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const px = ctx.timeScale.indexToX(self.points[0].time) * r;\n const py = ctx.priceScale.priceToY(self.points[0].price) * r;\n const p2x = ctx.timeScale.indexToX(self.points[1].time) * r;\n const p2y = ctx.priceScale.priceToY(self.points[1].price) * r;\n const p3x = ctx.timeScale.indexToX(self.points[2].time) * r;\n const p3y = ctx.priceScale.priceToY(self.points[2].price) * r;\n\n const mx = (p2x + p3x) / 2;\n const my = (p2y + p3y) / 2;\n const dx = mx - px;\n const dy = my - py;\n\n const medEndX = px + dx * 2;\n const medEndY = py + dy * 2;\n const upperEndX = p2x + dx;\n const upperEndY = p2y + dy;\n const lowerEndX = p3x + dx;\n const lowerEndY = p3y + dy;\n\n const color = self.options.color ?? '#2196F3';\n const lw = (self.options.lineWidth ?? 1) * r;\n\n c.save();\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n\n // Median line\n c.beginPath();\n c.moveTo(px, py);\n c.lineTo(medEndX, medEndY);\n c.stroke();\n\n // Upper tine\n c.beginPath();\n c.moveTo(p2x, p2y);\n c.lineTo(upperEndX, upperEndY);\n c.stroke();\n\n // Lower tine\n c.beginPath();\n c.moveTo(p3x, p3y);\n c.lineTo(lowerEndX, lowerEndY);\n c.stroke();\n\n // Selection handles\n if (self.selected) {\n c.fillStyle = color;\n const hs = 4 * r;\n c.fillRect(px - hs, py - hs, hs * 2, hs * 2);\n c.fillRect(p2x - hs, p2y - hs, hs * 2, hs * 2);\n c.fillRect(p3x - hs, p3y - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createPitchfork(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): PitchforkDrawing {\n return new PitchforkDrawing(id, points, options);\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,applyLineStyle as e}from"./index21.js";var i=[0,.618,1,1.618,2.618],n=["0%","61.8%","100%","161.8%","261.8%"],r=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="fib-projection",this.requiredPoints=3}_getLevelYs(){const t=this._ctx;if(!t||this.points.length<3)return null;const e=this.points[1].price-this.points[0].price;return i.map(i=>{const n=this.points[2].price+e*i;return t.priceScale.priceToY(n)})}_hitTestDrawing(t,e){const i=this._getLevelYs();if(!i)return null;for(const n of i)if(Math.abs(e-n)<6)return{drawingId:this.id,part:"body",cursorStyle:"ns-resize"};return null}_createPaneView(){const t=this;return{renderer(){const r=t._ctx;return!r||t.points.length<3?null:{draw(o){const{context:s,pixelRatio:l,width:c}=o,p=t.points[1].price-t.points[0].price,a=i.map(e=>{const i=t.points[2].price+p*e;return r.priceScale.priceToY(i)*l}),h=t.options.color??"#9C27B0",u=(t.options.lineWidth??1)*l,f=(t.options.fontSize??11)*l;s.save();for(let t=0;t<a.length-1;t++){s.fillStyle=h,s.globalAlpha=.06*(t%2==0?1:.5);const e=Math.min(a[t],a[t+1]),i=Math.max(a[t],a[t+1]);s.fillRect(0,e,c,i-e)}s.globalAlpha=1,s.strokeStyle=h,s.lineWidth=u,e(s,t.options.lineStyle),s.font=`${f}px sans-serif`,s.fillStyle=h,s.textBaseline="bottom";for(let t=0;t<a.length;t++){const e=a[t];s.beginPath(),s.moveTo(0,e),s.lineTo(c,e),s.stroke(),s.fillText(n[t],4*l,e-2*l)}s.restore()}}}}}};function o(t,e,i){return new r(t,e,i)}export{o as createFibProjection};
2
+ //# sourceMappingURL=index33.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index33.js","names":[],"sources":["../src/drawings/fib-projection.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nconst PROJ_LEVELS = [0, 0.618, 1, 1.618, 2.618] as const;\nconst PROJ_LABELS = ['0%', '61.8%', '100%', '161.8%', '261.8%'];\nconst FIB_FILL_ALPHA = 0.06;\n\nexport class FibProjectionDrawing extends BaseDrawing {\n readonly drawingType = 'fib-projection';\n readonly requiredPoints = 3;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n private _getLevelYs(): number[] | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 3) return null;\n const move = this.points[1].price - this.points[0].price;\n return PROJ_LEVELS.map(ratio => {\n const price = this.points[2].price + move * ratio;\n return ctx.priceScale.priceToY(price);\n });\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const levels = this._getLevelYs();\n if (!levels) return null;\n for (const ly of levels) {\n if (Math.abs(y - ly) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'ns-resize' };\n }\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 3) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r, width: w } = target;\n const move = self.points[1].price - self.points[0].price;\n const levelYs = PROJ_LEVELS.map(ratio => {\n const price = self.points[2].price + move * ratio;\n return ctx.priceScale.priceToY(price) * r;\n });\n\n const color = self.options.color ?? '#9C27B0';\n const lw = (self.options.lineWidth ?? 1) * r;\n const fontSize = (self.options.fontSize ?? 11) * r;\n\n c.save();\n\n // Draw shaded zones between levels\n for (let i = 0; i < levelYs.length - 1; i++) {\n c.fillStyle = color;\n c.globalAlpha = FIB_FILL_ALPHA * (i % 2 === 0 ? 1 : 0.5);\n const top = Math.min(levelYs[i], levelYs[i + 1]);\n const bot = Math.max(levelYs[i], levelYs[i + 1]);\n c.fillRect(0, top, w, bot - top);\n }\n\n c.globalAlpha = 1;\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n c.font = `${fontSize}px sans-serif`;\n c.fillStyle = color;\n c.textBaseline = 'bottom';\n\n for (let i = 0; i < levelYs.length; i++) {\n const ly = levelYs[i];\n c.beginPath();\n c.moveTo(0, ly);\n c.lineTo(w, ly);\n c.stroke();\n c.fillText(PROJ_LABELS[i], 4 * r, ly - 2 * r);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createFibProjection(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): FibProjectionDrawing {\n return new FibProjectionDrawing(id, points, options);\n}\n"],"mappings":"+DAUA,IAAM,EAAc,CAAC,EAAG,KAAO,EAAG,MAAO,OACnC,EAAc,CAAC,KAAM,QAAS,OAAQ,SAAU,UAGzC,EAAb,cAA0C,EAIxC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,oBAJG,qCACG,EAM1B,WAAA,GACE,MAAM,EAAM,KAAK,KACjB,IAAK,GAAO,KAAK,OAAO,OAAS,EAAG,OAAO,KAC3C,MAAM,EAAO,KAAK,OAAO,GAAG,MAAQ,KAAK,OAAO,GAAG,MACnD,OAAO,EAAY,IAAI,IACrB,MAAM,EAAQ,KAAK,OAAO,GAAG,MAAQ,EAAO,EAC5C,OAAO,EAAI,WAAW,SAAS,KAInC,eAAA,CAAgB,EAAW,GACzB,MAAM,EAAS,KAAK,cACpB,IAAK,EAAQ,OAAO,KACpB,IAAK,MAAM,KAAM,EACf,GAAI,KAAK,IAAI,EAAI,GAAG,EAClB,MAAO,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,aAG5D,OAAO,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,EAAG,MAAO,GAAM,EAC1C,EAAO,EAAK,OAAO,GAAG,MAAQ,EAAK,OAAO,GAAG,MAC7C,EAAU,EAAY,IAAI,IAC9B,MAAM,EAAQ,EAAK,OAAO,GAAG,MAAQ,EAAO,EAC5C,OAAO,EAAI,WAAW,SAAS,GAAS,IAGpC,EAAQ,EAAK,QAAQ,OAAS,UAC9B,GAAM,EAAK,QAAQ,WAAa,GAAK,EACrC,GAAY,EAAK,QAAQ,UAAY,IAAM,EAEjD,EAAE,OAGF,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,OAAS,EAAG,IAAK,CAC3C,EAAE,UAAY,EACd,EAAE,YAvDO,KAuDyB,EAAI,GAAM,EAAI,EAAI,IACpD,MAAM,EAAM,KAAK,IAAI,EAAQ,GAAI,EAAQ,EAAI,IACvC,EAAM,KAAK,IAAI,EAAQ,GAAI,EAAQ,EAAI,IAC7C,EAAE,SAAS,EAAG,EAAK,EAAG,EAAM,GAG9B,EAAE,YAAc,EAChB,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAe,EAAG,EAAK,QAAQ,WAC/B,EAAE,KAAO,GAAG,iBACZ,EAAE,UAAY,EACd,EAAE,aAAe,SAEjB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,OAAQ,IAAK,CACvC,MAAM,EAAK,EAAQ,GACnB,EAAE,YACF,EAAE,OAAO,EAAG,GACZ,EAAE,OAAO,EAAG,GACZ,EAAE,SACF,EAAE,SAAS,EAAY,GAAI,EAAI,EAAG,EAAK,EAAI,GAG7C,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAqB,EAAI,EAAQ"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t}from"./index21.js";var e=[.236,.382,.5,.618],i=["23.6%","38.2%","50%","61.8%"],r=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="fib-arc",this.requiredPoints=2}_hitTestDrawing(t,i){const r=this._ctx;if(!r||this.points.length<2)return null;const n=r.timeScale.indexToX(this.points[0].time),o=r.priceScale.priceToY(this.points[0].price),s=r.timeScale.indexToX(this.points[1].time),c=r.priceScale.priceToY(this.points[1].price);if(Math.hypot(t-n,i-o)<6)return{drawingId:this.id,part:"handle1",cursorStyle:"grab"};if(Math.hypot(t-s,i-c)<6)return{drawingId:this.id,part:"handle2",cursorStyle:"grab"};const a=Math.hypot(s-n,c-o),l=Math.hypot(t-s,i-c);for(const p of e){const t=a*p;if(Math.abs(l-t)<6)return{drawingId:this.id,part:"body",cursorStyle:"move"}}return null}_createPaneView(){const t=this;return{renderer(){const r=t._ctx;return!r||t.points.length<2?null:{draw(n){const{context:o,pixelRatio:s}=n,c=r.timeScale.indexToX(t.points[0].time)*s,a=r.priceScale.priceToY(t.points[0].price)*s,l=r.timeScale.indexToX(t.points[1].time)*s,p=r.priceScale.priceToY(t.points[1].price)*s,h=Math.hypot(l-c,p-a),d=t.options.color??"#FF9800",f=(t.options.lineWidth??1)*s,u=(t.options.fontSize??11)*s;o.save(),o.strokeStyle=d,o.fillStyle=d,o.lineWidth=f,o.font=`${u}px sans-serif`,o.textBaseline="bottom";for(let t=0;t<e.length;t++){const r=h*e[t];o.beginPath(),o.arc(l,p,r,0,Math.PI,!0),o.stroke(),o.fillText(i[t],l-r+2*s,p-2*s)}if(t.selected){const t=4*s;o.fillRect(c-t,a-t,2*t,2*t),o.fillRect(l-t,p-t,2*t,2*t)}o.restore()}}}}}};function n(t,e,i){return new r(t,e,i)}export{n as createFibArc};
2
+ //# sourceMappingURL=index34.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index34.js","names":[],"sources":["../src/drawings/fib-arc.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nconst ARC_RATIOS = [0.236, 0.382, 0.5, 0.618] as const;\nconst ARC_LABELS = ['23.6%', '38.2%', '50%', '61.8%'];\n\nexport class FibArcDrawing extends BaseDrawing {\n readonly drawingType = 'fib-arc';\n readonly requiredPoints = 2;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 2) return null;\n\n const x1 = ctx.timeScale.indexToX(this.points[0].time);\n const y1 = ctx.priceScale.priceToY(this.points[0].price);\n const x2 = ctx.timeScale.indexToX(this.points[1].time);\n const y2 = ctx.priceScale.priceToY(this.points[1].price);\n\n // Check handles\n if (Math.hypot(x - x1, y - y1) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle1', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - x2, y - y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle2', cursorStyle: 'grab' };\n }\n\n const totalDist = Math.hypot(x2 - x1, y2 - y1);\n const distFromCenter = Math.hypot(x - x2, y - y2);\n\n for (const ratio of ARC_RATIOS) {\n const radius = totalDist * ratio;\n if (Math.abs(distFromCenter - radius) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 2) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const x1 = ctx.timeScale.indexToX(self.points[0].time) * r;\n const y1 = ctx.priceScale.priceToY(self.points[0].price) * r;\n const x2 = ctx.timeScale.indexToX(self.points[1].time) * r;\n const y2 = ctx.priceScale.priceToY(self.points[1].price) * r;\n\n const totalDist = Math.hypot(x2 - x1, y2 - y1);\n const color = self.options.color ?? '#FF9800';\n const lw = (self.options.lineWidth ?? 1) * r;\n const fontSize = (self.options.fontSize ?? 11) * r;\n\n c.save();\n c.strokeStyle = color;\n c.fillStyle = color;\n c.lineWidth = lw;\n c.font = `${fontSize}px sans-serif`;\n c.textBaseline = 'bottom';\n\n for (let i = 0; i < ARC_RATIOS.length; i++) {\n const radius = totalDist * ARC_RATIOS[i];\n c.beginPath();\n // Upper half arc (counterclockwise from 0 to PI)\n c.arc(x2, y2, radius, 0, Math.PI, true);\n c.stroke();\n // Label at leftmost point of arc\n c.fillText(ARC_LABELS[i], x2 - radius + 2 * r, y2 - 2 * r);\n }\n\n if (self.selected) {\n const hs = 4 * r;\n c.fillRect(x1 - hs, y1 - hs, hs * 2, hs * 2);\n c.fillRect(x2 - hs, y2 - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createFibArc(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): FibArcDrawing {\n return new FibArcDrawing(id, points, options);\n}\n"],"mappings":"2CASA,IAAM,EAAa,CAAC,KAAO,KAAO,GAAK,MACjC,EAAa,CAAC,QAAS,QAAS,MAAO,SAEhC,EAAb,cAAmC,EAIjC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,oBAJG,8BACG,EAM1B,eAAA,CAAgB,EAAW,GACzB,MAAM,EAAM,KAAK,KACjB,IAAK,GAAO,KAAK,OAAO,OAAS,EAAG,OAAO,KAE3C,MAAM,EAAK,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MAC3C,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAC5C,EAAK,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MAC3C,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAGlD,GAAI,KAAK,MAAM,EAAI,EAAI,EAAI,GAAG,EAC5B,MAAO,CAAE,UAAW,KAAK,GAAI,KAAM,UAAW,YAAa,QAE7D,GAAI,KAAK,MAAM,EAAI,EAAI,EAAI,GAAG,EAC5B,MAAO,CAAE,UAAW,KAAK,GAAI,KAAM,UAAW,YAAa,QAG7D,MAAM,EAAY,KAAK,MAAM,EAAK,EAAI,EAAK,GACrC,EAAiB,KAAK,MAAM,EAAI,EAAI,EAAI,GAE9C,IAAK,MAAM,KAAS,EAAY,CAC9B,MAAM,EAAS,EAAY,EAC3B,GAAI,KAAK,IAAI,EAAiB,GAAO,EACnC,MAAO,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,QAG5D,OAAO,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,GAAM,EAChC,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EACrD,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EAErD,EAAY,KAAK,MAAM,EAAK,EAAI,EAAK,GACrC,EAAQ,EAAK,QAAQ,OAAS,UAC9B,GAAM,EAAK,QAAQ,WAAa,GAAK,EACrC,GAAY,EAAK,QAAQ,UAAY,IAAM,EAEjD,EAAE,OACF,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAE,UAAY,EACd,EAAE,KAAO,GAAG,iBACZ,EAAE,aAAe,SAEjB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,OAAQ,IAAK,CAC1C,MAAM,EAAS,EAAY,EAAW,GACtC,EAAE,YAEF,EAAE,IAAI,EAAI,EAAI,EAAQ,EAAG,KAAK,IAAI,GAClC,EAAE,SAEF,EAAE,SAAS,EAAW,GAAI,EAAK,EAAS,EAAI,EAAG,EAAK,EAAI,GAG1D,GAAI,EAAK,SAAU,CACjB,MAAM,EAAK,EAAI,EACf,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GACrC,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GAGvC,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAc,EAAI,EAAQ"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,distToSegment as e}from"./index21.js";var i=[.236,.382,.5,.618,.786],n=["23.6%","38.2%","50%","61.8%","78.6%"],r=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="fib-fan",this.requiredPoints=2}_extendToEdge(t,e,i,n,r,o){const s=i-t,c=n-e;if(0===s&&0===c)return[i,n];let a=1e9;return s>0?a=Math.min(a,(r-t)/s):s<0&&(a=Math.min(a,-t/s)),c>0?a=Math.min(a,(o-e)/c):c<0&&(a=Math.min(a,-e/c)),[t+a*s,e+a*c]}_hitTestDrawing(t,n){const r=this._ctx;if(!r||this.points.length<2)return null;const o=r.timeScale.indexToX(this.points[0].time),s=r.priceScale.priceToY(this.points[0].price),c=r.timeScale.indexToX(this.points[1].time),a=r.priceScale.priceToY(this.points[1].price);if(Math.hypot(t-o,n-s)<6)return{drawingId:this.id,part:"handle1",cursorStyle:"grab"};if(Math.hypot(t-c,n-a)<6)return{drawingId:this.id,part:"handle2",cursorStyle:"grab"};for(const l of i){const i=s+(a-s)*l,[h,p]=this._extendToEdge(o,s,c,i,r.chartWidth,r.chartHeight);if(e(t,n,o,s,h,p)<6)return{drawingId:this.id,part:"body",cursorStyle:"move"}}return null}_createPaneView(){const t=this;return{renderer(){const e=t._ctx;return!e||t.points.length<2?null:{draw(r){const{context:o,pixelRatio:s}=r,c=e.timeScale.indexToX(t.points[0].time)*s,a=e.priceScale.priceToY(t.points[0].price)*s,l=e.timeScale.indexToX(t.points[1].time)*s,h=e.priceScale.priceToY(t.points[1].price)*s,p=r.width,d=r.height,m=t.options.color??"#FF9800",f=(t.options.lineWidth??1)*s,u=(t.options.fontSize??11)*s;o.save(),o.strokeStyle=m,o.fillStyle=m,o.lineWidth=f,o.font=`${u}px sans-serif`,o.textBaseline="bottom";for(let t=0;t<i.length;t++){const e=l-c,r=a+(h-a)*i[t]-a;let m=1e9;e>0?m=Math.min(m,(p-c)/e):e<0&&(m=Math.min(m,-c/e)),r>0?m=Math.min(m,(d-a)/r):r<0&&(m=Math.min(m,-a/r));const f=c+m*e,u=a+m*r;o.beginPath(),o.moveTo(c,a),o.lineTo(f,u),o.stroke(),o.fillText(n[t],f-40*s,u-2*s)}if(t.selected){const t=4*s;o.fillRect(c-t,a-t,2*t,2*t),o.fillRect(l-t,h-t,2*t,2*t)}o.restore()}}}}}};function o(t,e,i){return new r(t,e,i)}export{o as createFibFan};
2
+ //# sourceMappingURL=index35.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index35.js","names":[],"sources":["../src/drawings/fib-fan.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n distToSegment,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nconst FAN_RATIOS = [0.236, 0.382, 0.5, 0.618, 0.786] as const;\nconst FAN_LABELS = ['23.6%', '38.2%', '50%', '61.8%', '78.6%'];\n\nexport class FibFanDrawing extends BaseDrawing {\n readonly drawingType = 'fib-fan';\n readonly requiredPoints = 2;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n /** Extend a line from (x1,y1) through (tx,ty) to the chart edge. */\n private _extendToEdge(\n x1: number, y1: number,\n tx: number, ty: number,\n w: number, h: number,\n ): [number, number] {\n const dx = tx - x1;\n const dy = ty - y1;\n if (dx === 0 && dy === 0) return [tx, ty];\n let tMax = 1e9;\n if (dx > 0) tMax = Math.min(tMax, (w - x1) / dx);\n else if (dx < 0) tMax = Math.min(tMax, -x1 / dx);\n if (dy > 0) tMax = Math.min(tMax, (h - y1) / dy);\n else if (dy < 0) tMax = Math.min(tMax, -y1 / dy);\n return [x1 + tMax * dx, y1 + tMax * dy];\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 2) return null;\n\n const x1 = ctx.timeScale.indexToX(this.points[0].time);\n const y1 = ctx.priceScale.priceToY(this.points[0].price);\n const x2 = ctx.timeScale.indexToX(this.points[1].time);\n const y2 = ctx.priceScale.priceToY(this.points[1].price);\n\n if (Math.hypot(x - x1, y - y1) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle1', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - x2, y - y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle2', cursorStyle: 'grab' };\n }\n\n for (const ratio of FAN_RATIOS) {\n const ty = y1 + (y2 - y1) * ratio;\n const [ex, ey] = this._extendToEdge(x1, y1, x2, ty, ctx.chartWidth, ctx.chartHeight);\n if (distToSegment(x, y, x1, y1, ex, ey) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n }\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 2) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const x1 = ctx.timeScale.indexToX(self.points[0].time) * r;\n const y1 = ctx.priceScale.priceToY(self.points[0].price) * r;\n const x2 = ctx.timeScale.indexToX(self.points[1].time) * r;\n const y2 = ctx.priceScale.priceToY(self.points[1].price) * r;\n const w = target.width;\n const h = target.height;\n\n const color = self.options.color ?? '#FF9800';\n const lw = (self.options.lineWidth ?? 1) * r;\n const fontSize = (self.options.fontSize ?? 11) * r;\n\n c.save();\n c.strokeStyle = color;\n c.fillStyle = color;\n c.lineWidth = lw;\n c.font = `${fontSize}px sans-serif`;\n c.textBaseline = 'bottom';\n\n for (let i = 0; i < FAN_RATIOS.length; i++) {\n const ty = y1 + (y2 - y1) * FAN_RATIOS[i];\n const dx = x2 - x1;\n const dy = ty - y1;\n let tMax = 1e9;\n if (dx > 0) tMax = Math.min(tMax, (w - x1) / dx);\n else if (dx < 0) tMax = Math.min(tMax, -x1 / dx);\n if (dy > 0) tMax = Math.min(tMax, (h - y1) / dy);\n else if (dy < 0) tMax = Math.min(tMax, -y1 / dy);\n const ex = x1 + tMax * dx;\n const ey = y1 + tMax * dy;\n\n c.beginPath();\n c.moveTo(x1, y1);\n c.lineTo(ex, ey);\n c.stroke();\n\n // Label near the end of the line\n c.fillText(FAN_LABELS[i], ex - 40 * r, ey - 2 * r);\n }\n\n if (self.selected) {\n const hs = 4 * r;\n c.fillRect(x1 - hs, y1 - hs, hs * 2, hs * 2);\n c.fillRect(x2 - hs, y2 - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createFibFan(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): FibFanDrawing {\n return new FibFanDrawing(id, points, options);\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,applyLineStyle as e}from"./index21.js";var i=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="crossline",this.requiredPoints=1}_hitTestDrawing(t,e){const i=this._ctx;if(!i||this.points.length<1)return null;const r=i.timeScale.indexToX(this.points[0].time),n=i.priceScale.priceToY(this.points[0].price);return Math.hypot(t-r,e-n)<6?{drawingId:this.id,part:"handle1",cursorStyle:"grab"}:Math.abs(e-n)<6?{drawingId:this.id,part:"body",cursorStyle:"ns-resize"}:Math.abs(t-r)<6?{drawingId:this.id,part:"body",cursorStyle:"ew-resize"}:null}_createPaneView(){const t=this;return{renderer(){const i=t._ctx;return!i||t.points.length<1?null:{draw(r){const{context:n,pixelRatio:o}=r,s=i.timeScale.indexToX(t.points[0].time)*o,l=i.priceScale.priceToY(t.points[0].price)*o,c=r.width,a=r.height,h=t.options.color??"#2196F3",d=(t.options.lineWidth??1)*o;if(n.save(),n.strokeStyle=h,n.lineWidth=d,e(n,t.options.lineStyle),n.beginPath(),n.moveTo(0,l),n.lineTo(c,l),n.stroke(),n.beginPath(),n.moveTo(s,0),n.lineTo(s,a),n.stroke(),t.selected){n.fillStyle=h;const t=4*o;n.fillRect(s-t,l-t,2*t,2*t)}n.restore()}}}}}};function r(t,e,r){return new i(t,e,r)}export{r as createCrossline};
2
+ //# sourceMappingURL=index36.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index36.js","names":[],"sources":["../src/drawings/crossline.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n applyLineStyle,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nexport class CrosslineDrawing extends BaseDrawing {\n readonly drawingType = 'crossline';\n readonly requiredPoints = 1;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 1) return null;\n\n const cx = ctx.timeScale.indexToX(this.points[0].time);\n const cy = ctx.priceScale.priceToY(this.points[0].price);\n\n // Check handle\n if (Math.hypot(x - cx, y - cy) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle1', cursorStyle: 'grab' };\n }\n\n // Horizontal line\n if (Math.abs(y - cy) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'ns-resize' };\n }\n\n // Vertical line\n if (Math.abs(x - cx) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'ew-resize' };\n }\n\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 1) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const cx = ctx.timeScale.indexToX(self.points[0].time) * r;\n const cy = ctx.priceScale.priceToY(self.points[0].price) * r;\n const w = target.width;\n const h = target.height;\n const color = self.options.color ?? '#2196F3';\n const lw = (self.options.lineWidth ?? 1) * r;\n\n c.save();\n c.strokeStyle = color;\n c.lineWidth = lw;\n applyLineStyle(c, self.options.lineStyle);\n\n // Horizontal line\n c.beginPath();\n c.moveTo(0, cy);\n c.lineTo(w, cy);\n c.stroke();\n\n // Vertical line\n c.beginPath();\n c.moveTo(cx, 0);\n c.lineTo(cx, h);\n c.stroke();\n\n if (self.selected) {\n c.fillStyle = color;\n const hs = 4 * r;\n c.fillRect(cx - hs, cy - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createCrossline(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): CrosslineDrawing {\n return new CrosslineDrawing(id, points, options);\n}\n"],"mappings":"+DAUA,IAAa,EAAb,cAAsC,EAIpC,WAAA,CAAY,EAAY,EAAuB,GAC7C,MAAM,EAAI,EAAQ,oBAJG,gCACG,EAM1B,eAAA,CAAgB,EAAW,GACzB,MAAM,EAAM,KAAK,KACjB,IAAK,GAAO,KAAK,OAAO,OAAS,EAAG,OAAO,KAE3C,MAAM,EAAK,EAAI,UAAU,SAAS,KAAK,OAAO,GAAG,MAC3C,EAAK,EAAI,WAAW,SAAS,KAAK,OAAO,GAAG,OAGlD,OAAI,KAAK,MAAM,EAAI,EAAI,EAAI,GAAG,EACrB,CAAE,UAAW,KAAK,GAAI,KAAM,UAAW,YAAa,QAIzD,KAAK,IAAI,EAAI,GAAG,EACX,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,aAItD,KAAK,IAAI,EAAI,GAAG,EACX,CAAE,UAAW,KAAK,GAAI,KAAM,OAAQ,YAAa,aAGnD,KAGT,eAAA,GACE,MAAM,EAAO,KACb,MAAO,CACL,QAAA,GACE,MAAM,EAAM,EAAK,KACjB,OAAK,GAAO,EAAK,OAAO,OAAS,EAAU,KACpC,CACL,IAAA,CAAK,GACH,MAAQ,QAAS,EAAG,WAAY,GAAM,EAChC,EAAK,EAAI,UAAU,SAAS,EAAK,OAAO,GAAG,MAAQ,EACnD,EAAK,EAAI,WAAW,SAAS,EAAK,OAAO,GAAG,OAAS,EACrD,EAAI,EAAO,MACX,EAAI,EAAO,OACX,EAAQ,EAAK,QAAQ,OAAS,UAC9B,GAAM,EAAK,QAAQ,WAAa,GAAK,EAmB3C,GAjBA,EAAE,OACF,EAAE,YAAc,EAChB,EAAE,UAAY,EACd,EAAe,EAAG,EAAK,QAAQ,WAG/B,EAAE,YACF,EAAE,OAAO,EAAG,GACZ,EAAE,OAAO,EAAG,GACZ,EAAE,SAGF,EAAE,YACF,EAAE,OAAO,EAAI,GACb,EAAE,OAAO,EAAI,GACb,EAAE,SAEE,EAAK,SAAU,CACjB,EAAE,UAAY,EACd,MAAM,EAAK,EAAI,EACf,EAAE,SAAS,EAAK,EAAI,EAAK,EAAS,EAAL,EAAa,EAAL,GAGvC,EAAE,gBAQd,SAAgB,EACd,EACA,EACA,GAEA,OAAO,IAAI,EAAiB,EAAI,EAAQ"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as t,distToSegment as e,pointInRect as i}from"./index21.js";var o=class extends t{constructor(t,e,i){super(t,e,i),this.drawingType="measurement",this.requiredPoints=2}_buildLabel(){if(this.points.length<2)return"";const t=this.points[1].price-this.points[0].price,e=0!==this.points[0].price?t/this.points[0].price*100:0,i=Math.abs(this.points[1].time-this.points[0].time),o=t>=0?"+":"";return`${o}${t.toFixed(2)} (${o}${e.toFixed(1)}%) ${i} bars`}_hitTestDrawing(t,o){const n=this._ctx;if(!n||this.points.length<2)return null;const r=n.timeScale.indexToX(this.points[0].time),s=n.priceScale.priceToY(this.points[0].price),l=n.timeScale.indexToX(this.points[1].time),c=n.priceScale.priceToY(this.points[1].price);if(Math.hypot(t-r,o-s)<6)return{drawingId:this.id,part:"handle1",cursorStyle:"grab"};if(Math.hypot(t-l,o-c)<6)return{drawingId:this.id,part:"handle2",cursorStyle:"grab"};if(e(t,o,r,s,l,c)<6)return{drawingId:this.id,part:"body",cursorStyle:"move"};const a=(r+l)/2,p=(s+c)/2;return i(t,o,a-60,p-28,a+60,p)?{drawingId:this.id,part:"body",cursorStyle:"move"}:null}_createPaneView(){const t=this;return{renderer(){const e=t._ctx;return!e||t.points.length<2?null:{draw(i){const{context:o,pixelRatio:n}=i,r=e.timeScale.indexToX(t.points[0].time)*n,s=e.priceScale.priceToY(t.points[0].price)*n,l=e.timeScale.indexToX(t.points[1].time)*n,c=e.priceScale.priceToY(t.points[1].price)*n,a=t.options.color??"#2196F3",p=(t.options.lineWidth??1)*n;o.save(),o.strokeStyle=a,o.lineWidth=p,o.setLineDash([6*n,4*n]),o.beginPath(),o.moveTo(r,s),o.lineTo(l,c),o.stroke(),o.setLineDash([]);const h=(r+l)/2,d=(s+c)/2,u=t._buildLabel(),f=(t.options.fontSize??11)*n;o.font=`${f}px sans-serif`;const T=8*n,m=5*n,x=o.measureText(u).width+2*T,S=f+2*m,g=h-x/2,b=d-S-4*n,y=4*n;if(o.fillStyle=a,o.globalAlpha=.85,o.beginPath(),o.moveTo(g+y,b),o.lineTo(g+x-y,b),o.arcTo(g+x,b,g+x,b+y,y),o.lineTo(g+x,b+S-y),o.arcTo(g+x,b+S,g+x-y,b+S,y),o.lineTo(g+y,b+S),o.arcTo(g,b+S,g,b+S-y,y),o.lineTo(g,b+y),o.arcTo(g,b,g+y,b,y),o.closePath(),o.fill(),o.globalAlpha=1,o.fillStyle="#ffffff",o.textBaseline="top",o.fillText(u,g+T,b+m),t.selected){o.fillStyle=a;const t=4*n;o.fillRect(r-t,s-t,2*t,2*t),o.fillRect(l-t,c-t,2*t,2*t)}o.restore()}}}}}};function n(t,e,i){return new o(t,e,i)}export{n as createMeasurement};
2
+ //# sourceMappingURL=index37.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index37.js","names":[],"sources":["../src/drawings/measurement.ts"],"sourcesContent":["import type { IPaneView, IPaneRenderer, IRenderTarget } from '../core/types';\nimport {\n BaseDrawing,\n HIT_THRESHOLD,\n distToSegment,\n pointInRect,\n type AnchorPoint,\n type DrawingOptions,\n type DrawingHitTestResult,\n} from './base';\n\nconst LABEL_PADDING_X = 8;\nconst LABEL_PADDING_Y = 5;\n\nexport class MeasurementDrawing extends BaseDrawing {\n readonly drawingType = 'measurement';\n readonly requiredPoints = 2;\n\n constructor(id: string, points: AnchorPoint[], options: DrawingOptions) {\n super(id, points, options);\n }\n\n private _buildLabel(): string {\n if (this.points.length < 2) return '';\n const priceChange = this.points[1].price - this.points[0].price;\n const pct = this.points[0].price !== 0\n ? (priceChange / this.points[0].price) * 100\n : 0;\n const barCount = Math.abs(this.points[1].time - this.points[0].time);\n const sign = priceChange >= 0 ? '+' : '';\n return `${sign}${priceChange.toFixed(2)} (${sign}${pct.toFixed(1)}%) ${barCount} bars`;\n }\n\n _hitTestDrawing(x: number, y: number): DrawingHitTestResult | null {\n const ctx = this._ctx;\n if (!ctx || this.points.length < 2) return null;\n\n const x1 = ctx.timeScale.indexToX(this.points[0].time);\n const y1 = ctx.priceScale.priceToY(this.points[0].price);\n const x2 = ctx.timeScale.indexToX(this.points[1].time);\n const y2 = ctx.priceScale.priceToY(this.points[1].price);\n\n // Check handles\n if (Math.hypot(x - x1, y - y1) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle1', cursorStyle: 'grab' };\n }\n if (Math.hypot(x - x2, y - y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'handle2', cursorStyle: 'grab' };\n }\n\n // Hit on connector line\n if (distToSegment(x, y, x1, y1, x2, y2) < HIT_THRESHOLD) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n\n // Approximate label area at midpoint\n const mx = (x1 + x2) / 2;\n const my = (y1 + y2) / 2;\n if (pointInRect(x, y, mx - 60, my - 28, mx + 60, my)) {\n return { drawingId: this.id, part: 'body', cursorStyle: 'move' };\n }\n\n return null;\n }\n\n protected _createPaneView(): IPaneView {\n const self = this;\n return {\n renderer(): IPaneRenderer | null {\n const ctx = self._ctx;\n if (!ctx || self.points.length < 2) return null;\n return {\n draw(target: IRenderTarget): void {\n const { context: c, pixelRatio: r } = target;\n const x1 = ctx.timeScale.indexToX(self.points[0].time) * r;\n const y1 = ctx.priceScale.priceToY(self.points[0].price) * r;\n const x2 = ctx.timeScale.indexToX(self.points[1].time) * r;\n const y2 = ctx.priceScale.priceToY(self.points[1].price) * r;\n const color = self.options.color ?? '#2196F3';\n const lw = (self.options.lineWidth ?? 1) * r;\n\n c.save();\n\n // Dashed connector line\n c.strokeStyle = color;\n c.lineWidth = lw;\n c.setLineDash([6 * r, 4 * r]);\n c.beginPath();\n c.moveTo(x1, y1);\n c.lineTo(x2, y2);\n c.stroke();\n c.setLineDash([]);\n\n // Label at midpoint\n const mx = (x1 + x2) / 2;\n const my = (y1 + y2) / 2;\n const text = self._buildLabel();\n const fontSize = (self.options.fontSize ?? 11) * r;\n c.font = `${fontSize}px sans-serif`;\n const textW = c.measureText(text).width;\n const padX = LABEL_PADDING_X * r;\n const padY = LABEL_PADDING_Y * r;\n const boxW = textW + padX * 2;\n const boxH = fontSize + padY * 2;\n const boxX = mx - boxW / 2;\n const boxY = my - boxH - 4 * r;\n const cornerR = 4 * r;\n\n // Rounded rect background\n c.fillStyle = color;\n c.globalAlpha = 0.85;\n c.beginPath();\n c.moveTo(boxX + cornerR, boxY);\n c.lineTo(boxX + boxW - cornerR, boxY);\n c.arcTo(boxX + boxW, boxY, boxX + boxW, boxY + cornerR, cornerR);\n c.lineTo(boxX + boxW, boxY + boxH - cornerR);\n c.arcTo(boxX + boxW, boxY + boxH, boxX + boxW - cornerR, boxY + boxH, cornerR);\n c.lineTo(boxX + cornerR, boxY + boxH);\n c.arcTo(boxX, boxY + boxH, boxX, boxY + boxH - cornerR, cornerR);\n c.lineTo(boxX, boxY + cornerR);\n c.arcTo(boxX, boxY, boxX + cornerR, boxY, cornerR);\n c.closePath();\n c.fill();\n\n // White text\n c.globalAlpha = 1;\n c.fillStyle = '#ffffff';\n c.textBaseline = 'top';\n c.fillText(text, boxX + padX, boxY + padY);\n\n // Selection handles\n if (self.selected) {\n c.fillStyle = color;\n const hs = 4 * r;\n c.fillRect(x1 - hs, y1 - hs, hs * 2, hs * 2);\n c.fillRect(x2 - hs, y2 - hs, hs * 2, hs * 2);\n }\n\n c.restore();\n },\n };\n },\n };\n }\n}\n\nexport function createMeasurement(\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): MeasurementDrawing {\n return new MeasurementDrawing(id, points, options);\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{BaseDrawing as e,distToSegment as i,pointInRect as r}from"./index21.js";import{createHorizontalLine as t}from"./index22.js";import{createVerticalLine as o}from"./index23.js";import{createTrendline as n}from"./index24.js";import{createFibonacci as s}from"./index25.js";import{createRectangle as m}from"./index26.js";import{createTextAnnotation as f}from"./index27.js";import{createRay as p}from"./index28.js";import{createArrow as x}from"./index29.js";import{createChannel as d}from"./index30.js";import{createEllipse as j}from"./index31.js";import{createPitchfork as a}from"./index32.js";import{createFibProjection as l}from"./index33.js";import{createFibArc as c}from"./index34.js";import{createFibFan as b}from"./index35.js";import{createCrossline as u}from"./index36.js";import{createMeasurement as h}from"./index37.js";var g=/* @__PURE__ */new Map;function v(e,i,r,t){const o=g.get(e);return o?o(i,r,t):null}g.set("horizontal-line",t),g.set("vertical-line",o),g.set("trendline",n),g.set("fibonacci",s),g.set("rectangle",m),g.set("text-annotation",f),g.set("ray",p),g.set("arrow",x),g.set("channel",d),g.set("ellipse",j),g.set("pitchfork",a),g.set("fib-projection",l),g.set("fib-arc",c),g.set("fib-fan",b),g.set("crossline",u),g.set("measurement",h);export{g as DRAWING_REGISTRY,v as createBuiltinDrawing};
2
+ //# sourceMappingURL=index38.js.map