minerva-design 1.5.0 → 1.6.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 (457) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/custom-elements.json +122 -5
  3. package/dist/angular/fesm2022/minerva-angular.mjs +55 -0
  4. package/dist/angular/fesm2022/minerva-angular.mjs.map +1 -1
  5. package/dist/angular/types/minerva-angular.d.ts +23 -2
  6. package/dist/charts/canvas.d.cts +2 -1
  7. package/dist/charts/canvas.d.ts +2 -1
  8. package/dist/charts/core.d.cts +1 -1
  9. package/dist/charts/core.d.ts +1 -1
  10. package/dist/charts/engine/canvas.cjs +1 -1
  11. package/dist/charts/engine/canvas.cjs.map +1 -1
  12. package/dist/charts/engine/canvas.js +2 -1
  13. package/dist/charts/engine/canvas.js.map +1 -1
  14. package/dist/charts/engine/chart.cjs +1 -1
  15. package/dist/charts/engine/chart.cjs.map +1 -1
  16. package/dist/charts/engine/chart.js +144 -143
  17. package/dist/charts/engine/chart.js.map +1 -1
  18. package/dist/charts/engine/controller.cjs +2 -2
  19. package/dist/charts/engine/controller.cjs.map +1 -1
  20. package/dist/charts/engine/controller.d.cts +3 -1
  21. package/dist/charts/engine/controller.d.ts +3 -1
  22. package/dist/charts/engine/controller.js +130 -132
  23. package/dist/charts/engine/controller.js.map +1 -1
  24. package/dist/charts/engine/defaults.cjs.map +1 -1
  25. package/dist/charts/engine/defaults.d.cts +4 -4
  26. package/dist/charts/engine/defaults.d.ts +4 -4
  27. package/dist/charts/engine/defaults.js.map +1 -1
  28. package/dist/charts/engine/graph/chart.cjs +1 -1
  29. package/dist/charts/engine/graph/chart.cjs.map +1 -1
  30. package/dist/charts/engine/graph/chart.js +740 -597
  31. package/dist/charts/engine/graph/chart.js.map +1 -1
  32. package/dist/charts/engine/graph/dag.cjs +1 -1
  33. package/dist/charts/engine/graph/dag.cjs.map +1 -1
  34. package/dist/charts/engine/graph/dag.js +191 -166
  35. package/dist/charts/engine/graph/dag.js.map +1 -1
  36. package/dist/charts/engine/graph/force.cjs +1 -1
  37. package/dist/charts/engine/graph/force.cjs.map +1 -1
  38. package/dist/charts/engine/graph/force.d.cts +9 -0
  39. package/dist/charts/engine/graph/force.d.ts +9 -0
  40. package/dist/charts/engine/graph/force.js +279 -181
  41. package/dist/charts/engine/graph/force.js.map +1 -1
  42. package/dist/charts/engine/graph/geometry.cjs +1 -1
  43. package/dist/charts/engine/graph/geometry.cjs.map +1 -1
  44. package/dist/charts/engine/graph/geometry.d.cts +14 -1
  45. package/dist/charts/engine/graph/geometry.d.ts +14 -1
  46. package/dist/charts/engine/graph/geometry.js +77 -24
  47. package/dist/charts/engine/graph/geometry.js.map +1 -1
  48. package/dist/charts/engine/graph/model.cjs +1 -1
  49. package/dist/charts/engine/graph/model.cjs.map +1 -1
  50. package/dist/charts/engine/graph/model.d.cts +9 -0
  51. package/dist/charts/engine/graph/model.d.ts +9 -0
  52. package/dist/charts/engine/graph/model.js +63 -43
  53. package/dist/charts/engine/graph/model.js.map +1 -1
  54. package/dist/charts/engine/graph/types.d.cts +14 -0
  55. package/dist/charts/engine/graph/types.d.ts +14 -0
  56. package/dist/charts/engine/graph/worker.cjs +12 -6
  57. package/dist/charts/engine/graph/worker.cjs.map +1 -1
  58. package/dist/charts/engine/graph/worker.js +12 -6
  59. package/dist/charts/engine/graph/worker.js.map +1 -1
  60. package/dist/charts/engine/labels.cjs.map +1 -1
  61. package/dist/charts/engine/labels.d.cts +17 -0
  62. package/dist/charts/engine/labels.d.ts +17 -0
  63. package/dist/charts/engine/labels.js.map +1 -1
  64. package/dist/charts/engine/model.cjs +1 -1
  65. package/dist/charts/engine/model.cjs.map +1 -1
  66. package/dist/charts/engine/model.d.cts +33 -0
  67. package/dist/charts/engine/model.d.ts +33 -0
  68. package/dist/charts/engine/model.js +149 -126
  69. package/dist/charts/engine/model.js.map +1 -1
  70. package/dist/charts/engine/orderbook/field.cjs +37 -0
  71. package/dist/charts/engine/orderbook/field.cjs.map +1 -0
  72. package/dist/charts/engine/orderbook/field.d.cts +92 -0
  73. package/dist/charts/engine/orderbook/field.d.ts +92 -0
  74. package/dist/charts/engine/orderbook/field.js +297 -0
  75. package/dist/charts/engine/orderbook/field.js.map +1 -0
  76. package/dist/charts/engine/orderbook/heatmap.cjs +1 -1
  77. package/dist/charts/engine/orderbook/heatmap.cjs.map +1 -1
  78. package/dist/charts/engine/orderbook/heatmap.js +413 -441
  79. package/dist/charts/engine/orderbook/heatmap.js.map +1 -1
  80. package/dist/charts/engine/orderbook/host.cjs +1 -1
  81. package/dist/charts/engine/orderbook/host.cjs.map +1 -1
  82. package/dist/charts/engine/orderbook/host.d.cts +8 -1
  83. package/dist/charts/engine/orderbook/host.d.ts +8 -1
  84. package/dist/charts/engine/orderbook/host.js +27 -5
  85. package/dist/charts/engine/orderbook/host.js.map +1 -1
  86. package/dist/charts/engine/orderbook/ladder.cjs +1 -1
  87. package/dist/charts/engine/orderbook/ladder.cjs.map +1 -1
  88. package/dist/charts/engine/orderbook/ladder.js +1 -1
  89. package/dist/charts/engine/orderbook/ladder.js.map +1 -1
  90. package/dist/charts/engine/orderbook/layout.cjs +1 -1
  91. package/dist/charts/engine/orderbook/layout.cjs.map +1 -1
  92. package/dist/charts/engine/orderbook/layout.d.cts +5 -0
  93. package/dist/charts/engine/orderbook/layout.d.ts +5 -0
  94. package/dist/charts/engine/orderbook/layout.js +8 -2
  95. package/dist/charts/engine/orderbook/layout.js.map +1 -1
  96. package/dist/charts/engine/orderbook/tape.cjs +1 -1
  97. package/dist/charts/engine/orderbook/tape.cjs.map +1 -1
  98. package/dist/charts/engine/orderbook/tape.js +3 -3
  99. package/dist/charts/engine/orderbook/tape.js.map +1 -1
  100. package/dist/charts/engine/orderbook/types.d.cts +12 -4
  101. package/dist/charts/engine/orderbook/types.d.ts +12 -4
  102. package/dist/charts/engine/overlay.cjs +1 -1
  103. package/dist/charts/engine/overlay.cjs.map +1 -1
  104. package/dist/charts/engine/overlay.d.cts +17 -0
  105. package/dist/charts/engine/overlay.d.ts +17 -0
  106. package/dist/charts/engine/overlay.js +29 -13
  107. package/dist/charts/engine/overlay.js.map +1 -1
  108. package/dist/charts/engine/presets.cjs +1 -1
  109. package/dist/charts/engine/presets.cjs.map +1 -1
  110. package/dist/charts/engine/presets.d.cts +12 -2
  111. package/dist/charts/engine/presets.d.ts +12 -2
  112. package/dist/charts/engine/presets.js +8 -2
  113. package/dist/charts/engine/presets.js.map +1 -1
  114. package/dist/charts/engine/renderers/canvas2d.cjs +1 -1
  115. package/dist/charts/engine/renderers/canvas2d.cjs.map +1 -1
  116. package/dist/charts/engine/renderers/canvas2d.js +13 -9
  117. package/dist/charts/engine/renderers/canvas2d.js.map +1 -1
  118. package/dist/charts/engine/renderers/follow.cjs +2 -0
  119. package/dist/charts/engine/renderers/follow.cjs.map +1 -0
  120. package/dist/charts/engine/renderers/follow.d.cts +8 -0
  121. package/dist/charts/engine/renderers/follow.d.ts +8 -0
  122. package/dist/charts/engine/renderers/follow.js +10 -0
  123. package/dist/charts/engine/renderers/follow.js.map +1 -0
  124. package/dist/charts/engine/renderers/gl-budget.cjs +2 -0
  125. package/dist/charts/engine/renderers/gl-budget.cjs.map +1 -0
  126. package/dist/charts/engine/renderers/gl-budget.d.cts +32 -0
  127. package/dist/charts/engine/renderers/gl-budget.d.ts +32 -0
  128. package/dist/charts/engine/renderers/gl-budget.js +95 -0
  129. package/dist/charts/engine/renderers/gl-budget.js.map +1 -0
  130. package/dist/charts/engine/renderers/gl.cjs +1 -1
  131. package/dist/charts/engine/renderers/gl.cjs.map +1 -1
  132. package/dist/charts/engine/renderers/gl.js +1 -1
  133. package/dist/charts/engine/renderers/gl.js.map +1 -1
  134. package/dist/charts/engine/renderers/shaders.cjs +9 -6
  135. package/dist/charts/engine/renderers/shaders.cjs.map +1 -1
  136. package/dist/charts/engine/renderers/shaders.d.cts +1 -1
  137. package/dist/charts/engine/renderers/shaders.d.ts +1 -1
  138. package/dist/charts/engine/renderers/shaders.js +9 -6
  139. package/dist/charts/engine/renderers/shaders.js.map +1 -1
  140. package/dist/charts/engine/renderers/types.cjs.map +1 -1
  141. package/dist/charts/engine/renderers/types.d.cts +2 -0
  142. package/dist/charts/engine/renderers/types.d.ts +2 -0
  143. package/dist/charts/engine/renderers/types.js.map +1 -1
  144. package/dist/charts/engine/renderers/webgl.cjs +1 -1
  145. package/dist/charts/engine/renderers/webgl.cjs.map +1 -1
  146. package/dist/charts/engine/renderers/webgl.js +85 -64
  147. package/dist/charts/engine/renderers/webgl.js.map +1 -1
  148. package/dist/charts/engine/renderers/webgl2.cjs +1 -1
  149. package/dist/charts/engine/renderers/webgl2.cjs.map +1 -1
  150. package/dist/charts/engine/renderers/webgl2.js +72 -58
  151. package/dist/charts/engine/renderers/webgl2.js.map +1 -1
  152. package/dist/charts/engine/renderers/webgpu.cjs +1 -1
  153. package/dist/charts/engine/renderers/webgpu.cjs.map +1 -1
  154. package/dist/charts/engine/renderers/webgpu.js +1 -1
  155. package/dist/charts/engine/renderers/webgpu.js.map +1 -1
  156. package/dist/charts/engine/scene.cjs +1 -1
  157. package/dist/charts/engine/scene.cjs.map +1 -1
  158. package/dist/charts/engine/scene.d.cts +51 -4
  159. package/dist/charts/engine/scene.d.ts +51 -4
  160. package/dist/charts/engine/scene.js +188 -122
  161. package/dist/charts/engine/scene.js.map +1 -1
  162. package/dist/charts/engine/shapes/chord.cjs +1 -1
  163. package/dist/charts/engine/shapes/chord.cjs.map +1 -1
  164. package/dist/charts/engine/shapes/chord.js +108 -103
  165. package/dist/charts/engine/shapes/chord.js.map +1 -1
  166. package/dist/charts/engine/shapes/types.d.cts +5 -3
  167. package/dist/charts/engine/shapes/types.d.ts +5 -3
  168. package/dist/charts/engine/three-d/canvas2d.cjs +1 -1
  169. package/dist/charts/engine/three-d/canvas2d.cjs.map +1 -1
  170. package/dist/charts/engine/three-d/canvas2d.d.cts +36 -1
  171. package/dist/charts/engine/three-d/canvas2d.d.ts +36 -1
  172. package/dist/charts/engine/three-d/canvas2d.js +155 -80
  173. package/dist/charts/engine/three-d/canvas2d.js.map +1 -1
  174. package/dist/charts/engine/three-d/chart.cjs +1 -1
  175. package/dist/charts/engine/three-d/chart.cjs.map +1 -1
  176. package/dist/charts/engine/three-d/chart.js +219 -215
  177. package/dist/charts/engine/three-d/chart.js.map +1 -1
  178. package/dist/charts/engine/three-d/oit.cjs +109 -0
  179. package/dist/charts/engine/three-d/oit.cjs.map +1 -0
  180. package/dist/charts/engine/three-d/oit.d.cts +34 -0
  181. package/dist/charts/engine/three-d/oit.d.ts +34 -0
  182. package/dist/charts/engine/three-d/oit.js +111 -0
  183. package/dist/charts/engine/three-d/oit.js.map +1 -0
  184. package/dist/charts/engine/three-d/render-types.cjs +1 -1
  185. package/dist/charts/engine/three-d/render-types.cjs.map +1 -1
  186. package/dist/charts/engine/three-d/render-types.d.cts +16 -3
  187. package/dist/charts/engine/three-d/render-types.d.ts +16 -3
  188. package/dist/charts/engine/three-d/render-types.js +6 -9
  189. package/dist/charts/engine/three-d/render-types.js.map +1 -1
  190. package/dist/charts/engine/three-d/shaders.cjs +52 -26
  191. package/dist/charts/engine/three-d/shaders.cjs.map +1 -1
  192. package/dist/charts/engine/three-d/shaders.d.cts +11 -3
  193. package/dist/charts/engine/three-d/shaders.d.ts +11 -3
  194. package/dist/charts/engine/three-d/shaders.js +84 -40
  195. package/dist/charts/engine/three-d/shaders.js.map +1 -1
  196. package/dist/charts/engine/three-d/sort.cjs +1 -1
  197. package/dist/charts/engine/three-d/sort.cjs.map +1 -1
  198. package/dist/charts/engine/three-d/sort.d.cts +6 -4
  199. package/dist/charts/engine/three-d/sort.d.ts +6 -4
  200. package/dist/charts/engine/three-d/sort.js +51 -39
  201. package/dist/charts/engine/three-d/sort.js.map +1 -1
  202. package/dist/charts/engine/three-d/types.d.cts +9 -0
  203. package/dist/charts/engine/three-d/types.d.ts +9 -0
  204. package/dist/charts/engine/three-d/webgl.cjs +1 -1
  205. package/dist/charts/engine/three-d/webgl.cjs.map +1 -1
  206. package/dist/charts/engine/three-d/webgl.d.cts +9 -0
  207. package/dist/charts/engine/three-d/webgl.d.ts +9 -0
  208. package/dist/charts/engine/three-d/webgl.js +199 -76
  209. package/dist/charts/engine/three-d/webgl.js.map +1 -1
  210. package/dist/charts/engine/three-d/webgpu.cjs +1 -1
  211. package/dist/charts/engine/three-d/webgpu.cjs.map +1 -1
  212. package/dist/charts/engine/three-d/webgpu.js +225 -99
  213. package/dist/charts/engine/three-d/webgpu.js.map +1 -1
  214. package/dist/charts/engine/trading/chart.cjs +1 -1
  215. package/dist/charts/engine/trading/chart.cjs.map +1 -1
  216. package/dist/charts/engine/trading/chart.d.cts +0 -1
  217. package/dist/charts/engine/trading/chart.d.ts +0 -1
  218. package/dist/charts/engine/trading/chart.js +1048 -883
  219. package/dist/charts/engine/trading/chart.js.map +1 -1
  220. package/dist/charts/engine/trading/drawings.cjs +2 -2
  221. package/dist/charts/engine/trading/drawings.cjs.map +1 -1
  222. package/dist/charts/engine/trading/drawings.d.cts +6 -0
  223. package/dist/charts/engine/trading/drawings.d.ts +6 -0
  224. package/dist/charts/engine/trading/drawings.js +100 -88
  225. package/dist/charts/engine/trading/drawings.js.map +1 -1
  226. package/dist/charts/engine/trading/format.cjs +1 -1
  227. package/dist/charts/engine/trading/format.cjs.map +1 -1
  228. package/dist/charts/engine/trading/format.d.cts +6 -0
  229. package/dist/charts/engine/trading/format.d.ts +6 -0
  230. package/dist/charts/engine/trading/format.js +42 -30
  231. package/dist/charts/engine/trading/format.js.map +1 -1
  232. package/dist/charts/engine/trading/geometry.cjs +1 -1
  233. package/dist/charts/engine/trading/geometry.cjs.map +1 -1
  234. package/dist/charts/engine/trading/geometry.d.cts +16 -0
  235. package/dist/charts/engine/trading/geometry.d.ts +16 -0
  236. package/dist/charts/engine/trading/geometry.js +19 -4
  237. package/dist/charts/engine/trading/geometry.js.map +1 -1
  238. package/dist/charts/engine/trading/labels.cjs +1 -1
  239. package/dist/charts/engine/trading/labels.cjs.map +1 -1
  240. package/dist/charts/engine/trading/labels.js +24 -4
  241. package/dist/charts/engine/trading/labels.js.map +1 -1
  242. package/dist/charts/engine/trading/studies.cjs +1 -1
  243. package/dist/charts/engine/trading/studies.cjs.map +1 -1
  244. package/dist/charts/engine/trading/studies.d.cts +8 -0
  245. package/dist/charts/engine/trading/studies.d.ts +8 -0
  246. package/dist/charts/engine/trading/studies.js +4 -1
  247. package/dist/charts/engine/trading/studies.js.map +1 -1
  248. package/dist/charts/engine/trading/types.d.cts +34 -11
  249. package/dist/charts/engine/trading/types.d.ts +34 -11
  250. package/dist/charts/engine/types.d.cts +25 -4
  251. package/dist/charts/engine/types.d.ts +25 -4
  252. package/dist/charts/react/charts.cjs +1 -1
  253. package/dist/charts/react/charts.cjs.map +1 -1
  254. package/dist/charts/react/charts.js +20 -15
  255. package/dist/charts/react/charts.js.map +1 -1
  256. package/dist/charts/react/graph.cjs +1 -1
  257. package/dist/charts/react/graph.cjs.map +1 -1
  258. package/dist/charts/react/graph.d.cts +6 -0
  259. package/dist/charts/react/graph.d.ts +6 -0
  260. package/dist/charts/react/graph.js +28 -27
  261. package/dist/charts/react/graph.js.map +1 -1
  262. package/dist/charts/react/orderbook.cjs +1 -1
  263. package/dist/charts/react/orderbook.cjs.map +1 -1
  264. package/dist/charts/react/orderbook.d.cts +3 -1
  265. package/dist/charts/react/orderbook.d.ts +3 -1
  266. package/dist/charts/react/orderbook.js +1 -0
  267. package/dist/charts/react/orderbook.js.map +1 -1
  268. package/dist/charts/react/shapes.cjs.map +1 -1
  269. package/dist/charts/react/shapes.d.cts +4 -3
  270. package/dist/charts/react/shapes.d.ts +4 -3
  271. package/dist/charts/react/shapes.js.map +1 -1
  272. package/dist/charts/react/three-d.cjs +1 -1
  273. package/dist/charts/react/three-d.cjs.map +1 -1
  274. package/dist/charts/react/three-d.d.cts +7 -0
  275. package/dist/charts/react/three-d.d.ts +7 -0
  276. package/dist/charts/react/three-d.js +14 -13
  277. package/dist/charts/react/three-d.js.map +1 -1
  278. package/dist/charts/react/trading.cjs.map +1 -1
  279. package/dist/charts/react/trading.d.cts +3 -3
  280. package/dist/charts/react/trading.d.ts +3 -3
  281. package/dist/charts/react/trading.js.map +1 -1
  282. package/dist/core/contracts.cjs +1 -1
  283. package/dist/core/contracts.cjs.map +1 -1
  284. package/dist/core/contracts.js +1 -1
  285. package/dist/core/contracts.js.map +1 -1
  286. package/dist/native/charts/src/canvas.cjs +1 -1
  287. package/dist/native/charts/src/canvas.js +4 -3
  288. package/dist/native/charts/src/engine/controller.cjs +2 -2
  289. package/dist/native/charts/src/engine/controller.cjs.map +1 -1
  290. package/dist/native/charts/src/engine/controller.js +102 -104
  291. package/dist/native/charts/src/engine/controller.js.map +1 -1
  292. package/dist/native/charts/src/engine/labels.cjs +1 -1
  293. package/dist/native/charts/src/engine/labels.cjs.map +1 -1
  294. package/dist/native/charts/src/engine/labels.js +14 -1
  295. package/dist/native/charts/src/engine/labels.js.map +1 -1
  296. package/dist/native/charts/src/engine/model.cjs +1 -1
  297. package/dist/native/charts/src/engine/model.cjs.map +1 -1
  298. package/dist/native/charts/src/engine/model.js +180 -157
  299. package/dist/native/charts/src/engine/model.js.map +1 -1
  300. package/dist/native/charts/src/engine/overlay.cjs.map +1 -1
  301. package/dist/native/charts/src/engine/overlay.js.map +1 -1
  302. package/dist/native/charts/src/engine/presets.cjs +1 -1
  303. package/dist/native/charts/src/engine/presets.cjs.map +1 -1
  304. package/dist/native/charts/src/engine/presets.js +8 -2
  305. package/dist/native/charts/src/engine/presets.js.map +1 -1
  306. package/dist/native/charts/src/engine/scene.cjs +1 -1
  307. package/dist/native/charts/src/engine/scene.cjs.map +1 -1
  308. package/dist/native/charts/src/engine/scene.js +188 -122
  309. package/dist/native/charts/src/engine/scene.js.map +1 -1
  310. package/dist/native/charts/src/engine/shapes/chord.cjs +1 -1
  311. package/dist/native/charts/src/engine/shapes/chord.cjs.map +1 -1
  312. package/dist/native/charts/src/engine/shapes/chord.js +108 -103
  313. package/dist/native/charts/src/engine/shapes/chord.js.map +1 -1
  314. package/dist/native/charts/src/engine/shapes/layout.cjs +2 -2
  315. package/dist/native/charts/src/engine/shapes/layout.cjs.map +1 -1
  316. package/dist/native/charts/src/engine/shapes/layout.js +88 -73
  317. package/dist/native/charts/src/engine/shapes/layout.js.map +1 -1
  318. package/dist/native/components/Chart/ChartBase.cjs +1 -1
  319. package/dist/native/components/Chart/ChartBase.cjs.map +1 -1
  320. package/dist/native/components/Chart/ChartBase.js +127 -115
  321. package/dist/native/components/Chart/ChartBase.js.map +1 -1
  322. package/dist/native/components/Chart/charts.cjs +1 -1
  323. package/dist/native/components/Chart/charts.cjs.map +1 -1
  324. package/dist/native/components/Chart/charts.js +8 -5
  325. package/dist/native/components/Chart/charts.js.map +1 -1
  326. package/dist/native/components/Chart/scene.cjs +1 -1
  327. package/dist/native/components/Chart/scene.cjs.map +1 -1
  328. package/dist/native/components/Chart/scene.d.cts +6 -1
  329. package/dist/native/components/Chart/scene.d.ts +6 -1
  330. package/dist/native/components/Chart/scene.js +99 -50
  331. package/dist/native/components/Chart/scene.js.map +1 -1
  332. package/dist/native/components/Chart/types.d.cts +7 -1
  333. package/dist/native/components/Chart/types.d.ts +7 -1
  334. package/dist/native/components/Charts/charts.cjs +1 -1
  335. package/dist/native/components/Charts/charts.cjs.map +1 -1
  336. package/dist/native/components/Charts/charts.js +23 -18
  337. package/dist/native/components/Charts/charts.js.map +1 -1
  338. package/dist/native/components/ShapeChart/ShapeChartBase.cjs +1 -1
  339. package/dist/native/components/ShapeChart/ShapeChartBase.cjs.map +1 -1
  340. package/dist/native/components/ShapeChart/ShapeChartBase.d.cts +1 -1
  341. package/dist/native/components/ShapeChart/ShapeChartBase.d.ts +1 -1
  342. package/dist/native/components/ShapeChart/ShapeChartBase.js +97 -107
  343. package/dist/native/components/ShapeChart/ShapeChartBase.js.map +1 -1
  344. package/dist/native/components/ShapeChart/geometry.cjs +1 -1
  345. package/dist/native/components/ShapeChart/geometry.cjs.map +1 -1
  346. package/dist/native/components/ShapeChart/geometry.js +120 -36
  347. package/dist/native/components/ShapeChart/geometry.js.map +1 -1
  348. package/dist/native/components/ShapeChart/types.d.cts +6 -4
  349. package/dist/native/components/ShapeChart/types.d.ts +6 -4
  350. package/dist/native/source/components/Chart/ChartBase.tsx +19 -6
  351. package/dist/native/source/components/Chart/charts.tsx +10 -3
  352. package/dist/native/source/components/Chart/scene.tsx +85 -0
  353. package/dist/native/source/components/Chart/types.ts +7 -0
  354. package/dist/native/source/components/Charts/charts.tsx +7 -0
  355. package/dist/native/source/components/ShapeChart/ShapeChartBase.tsx +10 -36
  356. package/dist/native/source/components/ShapeChart/geometry.ts +188 -18
  357. package/dist/native/source/components/ShapeChart/types.ts +6 -4
  358. package/dist/taro/chart-a11y.d.ts +7 -0
  359. package/dist/taro/charts.d.ts +4 -1
  360. package/dist/taro/index.js +3212 -3049
  361. package/dist/taro/shape-charts.d.ts +6 -4
  362. package/dist/uni/AreaChart.vue +2 -1
  363. package/dist/uni/AreaChart.vue.d.ts +1 -1
  364. package/dist/uni/BarChart.vue +2 -1
  365. package/dist/uni/BarChart.vue.d.ts +1 -1
  366. package/dist/uni/BoxPlotChart.vue +2 -1
  367. package/dist/uni/BubbleChart.vue +2 -1
  368. package/dist/uni/CandlestickChart.vue +2 -1
  369. package/dist/uni/Chart.vue +2 -1
  370. package/dist/uni/Divider.vue.d.ts +1 -1
  371. package/dist/uni/DonutChart.vue.d.ts +1 -1
  372. package/dist/uni/GanttChart.vue +2 -1
  373. package/dist/uni/GanttChart.vue.d.ts +11 -0
  374. package/dist/uni/GaugeChart.vue.d.ts +1 -1
  375. package/dist/uni/HeatmapChart.vue +2 -1
  376. package/dist/uni/HistogramChart.vue +2 -1
  377. package/dist/uni/HorizontalBarChart.vue +2 -1
  378. package/dist/uni/HorizontalBarChart.vue.d.ts +1 -1
  379. package/dist/uni/LineChart.vue +2 -1
  380. package/dist/uni/MixedChart.vue +2 -1
  381. package/dist/uni/PieChart.vue.d.ts +1 -1
  382. package/dist/uni/QuadrantChart.vue +2 -1
  383. package/dist/uni/RangeAreaChart.vue +2 -1
  384. package/dist/uni/ScatterChart.vue +2 -1
  385. package/dist/uni/Sparkline.vue +2 -1
  386. package/dist/uni/WaterfallChart.vue +2 -1
  387. package/dist/uni/chart-a11y.d.ts +7 -0
  388. package/dist/uni/chart-a11y.js +29 -0
  389. package/dist/uni/chart-canvas.d.ts +9 -0
  390. package/dist/uni/chart-canvas.js +11 -1
  391. package/dist/uni/chart-types.d.ts +8 -1
  392. package/dist/uni/chart-types.js +5 -1
  393. package/dist/uni/charts-canvas.js +2 -1
  394. package/dist/uni/named-chart-options.d.ts +2 -0
  395. package/dist/uni/named-chart-options.js +3 -0
  396. package/dist/uni/shape-chart-canvas.d.ts +0 -2
  397. package/dist/uni/shape-chart-canvas.js +4 -36
  398. package/dist/uni/shape-chart-types.d.ts +2 -2
  399. package/dist/uni/shape-chart-types.js +2 -2
  400. package/dist/vue/components/Chart/Bar3DChart.vue.d.ts +2 -0
  401. package/dist/vue/components/Chart/DependencyGraph.vue.d.ts +2 -0
  402. package/dist/vue/components/Chart/GanttChart.vue.d.ts +15 -0
  403. package/dist/vue/components/Chart/GanttChart.vue.js.map +1 -1
  404. package/dist/vue/components/Chart/GanttChart.vue_vue_type_script_setup_true_lang.js +8 -0
  405. package/dist/vue/components/Chart/GanttChart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  406. package/dist/vue/components/Chart/GraphChart.vue.d.ts +2 -0
  407. package/dist/vue/components/Chart/Line3DChart.vue.d.ts +2 -0
  408. package/dist/vue/components/Chart/Scatter3DChart.vue.d.ts +2 -0
  409. package/dist/vue/components/Chart/Surface3DChart.vue.d.ts +2 -0
  410. package/dist/vue/components/Chart/TradingChart.vue.d.ts +9 -0
  411. package/dist/vue/components/Chart/TreeChart.vue.d.ts +2 -0
  412. package/dist/vue/components/Chart/graph.d.ts +3 -0
  413. package/dist/vue/components/Chart/graph.js +2 -0
  414. package/dist/vue/components/Chart/graph.js.map +1 -1
  415. package/dist/vue/components/Chart/three-d.d.ts +3 -0
  416. package/dist/vue/components/Chart/three-d.js +2 -0
  417. package/dist/vue/components/Chart/three-d.js.map +1 -1
  418. package/dist/vue/components/Chart/trading.d.ts +7 -2
  419. package/dist/vue/components/Chart/trading.js +1 -0
  420. package/dist/vue/components/Chart/trading.js.map +1 -1
  421. package/dist/weapp/area-chart/index.wxml +1 -1
  422. package/dist/weapp/bar-chart/index.wxml +1 -1
  423. package/dist/weapp/box-plot-chart/index.wxml +1 -1
  424. package/dist/weapp/bubble-chart/index.wxml +1 -1
  425. package/dist/weapp/candlestick-chart/index.wxml +1 -1
  426. package/dist/weapp/chart/index.wxml +1 -1
  427. package/dist/weapp/charts/canvas.js +326 -54
  428. package/dist/weapp/charts/core.js +2 -0
  429. package/dist/weapp/controls.js +58 -27
  430. package/dist/weapp/gantt-chart/index.wxml +1 -1
  431. package/dist/weapp/heatmap-chart/index.wxml +1 -1
  432. package/dist/weapp/histogram-chart/index.wxml +1 -1
  433. package/dist/weapp/horizontal-bar-chart/index.wxml +1 -1
  434. package/dist/weapp/line-chart/index.wxml +1 -1
  435. package/dist/weapp/mixed-chart/index.wxml +1 -1
  436. package/dist/weapp/quadrant-chart/index.wxml +1 -1
  437. package/dist/weapp/range-area-chart/index.wxml +1 -1
  438. package/dist/weapp/scatter-chart/index.wxml +1 -1
  439. package/dist/weapp/sparkline/index.wxml +1 -1
  440. package/dist/weapp/types.d.ts +11 -2
  441. package/dist/weapp/waterfall-chart/index.wxml +1 -1
  442. package/dist/web-components/components/chart/extended.d.ts +4 -0
  443. package/dist/web-components/components/chart/extended.js +8 -2
  444. package/dist/web-components/components/chart/extended.js.map +1 -1
  445. package/dist/web-components/components/chart-3d/chart-3d.d.ts +1 -1
  446. package/dist/web-components/components/chart-3d/chart-3d.js.map +1 -1
  447. package/dist/web-components/components/graph/graph.d.ts +2 -0
  448. package/dist/web-components/components/graph/graph.js +3 -2
  449. package/dist/web-components/components/graph/graph.js.map +1 -1
  450. package/dist/web-components/components/trading-chart/trading-chart.d.ts +1 -1
  451. package/dist/web-components/components/trading-chart/trading-chart.js.map +1 -1
  452. package/dist/web-components/html-custom-data.json +45 -0
  453. package/dist/web-components/types/react.d.ts +4 -4
  454. package/dist/web-components/types/solid.d.ts +8 -8
  455. package/dist/web-components/types/svelte.d.ts +8 -8
  456. package/dist/web-components/types/vue.d.ts +4 -4
  457. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ladder.js","names":["LABELS","COLUMNS","createOrderBook","options","initial","store","createOrderBookStore","emitter","createEmitter","fmt","createFormatters","finePrice","texts","localeLabels","inferred","colors","lastPrice","previousLast","lastDirection","flashes","shownRange","drawn","rows","hoverAt","keyRow","hoverKey","hovered","rowHeight","host","createHost","container","sideColors","root","labels","refreshFormat","grouping","raw","inferPriceDecimals","decimalsOf","inferSizeDecimals","fine","numberFormat","v","applyTexts","applyOptions","sideRows","side","out","sum","notional","i","count","p","price","s","size","draw","ctx","l","mode","compact","width","fontSize","rh","headerH","spreadH","imbalanceH","sides","avail","height","perSide","pad","dpr","asks","bids","y","asksTop","row","spreadY","bidsTop","spreadTop","cols","all","c","shownCols","n","inner","colX","j","barsMode","barMax","flash","duration","nextFlashes","animating","inside","range","key","previous","entry","now","prices","r","hx","hy","list","threshold","text","toCss","theme","muted","fontOf","color","large","w","f","flashAlpha","age","ty","label","x","roundRect","edge","mid","shown","sy","dirColor","cy","priceText","spread","bps","right","rw","bidSum","askSum","share","by","bh","bw","split","tooltipHtml","doc","ax","toEvent","bb","ba","onPointerMove","localPoint","event","onPointerLeave","onClick","onKeyDown","order","current","o","down","clamp","onBlur","changed","snapshot","applyDeltas","deltas","regroup","next","handler"],"sources":["../../../../../charts/src/engine/orderbook/ladder.ts"],"sourcesContent":["// createOrderBook: the price ladder (asks above the spread row, bids below)\n// drawn with Canvas2D. Any number of deltas between two frames cost one\n// draw of the visible rows; changed levels flash, walls stand out, hovering\n// sums the levels up to the pointer.\n\nimport { toCss, type Rgba } from \"../color\";\nimport {\n applyDeltas,\n createOrderBookStore,\n decimalsOf,\n inferPriceDecimals,\n inferSizeDecimals,\n} from \"./book\";\nimport {\n clamp,\n createFormatters,\n fontOf,\n numberFormat,\n roundRect,\n sideColors,\n type Formatters,\n} from \"./format\";\nimport { localeLabels, type LabelDictionary } from \"../locale\";\nimport { createEmitter, createHost, localPoint, tooltipHtml } from \"./host\";\nimport type {\n OrderBookEventMap,\n OrderBookInstance,\n OrderBookLabels,\n OrderBookLevelEvent,\n OrderBookOptions,\n OrderBookSide,\n} from \"./types\";\n\nconst LABELS: LabelDictionary<OrderBookLabels> = {\n en: {\n price: \"Price\",\n size: \"Size\",\n total: \"Total\",\n spread: \"Spread\",\n average: \"Avg. price\",\n sum: \"Sum\",\n notional: \"Notional\",\n buyShare: \"B\",\n sellShare: \"S\",\n bid: \"Bid\",\n ask: \"Ask\",\n basisPoints: \"bp\",\n name: \"Order book\",\n },\n zh: {\n price: \"价格\",\n size: \"数量\",\n total: \"累计\",\n spread: \"价差\",\n average: \"均价\",\n sum: \"累计数量\",\n notional: \"累计金额\",\n buyShare: \"买\",\n sellShare: \"卖\",\n bid: \"买一\",\n ask: \"卖一\",\n basisPoints: \"基点\",\n name: \"订单簿\",\n },\n ja: {\n price: \"価格\",\n size: \"数量\",\n total: \"累計\",\n spread: \"スプレッド\",\n average: \"平均価格\",\n sum: \"累計数量\",\n notional: \"累計金額\",\n buyShare: \"買\",\n sellShare: \"売\",\n bid: \"最良買気配\",\n ask: \"最良売気配\",\n basisPoints: \"bp\",\n name: \"板情報\",\n },\n fr: {\n price: \"Prix\",\n size: \"Quantité\",\n total: \"Cumul\",\n spread: \"Écart\",\n average: \"Prix moyen\",\n sum: \"Somme\",\n notional: \"Montant\",\n buyShare: \"A\",\n sellShare: \"V\",\n bid: \"Meilleur achat\",\n ask: \"Meilleure vente\",\n basisPoints: \"pb\",\n name: \"Carnet d’ordres\",\n },\n};\n\nconst COLUMNS = [\"price\", \"size\", \"total\"] as const;\n\ninterface Row extends OrderBookLevelEvent {\n /** Top of the row, CSS pixels */\n y: number;\n}\n\ninterface Flash {\n size: number;\n at: number;\n grew: boolean;\n}\n\n/**\n * Creates an order book ladder in `container`: asks, spread row and bids\n * with depth bars, grouping, flashes on changes and a hover summary.\n */\nexport const createOrderBook = (\n container: HTMLElement,\n initial: OrderBookOptions = {},\n): OrderBookInstance => {\n let options = initial;\n const store = createOrderBookStore();\n const emitter = createEmitter<OrderBookEventMap>();\n let fmt: Formatters = createFormatters(options, 2, 4);\n let finePrice = fmt.price;\n /** Texts in the locale, resolved on every option update */\n let texts = localeLabels(LABELS, options.locale, options.labels);\n let inferred = false;\n let colors = { up: [0, 0, 0, 1] as Rgba, down: [0, 0, 0, 1] as Rgba };\n let lastPrice: number | null = null;\n let previousLast = NaN;\n let lastDirection = 0;\n let flashes = new Map<string, Flash>();\n /** Price range of the rows of the previous frame, per side */\n const shownRange: Record<OrderBookSide, [number, number]> = {\n bid: [NaN, NaN],\n ask: [NaN, NaN],\n };\n let drawn = false;\n let rows: Row[] = [];\n let hoverAt: [number, number] | null = null;\n /** Keyboard selection: side and index from the spread */\n let keyRow: { side: OrderBookSide; index: number } | null = null;\n let hoverKey = \"\";\n let hovered: Row | null = null;\n let rowHeight = 20;\n\n const host = createHost(container, {\n className: \"minerva-order-book\",\n draw,\n onTheme: () => {\n colors = sideColors(host.theme, options);\n },\n });\n const { root, doc } = host;\n root.tabIndex = 0;\n root.setAttribute(\"role\", \"figure\");\n root.style.cursor = \"default\";\n\n const labels = () => texts;\n\n const refreshFormat = () => {\n const grouping = options.grouping ?? 0;\n const raw = inferPriceDecimals(store);\n fmt = createFormatters(\n options,\n grouping > 0 ? Math.max(decimalsOf(grouping), 0) : raw,\n inferSizeDecimals(store),\n );\n // the spread row keeps the raw tick precision (a 0.1 spread is not \"0\")\n const fine = numberFormat(\n options.locale,\n Math.max(fmt.priceDecimals, options.grouping ? raw : 0),\n );\n finePrice = options.formatPrice\n ? fmt.price\n : (v) => (Number.isFinite(v) ? fine.format(v) : \"–\");\n };\n\n const applyTexts = () => {\n texts = localeLabels(LABELS, options.locale, options.labels);\n root.setAttribute(\"aria-label\", options.ariaLabel ?? texts.name);\n };\n\n const applyOptions = () => {\n applyTexts();\n colors = sideColors(host.theme, options);\n refreshFormat();\n // grouping changes the rows: no flash for the new buckets\n flashes = new Map();\n drawn = false;\n host.invalidate();\n };\n\n /** Levels of a side with their cumulative values */\n const sideRows = (side: OrderBookSide, limit: number): Row[] => {\n const { price, size, count } = store.levels(side, {\n step: options.grouping ?? 0,\n limit,\n });\n const out: Row[] = [];\n let sum = 0;\n let notional = 0;\n for (let i = 0; i < count; i++) {\n const p = price[i]!;\n const s = size[i]!;\n sum += s;\n notional += s * p;\n out.push({\n side,\n index: i,\n price: p,\n size: s,\n sum,\n notional,\n average: notional / sum,\n y: 0,\n });\n }\n return out;\n };\n\n function draw(now: number): boolean {\n const ctx = host.ctx;\n if (!ctx) return false;\n const { width, height, dpr, theme } = host;\n const l = labels();\n const mode = options.mode ?? \"both\";\n const compact = width < 260;\n const fontSize = options.fontSize ?? (compact ? 11 : 12);\n const rh = (rowHeight = Math.max(\n 12,\n options.rowHeight ?? (compact ? 18 : 20),\n ));\n const headerH = options.header === false ? 0 : rh + 2;\n const spreadH = options.spreadRow === false ? 0 : Math.round(rh * 1.7);\n const imbalanceH = options.imbalance === false ? 0 : 24;\n const sides = mode === \"both\" ? 2 : 1;\n const avail = Math.max(0, height - headerH - spreadH - imbalanceH);\n const perSide = Math.max(0, options.rows ?? Math.floor(avail / rh / sides));\n const pad = compact ? 6 : 10;\n\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n ctx.clearRect(0, 0, width, height);\n\n const asks = mode === \"bids\" ? [] : sideRows(\"ask\", perSide);\n const bids = mode === \"asks\" ? [] : sideRows(\"bid\", perSide);\n\n // vertical layout\n let y = headerH;\n const asksTop = y;\n if (mode !== \"bids\") {\n for (const row of asks) row.y = asksTop + (perSide - 1 - row.index) * rh;\n y += perSide * rh;\n }\n const spreadY = mode === \"bids\" ? headerH : y;\n if (mode !== \"bids\") y += spreadH;\n else y = headerH + spreadH;\n const bidsTop = y;\n for (const row of bids) row.y = bidsTop + row.index * rh;\n rows = [...asks, ...bids];\n const spreadTop = mode === \"asks\" ? asksTop + perSide * rh : spreadY;\n\n // columns\n const cols = (options.columns ?? COLUMNS).filter(\n (c, i, all) => all.indexOf(c) === i,\n );\n const shownCols = compact && cols.length > 2 ? cols.slice(0, 2) : cols;\n const n = shownCols.length;\n const inner = width - pad * 2;\n const colX = shownCols.map((_, j) =>\n j === 0\n ? pad\n : pad + inner * (j === n - 1 ? 1 : 0.24 + (0.76 * j) / (n - 1)),\n );\n\n // depth bar scale\n const barsMode = options.depthBars ?? \"cumulative\";\n let barMax = 0;\n for (const row of rows) {\n barMax = Math.max(barMax, barsMode === \"level\" ? row.size : row.sum);\n }\n\n // flashes: compare with the sizes of the previous frame\n const flash = options.flash !== false;\n const duration = Math.max(1, options.flashDuration ?? 450);\n const nextFlashes = new Map<string, Flash>();\n let animating = false;\n const inside = (row: Row) => {\n const range = shownRange[row.side];\n return drawn && row.price > range[0] && row.price < range[1];\n };\n for (const row of rows) {\n const key = `${row.side}:${row.price}`;\n const previous = flashes.get(key);\n let entry: Flash;\n // a level scrolling into view is not new: only levels appearing\n // between the rows already shown flash\n if (!previous)\n entry = {\n size: row.size,\n at: inside(row) ? now : -Infinity,\n grew: true,\n };\n else if (previous.size !== row.size)\n entry = { size: row.size, at: now, grew: row.size > previous.size };\n else entry = previous;\n nextFlashes.set(key, entry);\n }\n flashes = nextFlashes;\n drawn = true;\n for (const side of [\"bid\", \"ask\"] as const) {\n const list = side === \"bid\" ? bids : asks;\n const prices = list.map((r) => r.price);\n shownRange[side] = prices.length\n ? [Math.min(...prices), Math.max(...prices)]\n : [NaN, NaN];\n }\n\n // hover: rows from the spread to the hovered one\n hovered = null;\n if (hoverAt) {\n const [hx, hy] = hoverAt;\n if (hx >= 0 && hx <= width)\n hovered = rows.find((r) => hy >= r.y && hy < r.y + rh) ?? null;\n } else if (keyRow) {\n const list = keyRow.side === \"ask\" ? asks : bids;\n hovered = list[Math.min(keyRow.index, list.length - 1)] ?? null;\n }\n\n const threshold = options.largeOrderThreshold ?? Infinity;\n const text = toCss(theme.text);\n const muted = toCss(theme.textMuted);\n\n // header\n if (headerH) {\n ctx.font = fontOf(theme, options, 400, fontSize - 1);\n ctx.fillStyle = muted;\n ctx.textBaseline = \"middle\";\n shownCols.forEach((c, j) => {\n ctx.textAlign = j === 0 ? \"left\" : \"right\";\n ctx.fillText(l[c], colX[j]!, rh / 2 + 1);\n });\n }\n\n // rows\n for (const row of rows) {\n const color = row.side === \"bid\" ? colors.up : colors.down;\n const key = `${row.side}:${row.price}`;\n const large = row.size >= threshold;\n // hover band (cumulative selection)\n if (hovered && hovered.side === row.side && row.index <= hovered.index) {\n ctx.fillStyle = toCss(theme.text, row === hovered ? 0.09 : 0.045);\n ctx.fillRect(0, row.y, width, rh);\n }\n // depth bar\n if (barsMode !== \"none\" && barMax > 0) {\n const value = barsMode === \"level\" ? row.size : row.sum;\n const w = (value / barMax) * width;\n ctx.fillStyle = toCss(color, 0.14);\n ctx.fillRect(width - w, row.y + 1, w, rh - 2);\n }\n if (large) {\n ctx.fillStyle = toCss(color, 0.16);\n ctx.fillRect(0, row.y + 1, width, rh - 2);\n ctx.fillStyle = toCss(color);\n ctx.fillRect(0, row.y + 2, 3, rh - 4);\n }\n // flash: behind the size that changed (a whole-row flash makes a\n // ladder at 200 updates/s flicker)\n const f = flashes.get(key);\n let flashAlpha = 0;\n if (flash && f && Number.isFinite(f.at)) {\n const age = (now - f.at) / duration;\n if (age < 1) {\n flashAlpha = (1 - age) * (1 - age);\n animating = true;\n }\n }\n // texts\n ctx.textBaseline = \"middle\";\n const ty = row.y + rh / 2 + 0.5;\n shownCols.forEach((c, j) => {\n ctx.textAlign = j === 0 ? \"left\" : \"right\";\n if (c === \"price\") {\n ctx.font = fontOf(theme, options, 500, fontSize);\n ctx.fillStyle = toCss(color);\n ctx.fillText(\n fmt.price(row.price),\n colX[j]! + (large && j === 0 ? 4 : 0),\n ty,\n );\n } else if (c === \"size\") {\n ctx.font = fontOf(theme, options, large ? 700 : 400, fontSize);\n const label = fmt.size(row.size);\n if (flashAlpha > 0 && f) {\n const w = ctx.measureText(label).width + 10;\n const x = j === 0 ? colX[j]! - 5 : colX[j]! - w + 5;\n ctx.fillStyle = toCss(\n f.grew ? color : theme.textMuted,\n (f.grew ? 0.45 : 0.3) * flashAlpha,\n );\n roundRect(ctx, x, row.y + 2, w, rh - 4, 3);\n ctx.fill();\n }\n ctx.fillStyle = text;\n ctx.fillText(label, colX[j]!, ty);\n } else {\n ctx.font = fontOf(theme, options, 400, fontSize);\n ctx.fillStyle = muted;\n ctx.fillText(\n options.total === \"quote\"\n ? fmt.notional(row.notional)\n : fmt.total(row.sum),\n colX[j]!,\n ty,\n );\n }\n });\n }\n if (hovered) {\n // edge of the selection\n ctx.strokeStyle = toCss(theme.textMuted, 0.7);\n ctx.setLineDash([3, 3]);\n ctx.beginPath();\n const edge =\n hovered.side === \"bid\" ? hovered.y + rh - 0.5 : hovered.y + 0.5;\n ctx.moveTo(0, edge);\n ctx.lineTo(width, edge);\n ctx.stroke();\n ctx.setLineDash([]);\n }\n\n // spread row\n if (spreadH) {\n const mid = store.mid();\n const shown = lastPrice ?? mid;\n if (Number.isFinite(shown) && shown !== previousLast) {\n if (Number.isFinite(previousLast))\n lastDirection =\n shown > previousLast\n ? 1\n : shown < previousLast\n ? -1\n : lastDirection;\n previousLast = shown;\n }\n const sy = spreadTop;\n ctx.fillStyle = toCss(theme.text, 0.035);\n ctx.fillRect(0, sy, width, spreadH);\n ctx.strokeStyle = toCss(theme.grid);\n ctx.beginPath();\n ctx.moveTo(0, Math.round(sy) + 0.5);\n ctx.lineTo(width, Math.round(sy) + 0.5);\n ctx.moveTo(0, Math.round(sy + spreadH) - 0.5);\n ctx.lineTo(width, Math.round(sy + spreadH) - 0.5);\n ctx.stroke();\n const dirColor =\n lastDirection > 0\n ? colors.up\n : lastDirection < 0\n ? colors.down\n : theme.text;\n const cy = sy + spreadH / 2 + 0.5;\n ctx.textBaseline = \"middle\";\n ctx.textAlign = \"left\";\n ctx.font = fontOf(theme, options, 700, fontSize + (compact ? 2 : 4));\n ctx.fillStyle = toCss(dirColor);\n const priceText = finePrice(shown);\n ctx.fillText(priceText, pad, cy);\n let x = pad + ctx.measureText(priceText).width + 6;\n if (lastDirection !== 0) {\n // arrow of the last move\n const s = compact ? 4 : 5;\n ctx.beginPath();\n if (lastDirection > 0) {\n ctx.moveTo(x, cy + s * 0.6);\n ctx.lineTo(x + s, cy - s * 0.7);\n ctx.lineTo(x + s * 2, cy + s * 0.6);\n } else {\n ctx.moveTo(x, cy - s * 0.6);\n ctx.lineTo(x + s, cy + s * 0.7);\n ctx.lineTo(x + s * 2, cy - s * 0.6);\n }\n ctx.closePath();\n ctx.fill();\n x += s * 2 + 6;\n }\n const spread = store.spread();\n if (Number.isFinite(spread)) {\n ctx.textAlign = \"right\";\n ctx.font = fontOf(theme, options, 400, fontSize - 1);\n const bps = (spread / mid) * 1e4;\n const right = `${finePrice(spread)} · ${fmt.fixed(bps, bps < 10 ? 2 : 1)} ${l.basisPoints}`;\n ctx.fillStyle = text;\n ctx.fillText(right, width - pad, cy);\n if (!compact) {\n const rw = ctx.measureText(right).width;\n ctx.fillStyle = muted;\n const label = `${l.spread}`;\n if (width - pad - rw - 8 - ctx.measureText(label).width > x)\n ctx.fillText(label, width - pad - rw - 8, cy);\n }\n }\n }\n\n // imbalance bar\n if (imbalanceH) {\n let bidSum = 0;\n let askSum = 0;\n for (const r of bids) bidSum += r.size;\n for (const r of asks) askSum += r.size;\n const all = bidSum + askSum;\n const share = all > 0 ? bidSum / all : 0.5;\n const by = height - imbalanceH + 6;\n const bh = imbalanceH - 10;\n const bw = width - pad * 2;\n const split = pad + bw * share;\n ctx.save();\n roundRect(ctx, pad, by, bw, bh, 3);\n ctx.clip();\n ctx.fillStyle = toCss(colors.up, 0.22);\n ctx.fillRect(pad, by, split - pad, bh);\n ctx.fillStyle = toCss(colors.down, 0.22);\n ctx.fillRect(split, by, pad + bw - split, bh);\n ctx.restore();\n ctx.fillStyle = toCss(theme.background);\n ctx.fillRect(split - 1, by, 2, bh);\n ctx.font = fontOf(theme, options, 600, fontSize - 1);\n ctx.textBaseline = \"middle\";\n ctx.textAlign = \"left\";\n ctx.fillStyle = toCss(colors.up);\n const mid = by + bh / 2 + 0.5;\n ctx.fillText(\n `${l.buyShare} ${fmt.percent(share, 1, false)}`,\n pad + 6,\n mid,\n );\n ctx.textAlign = \"right\";\n ctx.fillStyle = toCss(colors.down);\n ctx.fillText(\n `${fmt.percent(1 - share, 1, false)} ${l.sellShare}`,\n pad + bw - 6,\n mid,\n );\n }\n\n // tooltip and hover event\n if (hovered && options.tooltip !== false) {\n const color = hovered.side === \"bid\" ? colors.up : colors.down;\n tooltipHtml(\n doc,\n host.tooltip,\n { text: fmt.price(hovered.price), color: toCss(color) },\n [\n [l.average, finePrice(hovered.average)],\n [l.sum, fmt.total(hovered.sum)],\n [l.notional, fmt.notional(hovered.notional)],\n ],\n );\n host.tooltip.style.display = \"block\";\n const ax = hoverAt ? hoverAt[0] : width * 0.4;\n host.placeTooltip(\n host.tooltip,\n ax,\n hovered.y + rh / 2,\n ax > width / 2 ? \"left\" : \"right\",\n );\n } else {\n host.tooltip.style.display = \"none\";\n }\n const key = hovered\n ? `${hovered.side}|${hovered.index}|${hovered.price}|${hovered.size}|${hovered.sum}`\n : \"\";\n if (key !== hoverKey) {\n hoverKey = key;\n emitter.emit(\"hover\", hovered ? toEvent(hovered) : null);\n }\n\n const bb = store.bestBid();\n const ba = store.bestAsk();\n host.describe(\n `${options.ariaLabel ?? l.name}. ${l.bid} ${finePrice(bb)}, ${l.ask} ${finePrice(ba)}, ${l.spread} ${finePrice(ba - bb)}.`,\n );\n return animating;\n }\n\n const toEvent = (row: Row): OrderBookLevelEvent => ({\n side: row.side,\n index: row.index,\n price: row.price,\n size: row.size,\n sum: row.sum,\n notional: row.notional,\n average: row.average,\n });\n\n // ---------------------------------------------------------- interaction\n\n const onPointerMove = (event: PointerEvent) => {\n hoverAt = localPoint(root, event);\n keyRow = null;\n host.invalidate();\n };\n const onPointerLeave = () => {\n hoverAt = null;\n host.invalidate();\n };\n const onClick = (event: MouseEvent) => {\n const [x, y] = localPoint(root, event);\n const row = rows.find((r) => y >= r.y && y < r.y + rowHeight);\n if (row && x >= 0) emitter.emit(\"levelClick\", toEvent(row));\n };\n const onKeyDown = (event: KeyboardEvent) => {\n const order: { side: OrderBookSide; index: number }[] = [];\n const asks = rows.filter((r) => r.side === \"ask\");\n const bids = rows.filter((r) => r.side === \"bid\");\n for (let i = asks.length - 1; i >= 0; i--)\n order.push({ side: \"ask\", index: i });\n for (let i = 0; i < bids.length; i++) order.push({ side: \"bid\", index: i });\n if (!order.length) return;\n const current = keyRow\n ? order.findIndex(\n (o) => o.side === keyRow!.side && o.index === keyRow!.index,\n )\n : -1;\n switch (event.key) {\n case \"ArrowDown\":\n case \"ArrowUp\": {\n const down = event.key === \"ArrowDown\";\n // first press: the best level on that side of the spread\n const next =\n current >= 0\n ? clamp(current + (down ? 1 : -1), 0, order.length - 1)\n : down\n ? Math.min(asks.length, order.length - 1)\n : Math.max(0, asks.length - 1);\n keyRow = order[next] ?? null;\n hoverAt = null;\n host.invalidate();\n break;\n }\n case \"Enter\":\n case \" \":\n if (hovered) emitter.emit(\"levelClick\", toEvent(hovered));\n break;\n case \"Escape\":\n keyRow = null;\n host.invalidate();\n break;\n default:\n return;\n }\n event.preventDefault();\n };\n const onBlur = () => {\n if (keyRow) {\n keyRow = null;\n host.invalidate();\n }\n };\n root.addEventListener(\"pointermove\", onPointerMove);\n root.addEventListener(\"pointerleave\", onPointerLeave);\n root.addEventListener(\"click\", onClick);\n root.addEventListener(\"keydown\", onKeyDown);\n root.addEventListener(\"blur\", onBlur);\n\n const changed = () => {\n if (!inferred && store.count(\"bid\") + store.count(\"ask\") > 0) {\n inferred = true;\n refreshFormat();\n }\n host.invalidate();\n };\n\n const instance: OrderBookInstance = {\n setBook(snapshot) {\n store.setSnapshot(snapshot);\n inferred = false;\n changed();\n },\n applyDeltas(deltas) {\n if (applyDeltas(store, deltas)) changed();\n },\n clear() {\n store.clear();\n inferred = false;\n flashes = new Map();\n drawn = false;\n host.invalidate();\n },\n setLastPrice(price) {\n lastPrice = price !== null && Number.isFinite(price) ? price : null;\n host.invalidate();\n },\n setOptions(next) {\n const regroup =\n (next.grouping ?? 0) !== (options.grouping ?? 0) ||\n next.mode !== options.mode;\n options = next;\n if (regroup) applyOptions();\n else {\n applyTexts();\n colors = sideColors(host.theme, options);\n refreshFormat();\n host.invalidate();\n }\n },\n getStore: () => store,\n on: (event, handler) => emitter.on(event, handler),\n resize() {\n host.invalidate();\n },\n destroy() {\n root.removeEventListener(\"pointermove\", onPointerMove);\n root.removeEventListener(\"pointerleave\", onPointerLeave);\n root.removeEventListener(\"click\", onClick);\n root.removeEventListener(\"keydown\", onKeyDown);\n root.removeEventListener(\"blur\", onBlur);\n emitter.clear();\n host.destroy();\n },\n };\n applyOptions();\n return instance;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ladder.js","names":["LABELS","COLUMNS","createOrderBook","options","initial","store","createOrderBookStore","emitter","createEmitter","fmt","createFormatters","finePrice","texts","localeLabels","inferred","colors","lastPrice","previousLast","lastDirection","flashes","shownRange","drawn","rows","hoverAt","keyRow","hoverKey","hovered","rowHeight","host","createHost","container","sideColors","root","labels","refreshFormat","grouping","raw","inferPriceDecimals","decimalsOf","inferSizeDecimals","fine","numberFormat","v","applyTexts","applyOptions","sideRows","side","out","sum","notional","i","count","p","price","s","size","draw","ctx","l","mode","compact","width","fontSize","rh","headerH","spreadH","imbalanceH","sides","avail","height","perSide","pad","dpr","asks","bids","y","asksTop","row","spreadY","bidsTop","spreadTop","cols","all","c","shownCols","n","inner","colX","j","barsMode","barMax","flash","duration","nextFlashes","animating","inside","range","key","previous","entry","now","prices","r","hx","hy","list","threshold","text","toCss","theme","muted","fontOf","color","large","w","f","flashAlpha","age","ty","label","x","roundRect","edge","mid","shown","sy","dirColor","cy","priceText","spread","bps","right","rw","bidSum","askSum","share","by","bh","bw","split","tooltipHtml","doc","ax","toEvent","bb","ba","onPointerMove","localPoint","event","onPointerLeave","onClick","onKeyDown","order","current","o","down","clamp","onBlur","changed","snapshot","applyDeltas","deltas","regroup","next","handler"],"sources":["../../../../../charts/src/engine/orderbook/ladder.ts"],"sourcesContent":["// createOrderBook: the price ladder (asks above the spread row, bids below)\n// drawn with Canvas2D. Any number of deltas between two frames cost one\n// draw of the visible rows; changed levels flash, walls stand out, hovering\n// sums the levels up to the pointer.\n\nimport { toCss, type Rgba } from \"../color\";\nimport {\n applyDeltas,\n createOrderBookStore,\n decimalsOf,\n inferPriceDecimals,\n inferSizeDecimals,\n} from \"./book\";\nimport {\n clamp,\n createFormatters,\n fontOf,\n numberFormat,\n roundRect,\n sideColors,\n type Formatters,\n} from \"./format\";\nimport { localeLabels, type LabelDictionary } from \"../locale\";\nimport { createEmitter, createHost, localPoint, tooltipHtml } from \"./host\";\nimport type {\n OrderBookEventMap,\n OrderBookInstance,\n OrderBookLabels,\n OrderBookLevelEvent,\n OrderBookOptions,\n OrderBookSide,\n} from \"./types\";\n\nconst LABELS: LabelDictionary<OrderBookLabels> = {\n en: {\n price: \"Price\",\n size: \"Size\",\n total: \"Total\",\n spread: \"Spread\",\n average: \"Avg. price\",\n sum: \"Sum\",\n notional: \"Notional\",\n buyShare: \"B\",\n sellShare: \"S\",\n bid: \"Bid\",\n ask: \"Ask\",\n basisPoints: \"bp\",\n name: \"Order book\",\n },\n zh: {\n price: \"价格\",\n size: \"数量\",\n total: \"累计\",\n spread: \"价差\",\n average: \"均价\",\n sum: \"累计数量\",\n notional: \"累计金额\",\n buyShare: \"买\",\n sellShare: \"卖\",\n bid: \"买一\",\n ask: \"卖一\",\n basisPoints: \"基点\",\n name: \"订单簿\",\n },\n ja: {\n price: \"価格\",\n size: \"数量\",\n total: \"累計\",\n spread: \"スプレッド\",\n average: \"平均価格\",\n sum: \"累計数量\",\n notional: \"累計金額\",\n buyShare: \"買\",\n sellShare: \"売\",\n bid: \"最良買気配\",\n ask: \"最良売気配\",\n basisPoints: \"bp\",\n name: \"板情報\",\n },\n fr: {\n price: \"Prix\",\n size: \"Quantité\",\n total: \"Cumul\",\n spread: \"Écart\",\n average: \"Prix moyen\",\n sum: \"Somme\",\n notional: \"Montant\",\n buyShare: \"A\",\n sellShare: \"V\",\n bid: \"Meilleur achat\",\n ask: \"Meilleure vente\",\n basisPoints: \"pb\",\n name: \"Carnet d’ordres\",\n },\n};\n\nconst COLUMNS = [\"price\", \"size\", \"total\"] as const;\n\ninterface Row extends OrderBookLevelEvent {\n /** Top of the row, CSS pixels */\n y: number;\n}\n\ninterface Flash {\n size: number;\n at: number;\n grew: boolean;\n}\n\n/**\n * Creates an order book ladder in `container`: asks, spread row and bids\n * with depth bars, grouping, flashes on changes and a hover summary.\n */\nexport const createOrderBook = (\n container: HTMLElement,\n initial: OrderBookOptions = {},\n): OrderBookInstance => {\n let options = initial;\n const store = createOrderBookStore();\n const emitter = createEmitter<OrderBookEventMap>();\n let fmt: Formatters = createFormatters(options, 2, 4);\n let finePrice = fmt.price;\n /** Texts in the locale, resolved on every option update */\n let texts = localeLabels(LABELS, options.locale, options.labels);\n let inferred = false;\n let colors = { up: [0, 0, 0, 1] as Rgba, down: [0, 0, 0, 1] as Rgba };\n let lastPrice: number | null = null;\n let previousLast = NaN;\n let lastDirection = 0;\n let flashes = new Map<string, Flash>();\n /** Price range of the rows of the previous frame, per side */\n const shownRange: Record<OrderBookSide, [number, number]> = {\n bid: [NaN, NaN],\n ask: [NaN, NaN],\n };\n let drawn = false;\n let rows: Row[] = [];\n let hoverAt: [number, number] | null = null;\n /** Keyboard selection: side and index from the spread */\n let keyRow: { side: OrderBookSide; index: number } | null = null;\n let hoverKey = \"\";\n let hovered: Row | null = null;\n let rowHeight = 20;\n\n const host = createHost(container, {\n className: \"minerva-order-book\",\n draw,\n onTheme: () => {\n colors = sideColors(host.theme, options);\n },\n });\n const { root, doc } = host;\n root.tabIndex = 0;\n root.setAttribute(\"role\", \"figure\");\n root.style.cursor = \"default\";\n\n const labels = () => texts;\n\n const refreshFormat = () => {\n const grouping = options.grouping ?? 0;\n const raw = inferPriceDecimals(store);\n fmt = createFormatters(\n options,\n grouping > 0 ? Math.max(decimalsOf(grouping), 0) : raw,\n inferSizeDecimals(store),\n );\n // the spread row keeps the raw tick precision (a 0.1 spread is not \"0\")\n const fine = numberFormat(\n options.locale,\n Math.max(fmt.priceDecimals, options.grouping ? raw : 0),\n );\n finePrice = options.formatPrice\n ? fmt.price\n : (v) => (Number.isFinite(v) ? fine.format(v) : \"–\");\n };\n\n const applyTexts = () => {\n texts = localeLabels(LABELS, options.locale, options.labels);\n root.setAttribute(\"aria-label\", options.ariaLabel ?? texts.name);\n };\n\n const applyOptions = () => {\n applyTexts();\n colors = sideColors(host.theme, options);\n refreshFormat();\n // grouping changes the rows: no flash for the new buckets\n flashes = new Map();\n drawn = false;\n host.invalidate();\n };\n\n /** Levels of a side with their cumulative values */\n const sideRows = (side: OrderBookSide, limit: number): Row[] => {\n const { price, size, count } = store.levels(side, {\n step: options.grouping ?? 0,\n limit,\n });\n const out: Row[] = [];\n let sum = 0;\n let notional = 0;\n for (let i = 0; i < count; i++) {\n const p = price[i]!;\n const s = size[i]!;\n sum += s;\n notional += s * p;\n out.push({\n side,\n index: i,\n price: p,\n size: s,\n sum,\n notional,\n average: notional / sum,\n y: 0,\n });\n }\n return out;\n };\n\n function draw(now: number): boolean {\n const ctx = host.ctx;\n if (!ctx) return false;\n const { width, height, dpr, theme } = host;\n const l = labels();\n const mode = options.mode ?? \"both\";\n const compact = width < 260;\n const fontSize = options.fontSize ?? (compact ? 11 : 12);\n const rh = (rowHeight = Math.max(\n 12,\n options.rowHeight ?? (compact ? 18 : 20),\n ));\n const headerH = options.header === false ? 0 : rh + 2;\n const spreadH = options.spreadRow === false ? 0 : Math.round(rh * 1.7);\n const imbalanceH = options.imbalance === false ? 0 : 24;\n const sides = mode === \"both\" ? 2 : 1;\n const avail = Math.max(0, height - headerH - spreadH - imbalanceH);\n const perSide = Math.max(0, options.rows ?? Math.floor(avail / rh / sides));\n const pad = compact ? 6 : 10;\n\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n ctx.clearRect(0, 0, width, height);\n\n const asks = mode === \"bids\" ? [] : sideRows(\"ask\", perSide);\n const bids = mode === \"asks\" ? [] : sideRows(\"bid\", perSide);\n\n // vertical layout\n let y = headerH;\n const asksTop = y;\n if (mode !== \"bids\") {\n for (const row of asks) row.y = asksTop + (perSide - 1 - row.index) * rh;\n y += perSide * rh;\n }\n const spreadY = mode === \"bids\" ? headerH : y;\n if (mode !== \"bids\") y += spreadH;\n else y = headerH + spreadH;\n const bidsTop = y;\n for (const row of bids) row.y = bidsTop + row.index * rh;\n rows = [...asks, ...bids];\n const spreadTop = mode === \"asks\" ? asksTop + perSide * rh : spreadY;\n\n // columns\n const cols = (options.columns ?? COLUMNS).filter(\n (c, i, all) => all.indexOf(c) === i,\n );\n const shownCols = compact && cols.length > 2 ? cols.slice(0, 2) : cols;\n const n = shownCols.length;\n const inner = width - pad * 2;\n const colX = shownCols.map((_, j) =>\n j === 0\n ? pad\n : pad + inner * (j === n - 1 ? 1 : 0.24 + (0.76 * j) / (n - 1)),\n );\n\n // depth bar scale\n const barsMode = options.depthBars ?? \"cumulative\";\n let barMax = 0;\n for (const row of rows) {\n barMax = Math.max(barMax, barsMode === \"level\" ? row.size : row.sum);\n }\n\n // flashes: compare with the sizes of the previous frame\n const flash = options.flash !== false;\n const duration = Math.max(1, options.flashDuration ?? 450);\n const nextFlashes = new Map<string, Flash>();\n let animating = false;\n const inside = (row: Row) => {\n const range = shownRange[row.side];\n return drawn && row.price > range[0] && row.price < range[1];\n };\n for (const row of rows) {\n const key = `${row.side}:${row.price}`;\n const previous = flashes.get(key);\n let entry: Flash;\n // a level scrolling into view is not new: only levels appearing\n // between the rows already shown flash\n if (!previous)\n entry = {\n size: row.size,\n at: inside(row) ? now : -Infinity,\n grew: true,\n };\n else if (previous.size !== row.size)\n entry = { size: row.size, at: now, grew: row.size > previous.size };\n else entry = previous;\n nextFlashes.set(key, entry);\n }\n flashes = nextFlashes;\n drawn = true;\n for (const side of [\"bid\", \"ask\"] as const) {\n const list = side === \"bid\" ? bids : asks;\n const prices = list.map((r) => r.price);\n shownRange[side] = prices.length\n ? [Math.min(...prices), Math.max(...prices)]\n : [NaN, NaN];\n }\n\n // hover: rows from the spread to the hovered one\n hovered = null;\n if (hoverAt) {\n const [hx, hy] = hoverAt;\n if (hx >= 0 && hx <= width)\n hovered = rows.find((r) => hy >= r.y && hy < r.y + rh) ?? null;\n } else if (keyRow) {\n const list = keyRow.side === \"ask\" ? asks : bids;\n hovered = list[Math.min(keyRow.index, list.length - 1)] ?? null;\n }\n\n const threshold = options.largeOrderThreshold ?? Infinity;\n const text = toCss(theme.text);\n const muted = toCss(theme.textMuted);\n\n // header\n if (headerH) {\n ctx.font = fontOf(theme, options, 400, fontSize - 1);\n ctx.fillStyle = muted;\n ctx.textBaseline = \"middle\";\n shownCols.forEach((c, j) => {\n ctx.textAlign = j === 0 ? \"left\" : \"right\";\n ctx.fillText(l[c], colX[j]!, rh / 2 + 1);\n });\n }\n\n // rows\n for (const row of rows) {\n const color = row.side === \"bid\" ? colors.up : colors.down;\n const key = `${row.side}:${row.price}`;\n const large = row.size >= threshold;\n // hover band (cumulative selection)\n if (hovered && hovered.side === row.side && row.index <= hovered.index) {\n ctx.fillStyle = toCss(theme.text, row === hovered ? 0.09 : 0.045);\n ctx.fillRect(0, row.y, width, rh);\n }\n // depth bar\n if (barsMode !== \"none\" && barMax > 0) {\n const value = barsMode === \"level\" ? row.size : row.sum;\n const w = (value / barMax) * width;\n ctx.fillStyle = toCss(color, 0.14);\n ctx.fillRect(width - w, row.y + 1, w, rh - 2);\n }\n if (large) {\n ctx.fillStyle = toCss(color, 0.16);\n ctx.fillRect(0, row.y + 1, width, rh - 2);\n // a small dot in the left padding marks the large level (no accent bar)\n ctx.fillStyle = toCss(color);\n ctx.beginPath();\n ctx.arc(\n pad / 2,\n row.y + rh / 2,\n Math.min(2.5, pad / 2 - 1),\n 0,\n Math.PI * 2,\n );\n ctx.fill();\n }\n // flash: behind the size that changed (a whole-row flash makes a\n // ladder at 200 updates/s flicker)\n const f = flashes.get(key);\n let flashAlpha = 0;\n if (flash && f && Number.isFinite(f.at)) {\n const age = (now - f.at) / duration;\n if (age < 1) {\n flashAlpha = (1 - age) * (1 - age);\n animating = true;\n }\n }\n // texts\n ctx.textBaseline = \"middle\";\n const ty = row.y + rh / 2 + 0.5;\n shownCols.forEach((c, j) => {\n ctx.textAlign = j === 0 ? \"left\" : \"right\";\n if (c === \"price\") {\n ctx.font = fontOf(theme, options, 500, fontSize);\n ctx.fillStyle = toCss(color);\n ctx.fillText(\n fmt.price(row.price),\n colX[j]! + (large && j === 0 ? 4 : 0),\n ty,\n );\n } else if (c === \"size\") {\n ctx.font = fontOf(theme, options, large ? 700 : 400, fontSize);\n const label = fmt.size(row.size);\n if (flashAlpha > 0 && f) {\n const w = ctx.measureText(label).width + 10;\n const x = j === 0 ? colX[j]! - 5 : colX[j]! - w + 5;\n ctx.fillStyle = toCss(\n f.grew ? color : theme.textMuted,\n (f.grew ? 0.45 : 0.3) * flashAlpha,\n );\n roundRect(ctx, x, row.y + 2, w, rh - 4, 3);\n ctx.fill();\n }\n ctx.fillStyle = text;\n ctx.fillText(label, colX[j]!, ty);\n } else {\n ctx.font = fontOf(theme, options, 400, fontSize);\n ctx.fillStyle = muted;\n ctx.fillText(\n options.total === \"quote\"\n ? fmt.notional(row.notional)\n : fmt.total(row.sum),\n colX[j]!,\n ty,\n );\n }\n });\n }\n if (hovered) {\n // edge of the selection\n ctx.strokeStyle = toCss(theme.textMuted, 0.7);\n ctx.setLineDash([3, 3]);\n ctx.beginPath();\n const edge =\n hovered.side === \"bid\" ? hovered.y + rh - 0.5 : hovered.y + 0.5;\n ctx.moveTo(0, edge);\n ctx.lineTo(width, edge);\n ctx.stroke();\n ctx.setLineDash([]);\n }\n\n // spread row\n if (spreadH) {\n const mid = store.mid();\n const shown = lastPrice ?? mid;\n if (Number.isFinite(shown) && shown !== previousLast) {\n if (Number.isFinite(previousLast))\n lastDirection =\n shown > previousLast\n ? 1\n : shown < previousLast\n ? -1\n : lastDirection;\n previousLast = shown;\n }\n const sy = spreadTop;\n ctx.fillStyle = toCss(theme.text, 0.035);\n ctx.fillRect(0, sy, width, spreadH);\n ctx.strokeStyle = toCss(theme.grid);\n ctx.beginPath();\n ctx.moveTo(0, Math.round(sy) + 0.5);\n ctx.lineTo(width, Math.round(sy) + 0.5);\n ctx.moveTo(0, Math.round(sy + spreadH) - 0.5);\n ctx.lineTo(width, Math.round(sy + spreadH) - 0.5);\n ctx.stroke();\n const dirColor =\n lastDirection > 0\n ? colors.up\n : lastDirection < 0\n ? colors.down\n : theme.text;\n const cy = sy + spreadH / 2 + 0.5;\n ctx.textBaseline = \"middle\";\n ctx.textAlign = \"left\";\n ctx.font = fontOf(theme, options, 700, fontSize + (compact ? 2 : 4));\n ctx.fillStyle = toCss(dirColor);\n const priceText = finePrice(shown);\n ctx.fillText(priceText, pad, cy);\n let x = pad + ctx.measureText(priceText).width + 6;\n if (lastDirection !== 0) {\n // arrow of the last move\n const s = compact ? 4 : 5;\n ctx.beginPath();\n if (lastDirection > 0) {\n ctx.moveTo(x, cy + s * 0.6);\n ctx.lineTo(x + s, cy - s * 0.7);\n ctx.lineTo(x + s * 2, cy + s * 0.6);\n } else {\n ctx.moveTo(x, cy - s * 0.6);\n ctx.lineTo(x + s, cy + s * 0.7);\n ctx.lineTo(x + s * 2, cy - s * 0.6);\n }\n ctx.closePath();\n ctx.fill();\n x += s * 2 + 6;\n }\n const spread = store.spread();\n if (Number.isFinite(spread)) {\n ctx.textAlign = \"right\";\n ctx.font = fontOf(theme, options, 400, fontSize - 1);\n const bps = (spread / mid) * 1e4;\n const right = `${finePrice(spread)} · ${fmt.fixed(bps, bps < 10 ? 2 : 1)} ${l.basisPoints}`;\n ctx.fillStyle = text;\n ctx.fillText(right, width - pad, cy);\n if (!compact) {\n const rw = ctx.measureText(right).width;\n ctx.fillStyle = muted;\n const label = `${l.spread}`;\n if (width - pad - rw - 8 - ctx.measureText(label).width > x)\n ctx.fillText(label, width - pad - rw - 8, cy);\n }\n }\n }\n\n // imbalance bar\n if (imbalanceH) {\n let bidSum = 0;\n let askSum = 0;\n for (const r of bids) bidSum += r.size;\n for (const r of asks) askSum += r.size;\n const all = bidSum + askSum;\n const share = all > 0 ? bidSum / all : 0.5;\n const by = height - imbalanceH + 6;\n const bh = imbalanceH - 10;\n const bw = width - pad * 2;\n const split = pad + bw * share;\n ctx.save();\n roundRect(ctx, pad, by, bw, bh, 3);\n ctx.clip();\n ctx.fillStyle = toCss(colors.up, 0.22);\n ctx.fillRect(pad, by, split - pad, bh);\n ctx.fillStyle = toCss(colors.down, 0.22);\n ctx.fillRect(split, by, pad + bw - split, bh);\n ctx.restore();\n ctx.fillStyle = toCss(theme.background);\n ctx.fillRect(split - 1, by, 2, bh);\n ctx.font = fontOf(theme, options, 600, fontSize - 1);\n ctx.textBaseline = \"middle\";\n ctx.textAlign = \"left\";\n ctx.fillStyle = toCss(colors.up);\n const mid = by + bh / 2 + 0.5;\n ctx.fillText(\n `${l.buyShare} ${fmt.percent(share, 1, false)}`,\n pad + 6,\n mid,\n );\n ctx.textAlign = \"right\";\n ctx.fillStyle = toCss(colors.down);\n ctx.fillText(\n `${fmt.percent(1 - share, 1, false)} ${l.sellShare}`,\n pad + bw - 6,\n mid,\n );\n }\n\n // tooltip and hover event\n if (hovered && options.tooltip !== false) {\n const color = hovered.side === \"bid\" ? colors.up : colors.down;\n tooltipHtml(\n doc,\n host.tooltip,\n { text: fmt.price(hovered.price), color: toCss(color) },\n [\n [l.average, finePrice(hovered.average)],\n [l.sum, fmt.total(hovered.sum)],\n [l.notional, fmt.notional(hovered.notional)],\n ],\n );\n host.tooltip.style.display = \"block\";\n const ax = hoverAt ? hoverAt[0] : width * 0.4;\n host.placeTooltip(\n host.tooltip,\n ax,\n hovered.y + rh / 2,\n ax > width / 2 ? \"left\" : \"right\",\n );\n } else {\n host.tooltip.style.display = \"none\";\n }\n const key = hovered\n ? `${hovered.side}|${hovered.index}|${hovered.price}|${hovered.size}|${hovered.sum}`\n : \"\";\n if (key !== hoverKey) {\n hoverKey = key;\n emitter.emit(\"hover\", hovered ? toEvent(hovered) : null);\n }\n\n const bb = store.bestBid();\n const ba = store.bestAsk();\n host.describe(\n `${options.ariaLabel ?? l.name}. ${l.bid} ${finePrice(bb)}, ${l.ask} ${finePrice(ba)}, ${l.spread} ${finePrice(ba - bb)}.`,\n );\n return animating;\n }\n\n const toEvent = (row: Row): OrderBookLevelEvent => ({\n side: row.side,\n index: row.index,\n price: row.price,\n size: row.size,\n sum: row.sum,\n notional: row.notional,\n average: row.average,\n });\n\n // ---------------------------------------------------------- interaction\n\n const onPointerMove = (event: PointerEvent) => {\n hoverAt = localPoint(root, event);\n keyRow = null;\n host.invalidate();\n };\n const onPointerLeave = () => {\n hoverAt = null;\n host.invalidate();\n };\n const onClick = (event: MouseEvent) => {\n const [x, y] = localPoint(root, event);\n const row = rows.find((r) => y >= r.y && y < r.y + rowHeight);\n if (row && x >= 0) emitter.emit(\"levelClick\", toEvent(row));\n };\n const onKeyDown = (event: KeyboardEvent) => {\n const order: { side: OrderBookSide; index: number }[] = [];\n const asks = rows.filter((r) => r.side === \"ask\");\n const bids = rows.filter((r) => r.side === \"bid\");\n for (let i = asks.length - 1; i >= 0; i--)\n order.push({ side: \"ask\", index: i });\n for (let i = 0; i < bids.length; i++) order.push({ side: \"bid\", index: i });\n if (!order.length) return;\n const current = keyRow\n ? order.findIndex(\n (o) => o.side === keyRow!.side && o.index === keyRow!.index,\n )\n : -1;\n switch (event.key) {\n case \"ArrowDown\":\n case \"ArrowUp\": {\n const down = event.key === \"ArrowDown\";\n // first press: the best level on that side of the spread\n const next =\n current >= 0\n ? clamp(current + (down ? 1 : -1), 0, order.length - 1)\n : down\n ? Math.min(asks.length, order.length - 1)\n : Math.max(0, asks.length - 1);\n keyRow = order[next] ?? null;\n hoverAt = null;\n host.invalidate();\n break;\n }\n case \"Enter\":\n case \" \":\n if (hovered) emitter.emit(\"levelClick\", toEvent(hovered));\n break;\n case \"Escape\":\n keyRow = null;\n host.invalidate();\n break;\n default:\n return;\n }\n event.preventDefault();\n };\n const onBlur = () => {\n if (keyRow) {\n keyRow = null;\n host.invalidate();\n }\n };\n root.addEventListener(\"pointermove\", onPointerMove);\n root.addEventListener(\"pointerleave\", onPointerLeave);\n root.addEventListener(\"click\", onClick);\n root.addEventListener(\"keydown\", onKeyDown);\n root.addEventListener(\"blur\", onBlur);\n\n const changed = () => {\n if (!inferred && store.count(\"bid\") + store.count(\"ask\") > 0) {\n inferred = true;\n refreshFormat();\n }\n host.invalidate();\n };\n\n const instance: OrderBookInstance = {\n setBook(snapshot) {\n store.setSnapshot(snapshot);\n inferred = false;\n changed();\n },\n applyDeltas(deltas) {\n if (applyDeltas(store, deltas)) changed();\n },\n clear() {\n store.clear();\n inferred = false;\n flashes = new Map();\n drawn = false;\n host.invalidate();\n },\n setLastPrice(price) {\n lastPrice = price !== null && Number.isFinite(price) ? price : null;\n host.invalidate();\n },\n setOptions(next) {\n const regroup =\n (next.grouping ?? 0) !== (options.grouping ?? 0) ||\n next.mode !== options.mode;\n options = next;\n if (regroup) applyOptions();\n else {\n applyTexts();\n colors = sideColors(host.theme, options);\n refreshFormat();\n host.invalidate();\n }\n },\n getStore: () => store,\n on: (event, handler) => emitter.on(event, handler),\n resize() {\n host.invalidate();\n },\n destroy() {\n root.removeEventListener(\"pointermove\", onPointerMove);\n root.removeEventListener(\"pointerleave\", onPointerLeave);\n root.removeEventListener(\"click\", onClick);\n root.removeEventListener(\"keydown\", onKeyDown);\n root.removeEventListener(\"blur\", onBlur);\n emitter.clear();\n host.destroy();\n },\n };\n applyOptions();\n return instance;\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- var e=(e,t,n,r,i,a=2)=>{let[o,s]=i,c=e.map((e,t)=>({label:e,i:t})).filter(({label:e})=>Number.isFinite(e.y)).sort((e,t)=>e.label.y-t.label.y||e.i-t.i),l=t=>{let n=0;t.items.forEach((r,i)=>{n+=e[r].y-t.offsets[i]});let r=n/t.items.length;t.top=Math.max(o,Math.min(r,s-t.height))},u=[];for(let{label:e,i:t}of c){let n={items:[t],offsets:[e.h/2],height:e.h,top:e.y-e.h/2};for(l(n),u.push(n);u.length>1;){let e=u[u.length-1],t=u[u.length-2];if(t.top+t.height+a<=e.top)break;let n=t.height+a;t.items.push(...e.items),t.offsets.push(...e.offsets.map(e=>e+n)),t.height+=a+e.height,u.pop(),l(t)}}let d=e.map(()=>null);for(let e of u)e.items.forEach((t,n)=>{d[t]=e.top+e.offsets[n]});let f=(e,t,n,r)=>Math.abs(e-n)<(t+r)/2+a;t&&d.forEach((n,r)=>{n!==null&&f(n,e[r].h,t.y,t.h)&&(d[r]=null)});let p=[];return d.forEach((t,n)=>{t!==null&&p.push({y:t,h:e[n].h})}),t&&p.push(t),{pinned:d,ticks:n.map(e=>e-r/2>=o&&e+r/2<=s&&!p.some(t=>f(e,r,t.y,t.h)))}},t=(e,t,n,r,i)=>{if(!Number.isFinite(t)||!Number.isFinite(n))return e?[e[0],e[1]]:[NaN,NaN];let a=i!==void 0&&i>0?i:Math.max(r,(n-t)*1.6);if(e&&Number.isFinite(e[0])&&Number.isFinite(e[1])){let r=e[1]-e[0],o=r*.12,s=t>=e[0]+o&&n<=e[1]-o,c=i!==void 0&&i>0?Math.abs(r/i-1)<1e-6:r<=a*1.8;if(s&&c)return[e[0],e[1]]}let o=(t+n)/2;return[o-a/2,o+a/2]},n=(e,t,n,r)=>[t-(Number.isFinite(e)?Math.max(Math.min(r,n),Math.min(n,t-e)):n),t],r=e=>{if(!(e>0)||!Number.isFinite(e))return 0;let t=10**Math.floor(Math.log10(e));for(let n of[1,2,2.5,5,10])if(n*t>=e*(1-1e-9))return n*t;return 10*t};exports.fitPriceRange=t,exports.fitTimeRange=n,exports.layoutAxisLabels=e,exports.niceCeil=r;
1
+ var e=(e,t,n,r,i,a=2)=>{let[o,s]=i,c=e.map((e,t)=>({label:e,i:t})).filter(({label:e})=>Number.isFinite(e.y)).sort((e,t)=>e.label.y-t.label.y||e.i-t.i),l=t=>{let n=0;t.items.forEach((r,i)=>{n+=e[r].y-t.offsets[i]});let r=n/t.items.length;t.top=Math.max(o,Math.min(r,s-t.height))},u=[];for(let{label:e,i:t}of c){let n={items:[t],offsets:[e.h/2],height:e.h,top:e.y-e.h/2};for(l(n),u.push(n);u.length>1;){let e=u[u.length-1],t=u[u.length-2];if(t.top+t.height+a<=e.top)break;let n=t.height+a;t.items.push(...e.items),t.offsets.push(...e.offsets.map(e=>e+n)),t.height+=a+e.height,u.pop(),l(t)}}let d=e.map(()=>null);for(let e of u)e.items.forEach((t,n)=>{d[t]=e.top+e.offsets[n]});let f=(e,t,n,r)=>Math.abs(e-n)<(t+r)/2+a;t&&d.forEach((n,r)=>{n!==null&&f(n,e[r].h,t.y,t.h)&&(d[r]=null)});let p=[];return d.forEach((t,n)=>{t!==null&&p.push({y:t,h:e[n].h})}),t&&p.push(t),{pinned:d,ticks:n.map(e=>e-r/2>=o&&e+r/2<=s&&!p.some(t=>f(e,r,t.y,t.h)))}},t=(e,t,n,r,i)=>{if(!Number.isFinite(t)||!Number.isFinite(n))return e?[e[0],e[1]]:[NaN,NaN];let a=i!==void 0&&i>0?i:Math.max(r,(n-t)*1.6);if(e&&Number.isFinite(e[0])&&Number.isFinite(e[1])){let r=e[1]-e[0],o=r*.12,s=t>=e[0]+o&&n<=e[1]-o,c=i!==void 0&&i>0?Math.abs(r/i-1)<1e-6:r<=a*1.8;if(s&&c)return[e[0],e[1]]}let o=(t+n)/2;return[o-a/2,o+a/2]},n=(e,t,n,r)=>[t-(Number.isFinite(e)?Math.max(Math.min(r,n),Math.min(n,t-e)):n),t],r=e=>{if(!(e>0)||!Number.isFinite(e))return 0;let t=10**Math.floor(Math.log10(e));for(let n of[1,1.2,1.5,2,2.5,3,4,5,6,8,10])if(n*t>=e*(1-1e-9))return+(n*t).toPrecision(12);return 10*t};exports.fineCeil=r,exports.fitPriceRange=t,exports.fitTimeRange=n,exports.layoutAxisLabels=e;
2
2
  //# sourceMappingURL=layout.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"layout.cjs","names":["layoutAxisLabels","top","bottom","bounds","order","pinned","label","a","b","place","sum","block","item","k","ideal","blocks","i","last","previous","gap","shift","o","centers","overlaps","ah","bh","hover","y","shown","ticks","tickHeight","fitPriceRange","lo","hi","current","want","fixedSpan","minSpan","span","margin","inside","sized","center","fitTimeRange","right","first","window","niceCeil","value","power","m"],"sources":["../../../../../charts/src/engine/orderbook/layout.ts"],"sourcesContent":["// Pure layout helpers of the order book widgets: price-axis label collision\n// resolution and the view fitting of the liquidity heatmap.\n\n/** A label on a vertical axis: center and height, in pixels */\nexport interface AxisLabel {\n y: number;\n h: number;\n}\n\n/** Result of `layoutAxisLabels` */\nexport interface AxisLabelLayout {\n /** Centers of the pinned labels (moved apart), `null` when hidden by the hover label */\n pinned: (number | null)[];\n /** Whether each tick label stays visible */\n ticks: boolean[];\n}\n\n/**\n * Resolves the collisions of the labels of a price axis. Priority: the\n * hover label stays where it is and hides the pinned labels it covers;\n * pinned labels (best bid / ask, last trade) never overlap each other: a\n * group of overlapping ones is stacked, in order, around their desired\n * positions and kept within `bounds`; tick labels under any of them are\n * hidden.\n */\nexport const layoutAxisLabels = (\n pinned: readonly AxisLabel[],\n hover: AxisLabel | null,\n ticks: readonly number[],\n tickHeight: number,\n bounds: readonly [number, number],\n gap = 2,\n): AxisLabelLayout => {\n const [top, bottom] = bounds;\n // blocks of stacked labels, top to bottom\n interface Block {\n items: number[];\n /** Offset of each item's center from the block's top */\n offsets: number[];\n height: number;\n top: number;\n }\n const order = pinned\n .map((label, i) => ({ label, i }))\n .filter(({ label }) => Number.isFinite(label.y))\n .sort((a, b) => a.label.y - b.label.y || a.i - b.i);\n const place = (block: Block) => {\n let sum = 0;\n block.items.forEach((item, k) => {\n sum += pinned[item]!.y - block.offsets[k]!;\n });\n const ideal = sum / block.items.length;\n block.top = Math.max(top, Math.min(ideal, bottom - block.height));\n };\n const blocks: Block[] = [];\n for (const { label, i } of order) {\n const block: Block = {\n items: [i],\n offsets: [label.h / 2],\n height: label.h,\n top: label.y - label.h / 2,\n };\n place(block);\n blocks.push(block);\n // merge with the blocks above while they overlap\n while (blocks.length > 1) {\n const last = blocks[blocks.length - 1]!;\n const previous = blocks[blocks.length - 2]!;\n if (previous.top + previous.height + gap <= last.top) break;\n const shift = previous.height + gap;\n previous.items.push(...last.items);\n previous.offsets.push(...last.offsets.map((o) => o + shift));\n previous.height += gap + last.height;\n blocks.pop();\n place(previous);\n }\n }\n const centers: (number | null)[] = pinned.map(() => null);\n for (const block of blocks) {\n block.items.forEach((item, k) => {\n centers[item] = block.top + block.offsets[k]!;\n });\n }\n const overlaps = (a: number, ah: number, b: number, bh: number) =>\n Math.abs(a - b) < (ah + bh) / 2 + gap;\n if (hover) {\n centers.forEach((y, i) => {\n if (y !== null && overlaps(y, pinned[i]!.h, hover.y, hover.h))\n centers[i] = null;\n });\n }\n const shown: AxisLabel[] = [];\n centers.forEach((y, i) => {\n if (y !== null) shown.push({ y, h: pinned[i]!.h });\n });\n if (hover) shown.push(hover);\n return {\n pinned: centers,\n ticks: ticks.map(\n (y) =>\n y - tickHeight / 2 >= top &&\n y + tickHeight / 2 <= bottom &&\n !shown.some((label) => overlaps(y, tickHeight, label.y, label.h)),\n ),\n };\n};\n\n/**\n * Price range of a following heatmap view, with hysteresis: the current\n * range is kept while the traded prices (`lo` – `hi`, best bid / ask of the\n * window) stay inside its inner part and it is not much too wide; otherwise\n * a range centered on them, `minSpan` or 1.6 × their spread high. With\n * `fixedSpan` (the user zoomed the prices) only the center moves.\n */\nexport const fitPriceRange = (\n current: readonly [number, number] | null,\n lo: number,\n hi: number,\n minSpan: number,\n fixedSpan?: number,\n): [number, number] => {\n if (!Number.isFinite(lo) || !Number.isFinite(hi)) {\n return current ? [current[0], current[1]] : [NaN, NaN];\n }\n const want =\n fixedSpan !== undefined && fixedSpan > 0\n ? fixedSpan\n : Math.max(minSpan, (hi - lo) * 1.6);\n if (current && Number.isFinite(current[0]) && Number.isFinite(current[1])) {\n const span = current[1] - current[0];\n const margin = span * 0.12;\n const inside = lo >= current[0] + margin && hi <= current[1] - margin;\n const sized =\n fixedSpan !== undefined && fixedSpan > 0\n ? Math.abs(span / fixedSpan - 1) < 1e-6\n : span <= want * 1.8;\n if (inside && sized) return [current[0], current[1]];\n }\n const center = (lo + hi) / 2;\n return [center - want / 2, center + want / 2];\n};\n\n/**\n * Time range of a following heatmap view ending at `right`: `window` wide\n * once the data covers it; before that, the span of the data (at least\n * `minSpan`), so a short history fills the plot from the left.\n */\nexport const fitTimeRange = (\n first: number,\n right: number,\n window: number,\n minSpan: number,\n): [number, number] => {\n const span = Number.isFinite(first)\n ? Math.max(Math.min(minSpan, window), Math.min(window, right - first))\n : window;\n return [right - span, right];\n};\n\n/** Smallest \"nice\" number (1, 2, 2.5, 5 × 10ⁿ) at least `value` */\nexport const niceCeil = (value: number): number => {\n if (!(value > 0) || !Number.isFinite(value)) return 0;\n const power = 10 ** Math.floor(Math.log10(value));\n for (const m of [1, 2, 2.5, 5, 10]) {\n if (m * power >= value * (1 - 1e-9)) return m * power;\n }\n return 10 * power;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"layout.cjs","names":["layoutAxisLabels","top","bottom","bounds","order","pinned","label","a","b","place","sum","block","item","k","ideal","blocks","i","last","previous","gap","shift","o","centers","overlaps","ah","bh","hover","y","shown","ticks","tickHeight","fitPriceRange","lo","hi","current","want","fixedSpan","minSpan","span","margin","inside","sized","center","fitTimeRange","right","first","window","fineCeil","value","power","m"],"sources":["../../../../../charts/src/engine/orderbook/layout.ts"],"sourcesContent":["// Pure layout helpers of the order book widgets: price-axis label collision\n// resolution and the view fitting of the liquidity heatmap.\n\n/** A label on a vertical axis: center and height, in pixels */\nexport interface AxisLabel {\n y: number;\n h: number;\n}\n\n/** Result of `layoutAxisLabels` */\nexport interface AxisLabelLayout {\n /** Centers of the pinned labels (moved apart), `null` when hidden by the hover label */\n pinned: (number | null)[];\n /** Whether each tick label stays visible */\n ticks: boolean[];\n}\n\n/**\n * Resolves the collisions of the labels of a price axis. Priority: the\n * hover label stays where it is and hides the pinned labels it covers;\n * pinned labels (best bid / ask, last trade) never overlap each other: a\n * group of overlapping ones is stacked, in order, around their desired\n * positions and kept within `bounds`; tick labels under any of them are\n * hidden.\n */\nexport const layoutAxisLabels = (\n pinned: readonly AxisLabel[],\n hover: AxisLabel | null,\n ticks: readonly number[],\n tickHeight: number,\n bounds: readonly [number, number],\n gap = 2,\n): AxisLabelLayout => {\n const [top, bottom] = bounds;\n // blocks of stacked labels, top to bottom\n interface Block {\n items: number[];\n /** Offset of each item's center from the block's top */\n offsets: number[];\n height: number;\n top: number;\n }\n const order = pinned\n .map((label, i) => ({ label, i }))\n .filter(({ label }) => Number.isFinite(label.y))\n .sort((a, b) => a.label.y - b.label.y || a.i - b.i);\n const place = (block: Block) => {\n let sum = 0;\n block.items.forEach((item, k) => {\n sum += pinned[item]!.y - block.offsets[k]!;\n });\n const ideal = sum / block.items.length;\n block.top = Math.max(top, Math.min(ideal, bottom - block.height));\n };\n const blocks: Block[] = [];\n for (const { label, i } of order) {\n const block: Block = {\n items: [i],\n offsets: [label.h / 2],\n height: label.h,\n top: label.y - label.h / 2,\n };\n place(block);\n blocks.push(block);\n // merge with the blocks above while they overlap\n while (blocks.length > 1) {\n const last = blocks[blocks.length - 1]!;\n const previous = blocks[blocks.length - 2]!;\n if (previous.top + previous.height + gap <= last.top) break;\n const shift = previous.height + gap;\n previous.items.push(...last.items);\n previous.offsets.push(...last.offsets.map((o) => o + shift));\n previous.height += gap + last.height;\n blocks.pop();\n place(previous);\n }\n }\n const centers: (number | null)[] = pinned.map(() => null);\n for (const block of blocks) {\n block.items.forEach((item, k) => {\n centers[item] = block.top + block.offsets[k]!;\n });\n }\n const overlaps = (a: number, ah: number, b: number, bh: number) =>\n Math.abs(a - b) < (ah + bh) / 2 + gap;\n if (hover) {\n centers.forEach((y, i) => {\n if (y !== null && overlaps(y, pinned[i]!.h, hover.y, hover.h))\n centers[i] = null;\n });\n }\n const shown: AxisLabel[] = [];\n centers.forEach((y, i) => {\n if (y !== null) shown.push({ y, h: pinned[i]!.h });\n });\n if (hover) shown.push(hover);\n return {\n pinned: centers,\n ticks: ticks.map(\n (y) =>\n y - tickHeight / 2 >= top &&\n y + tickHeight / 2 <= bottom &&\n !shown.some((label) => overlaps(y, tickHeight, label.y, label.h)),\n ),\n };\n};\n\n/**\n * Price range of a following heatmap view, with hysteresis: the current\n * range is kept while the traded prices (`lo` – `hi`, best bid / ask of the\n * window) stay inside its inner part and it is not much too wide; otherwise\n * a range centered on them, `minSpan` or 1.6 × their spread high. With\n * `fixedSpan` (the user zoomed the prices) only the center moves.\n */\nexport const fitPriceRange = (\n current: readonly [number, number] | null,\n lo: number,\n hi: number,\n minSpan: number,\n fixedSpan?: number,\n): [number, number] => {\n if (!Number.isFinite(lo) || !Number.isFinite(hi)) {\n return current ? [current[0], current[1]] : [NaN, NaN];\n }\n const want =\n fixedSpan !== undefined && fixedSpan > 0\n ? fixedSpan\n : Math.max(minSpan, (hi - lo) * 1.6);\n if (current && Number.isFinite(current[0]) && Number.isFinite(current[1])) {\n const span = current[1] - current[0];\n const margin = span * 0.12;\n const inside = lo >= current[0] + margin && hi <= current[1] - margin;\n const sized =\n fixedSpan !== undefined && fixedSpan > 0\n ? Math.abs(span / fixedSpan - 1) < 1e-6\n : span <= want * 1.8;\n if (inside && sized) return [current[0], current[1]];\n }\n const center = (lo + hi) / 2;\n return [center - want / 2, center + want / 2];\n};\n\n/**\n * Time range of a following heatmap view ending at `right`: `window` wide\n * once the data covers it; before that, the span of the data (at least\n * `minSpan`), so a short history fills the plot from the left.\n */\nexport const fitTimeRange = (\n first: number,\n right: number,\n window: number,\n minSpan: number,\n): [number, number] => {\n const span = Number.isFinite(first)\n ? Math.max(Math.min(minSpan, window), Math.min(window, right - first))\n : window;\n return [right - span, right];\n};\n\n/** Smallest \"nice\" number (1, 2, 2.5, 5 × 10ⁿ) at least `value` */\nexport const niceCeil = (value: number): number => {\n if (!(value > 0) || !Number.isFinite(value)) return 0;\n const power = 10 ** Math.floor(Math.log10(value));\n for (const m of [1, 2, 2.5, 5, 10]) {\n if (m * power >= value * (1 - 1e-9)) return m * power;\n }\n return 10 * power;\n};\n\n/**\n * Smallest number of a fine \"nice\" series (1, 1.2, 1.5, 2, 2.5, 3, 4, 5,\n * 6, 8 × 10ⁿ) at least `value`: a scale at most a third above the value\n */\nexport const fineCeil = (value: number): number => {\n if (!(value > 0) || !Number.isFinite(value)) return 0;\n const power = 10 ** Math.floor(Math.log10(value));\n for (const m of [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10]) {\n if (m * power >= value * (1 - 1e-9)) return +(m * power).toPrecision(12);\n }\n return 10 * power;\n};\n"],"mappings":"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"}
@@ -35,3 +35,8 @@ export declare const fitPriceRange: (current: readonly [number, number] | null,
35
35
  export declare const fitTimeRange: (first: number, right: number, window: number, minSpan: number) => [number, number];
36
36
  /** Smallest "nice" number (1, 2, 2.5, 5 × 10ⁿ) at least `value` */
37
37
  export declare const niceCeil: (value: number) => number;
38
+ /**
39
+ * Smallest number of a fine "nice" series (1, 1.2, 1.5, 2, 2.5, 3, 4, 5,
40
+ * 6, 8 × 10ⁿ) at least `value`: a scale at most a third above the value
41
+ */
42
+ export declare const fineCeil: (value: number) => number;
@@ -35,3 +35,8 @@ export declare const fitPriceRange: (current: readonly [number, number] | null,
35
35
  export declare const fitTimeRange: (first: number, right: number, window: number, minSpan: number) => [number, number];
36
36
  /** Smallest "nice" number (1, 2, 2.5, 5 × 10ⁿ) at least `value` */
37
37
  export declare const niceCeil: (value: number) => number;
38
+ /**
39
+ * Smallest number of a fine "nice" series (1, 1.2, 1.5, 2, 2.5, 3, 4, 5,
40
+ * 6, 8 × 10ⁿ) at least `value`: a scale at most a third above the value
41
+ */
42
+ export declare const fineCeil: (value: number) => number;
@@ -57,14 +57,20 @@ var e = (e, t, n, r, i, a = 2) => {
57
57
  let t = 10 ** Math.floor(Math.log10(e));
58
58
  for (let n of [
59
59
  1,
60
+ 1.2,
61
+ 1.5,
60
62
  2,
61
63
  2.5,
64
+ 3,
65
+ 4,
62
66
  5,
67
+ 6,
68
+ 8,
63
69
  10
64
- ]) if (n * t >= e * (1 - 1e-9)) return n * t;
70
+ ]) if (n * t >= e * (1 - 1e-9)) return +(n * t).toPrecision(12);
65
71
  return 10 * t;
66
72
  };
67
73
  //#endregion
68
- export { t as fitPriceRange, n as fitTimeRange, e as layoutAxisLabels, r as niceCeil };
74
+ export { r as fineCeil, t as fitPriceRange, n as fitTimeRange, e as layoutAxisLabels };
69
75
 
70
76
  //# sourceMappingURL=layout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"layout.js","names":["layoutAxisLabels","top","bottom","bounds","order","pinned","label","a","b","place","sum","item","block","k","ideal","blocks","i","last","previous","gap","shift","o","centers","overlaps","ah","bh","hover","y","shown","ticks","tickHeight","fitPriceRange","lo","hi","current","want","fixedSpan","minSpan","span","margin","inside","sized","center","fitTimeRange","right","first","window","niceCeil","value","power","m"],"sources":["../../../../../charts/src/engine/orderbook/layout.ts"],"sourcesContent":["// Pure layout helpers of the order book widgets: price-axis label collision\n// resolution and the view fitting of the liquidity heatmap.\n\n/** A label on a vertical axis: center and height, in pixels */\nexport interface AxisLabel {\n y: number;\n h: number;\n}\n\n/** Result of `layoutAxisLabels` */\nexport interface AxisLabelLayout {\n /** Centers of the pinned labels (moved apart), `null` when hidden by the hover label */\n pinned: (number | null)[];\n /** Whether each tick label stays visible */\n ticks: boolean[];\n}\n\n/**\n * Resolves the collisions of the labels of a price axis. Priority: the\n * hover label stays where it is and hides the pinned labels it covers;\n * pinned labels (best bid / ask, last trade) never overlap each other: a\n * group of overlapping ones is stacked, in order, around their desired\n * positions and kept within `bounds`; tick labels under any of them are\n * hidden.\n */\nexport const layoutAxisLabels = (\n pinned: readonly AxisLabel[],\n hover: AxisLabel | null,\n ticks: readonly number[],\n tickHeight: number,\n bounds: readonly [number, number],\n gap = 2,\n): AxisLabelLayout => {\n const [top, bottom] = bounds;\n // blocks of stacked labels, top to bottom\n interface Block {\n items: number[];\n /** Offset of each item's center from the block's top */\n offsets: number[];\n height: number;\n top: number;\n }\n const order = pinned\n .map((label, i) => ({ label, i }))\n .filter(({ label }) => Number.isFinite(label.y))\n .sort((a, b) => a.label.y - b.label.y || a.i - b.i);\n const place = (block: Block) => {\n let sum = 0;\n block.items.forEach((item, k) => {\n sum += pinned[item]!.y - block.offsets[k]!;\n });\n const ideal = sum / block.items.length;\n block.top = Math.max(top, Math.min(ideal, bottom - block.height));\n };\n const blocks: Block[] = [];\n for (const { label, i } of order) {\n const block: Block = {\n items: [i],\n offsets: [label.h / 2],\n height: label.h,\n top: label.y - label.h / 2,\n };\n place(block);\n blocks.push(block);\n // merge with the blocks above while they overlap\n while (blocks.length > 1) {\n const last = blocks[blocks.length - 1]!;\n const previous = blocks[blocks.length - 2]!;\n if (previous.top + previous.height + gap <= last.top) break;\n const shift = previous.height + gap;\n previous.items.push(...last.items);\n previous.offsets.push(...last.offsets.map((o) => o + shift));\n previous.height += gap + last.height;\n blocks.pop();\n place(previous);\n }\n }\n const centers: (number | null)[] = pinned.map(() => null);\n for (const block of blocks) {\n block.items.forEach((item, k) => {\n centers[item] = block.top + block.offsets[k]!;\n });\n }\n const overlaps = (a: number, ah: number, b: number, bh: number) =>\n Math.abs(a - b) < (ah + bh) / 2 + gap;\n if (hover) {\n centers.forEach((y, i) => {\n if (y !== null && overlaps(y, pinned[i]!.h, hover.y, hover.h))\n centers[i] = null;\n });\n }\n const shown: AxisLabel[] = [];\n centers.forEach((y, i) => {\n if (y !== null) shown.push({ y, h: pinned[i]!.h });\n });\n if (hover) shown.push(hover);\n return {\n pinned: centers,\n ticks: ticks.map(\n (y) =>\n y - tickHeight / 2 >= top &&\n y + tickHeight / 2 <= bottom &&\n !shown.some((label) => overlaps(y, tickHeight, label.y, label.h)),\n ),\n };\n};\n\n/**\n * Price range of a following heatmap view, with hysteresis: the current\n * range is kept while the traded prices (`lo` – `hi`, best bid / ask of the\n * window) stay inside its inner part and it is not much too wide; otherwise\n * a range centered on them, `minSpan` or 1.6 × their spread high. With\n * `fixedSpan` (the user zoomed the prices) only the center moves.\n */\nexport const fitPriceRange = (\n current: readonly [number, number] | null,\n lo: number,\n hi: number,\n minSpan: number,\n fixedSpan?: number,\n): [number, number] => {\n if (!Number.isFinite(lo) || !Number.isFinite(hi)) {\n return current ? [current[0], current[1]] : [NaN, NaN];\n }\n const want =\n fixedSpan !== undefined && fixedSpan > 0\n ? fixedSpan\n : Math.max(minSpan, (hi - lo) * 1.6);\n if (current && Number.isFinite(current[0]) && Number.isFinite(current[1])) {\n const span = current[1] - current[0];\n const margin = span * 0.12;\n const inside = lo >= current[0] + margin && hi <= current[1] - margin;\n const sized =\n fixedSpan !== undefined && fixedSpan > 0\n ? Math.abs(span / fixedSpan - 1) < 1e-6\n : span <= want * 1.8;\n if (inside && sized) return [current[0], current[1]];\n }\n const center = (lo + hi) / 2;\n return [center - want / 2, center + want / 2];\n};\n\n/**\n * Time range of a following heatmap view ending at `right`: `window` wide\n * once the data covers it; before that, the span of the data (at least\n * `minSpan`), so a short history fills the plot from the left.\n */\nexport const fitTimeRange = (\n first: number,\n right: number,\n window: number,\n minSpan: number,\n): [number, number] => {\n const span = Number.isFinite(first)\n ? Math.max(Math.min(minSpan, window), Math.min(window, right - first))\n : window;\n return [right - span, right];\n};\n\n/** Smallest \"nice\" number (1, 2, 2.5, 5 × 10ⁿ) at least `value` */\nexport const niceCeil = (value: number): number => {\n if (!(value > 0) || !Number.isFinite(value)) return 0;\n const power = 10 ** Math.floor(Math.log10(value));\n for (const m of [1, 2, 2.5, 5, 10]) {\n if (m * power >= value * (1 - 1e-9)) return m * power;\n }\n return 10 * power;\n};\n"],"mappings":";AAyBA,IAAaA,KACX,GACA,GACA,GACA,GACA,GACA,IAAM,MACc;CACpB,IAAM,CAACC,GAAKC,KAAUC,GAShBC,IAAQC,EACX,KAAK,GAAO,OAAO;EAAE;EAAO;CAAE,EAAE,CAAC,CACjC,QAAQ,EAAE,eAAY,OAAO,SAASC,EAAM,CAAC,CAAC,CAAC,CAC/C,MAAM,GAAG,MAAMC,EAAE,MAAM,IAAIC,EAAE,MAAM,KAAKD,EAAE,IAAIC,EAAE,CAAC,GAC9CC,KAAS,MAAiB;EAC9B,IAAIC,IAAM;EACV,EAAM,MAAM,SAAS,GAAM,MAAM;GAC/B,KAAOL,EAAOM,EAAK,CAAE,IAAIC,EAAM,QAAQC;EACzC,CAAC;EACD,IAAMC,IAAQJ,IAAME,EAAM,MAAM;EAChC,EAAM,MAAM,KAAK,IAAIX,GAAK,KAAK,IAAIa,GAAOZ,IAASU,EAAM,MAAM,CAAC;CAClE,GACMG,IAAkB,CAAC;CACzB,KAAK,IAAM,EAAE,UAAO,UAAOX,GAAO;EAChC,IAAMQ,IAAe;GACnB,OAAO,CAACI,CAAC;GACT,SAAS,CAACV,EAAM,IAAI,CAAC;GACrB,QAAQA,EAAM;GACd,KAAKA,EAAM,IAAIA,EAAM,IAAI;EAC3B;EAIA,KAHAG,EAAMG,CAAK,GACXG,EAAO,KAAKH,CAAK,GAEVG,EAAO,SAAS,IAAG;GACxB,IAAME,IAAOF,EAAOA,EAAO,SAAS,IAC9BG,IAAWH,EAAOA,EAAO,SAAS;GACxC,IAAIG,EAAS,MAAMA,EAAS,SAASC,KAAOF,EAAK,KAAK;GACtD,IAAMG,IAAQF,EAAS,SAASC;GAKhC,AAJAD,EAAS,MAAM,KAAK,GAAGD,EAAK,KAAK,GACjCC,EAAS,QAAQ,KAAK,GAAGD,EAAK,QAAQ,KAAK,MAAMI,IAAID,CAAK,CAAC,GAC3D,EAAS,UAAUD,IAAMF,EAAK,QAC9BF,EAAO,IAAI,GACXN,EAAMS,CAAQ;EAChB;CACF;CACA,IAAMI,IAA6BjB,EAAO,UAAU,IAAI;CACxD,KAAK,IAAMO,KAASG,GAClB,EAAM,MAAM,SAAS,GAAM,MAAM;EAC/B,EAAQJ,KAAQC,EAAM,MAAMA,EAAM,QAAQC;CAC5C,CAAC;CAEH,IAAMU,KAAY,GAAW,GAAY,GAAW,MAClD,KAAK,IAAIhB,IAAIC,CAAC,KAAKgB,IAAKC,KAAM,IAAIN;CACpC,AAAIO,KACFJ,EAAQ,SAAS,GAAG,MAAM;EACxB,AAAIK,MAAM,QAAQJ,EAASI,GAAGtB,EAAOW,EAAE,CAAE,GAAGU,EAAM,GAAGA,EAAM,CAAC,MAC1D,EAAQV,KAAK;CACjB,CAAC;CAEH,IAAMY,IAAqB,CAAC;CAK5B,OAJAN,EAAQ,SAAS,GAAG,MAAM;EACxB,AAAIK,MAAM,QAAMC,EAAM,KAAK;GAAE;GAAG,GAAGvB,EAAOW,EAAE,CAAE;EAAE,CAAC;CACnD,CAAC,GACGU,KAAOE,EAAM,KAAKF,CAAK,GACpB;EACL,QAAQJ;EACR,OAAOO,EAAM,KACV,MACCF,IAAIG,IAAa,KAAK7B,KACtB0B,IAAIG,IAAa,KAAK5B,KACtB,CAAC0B,EAAM,MAAM,MAAUL,EAASI,GAAGG,GAAYxB,EAAM,GAAGA,EAAM,CAAC,CAAC,CACpE;CACF;AACF,GASayB,KACX,GACA,GACA,GACA,GACA,MACqB;CACrB,IAAI,CAAC,OAAO,SAASC,CAAE,KAAK,CAAC,OAAO,SAASC,CAAE,GAC7C,OAAOC,IAAU,CAACA,EAAQ,IAAIA,EAAQ,EAAE,IAAI,CAAC,KAAK,GAAG;CAEvD,IAAMC,IACJC,MAAc,KAAA,KAAaA,IAAY,IACnCA,IACA,KAAK,IAAIC,IAAUJ,IAAKD,KAAM,GAAG;CACvC,IAAIE,KAAW,OAAO,SAASA,EAAQ,EAAE,KAAK,OAAO,SAASA,EAAQ,EAAE,GAAG;EACzE,IAAMI,IAAOJ,EAAQ,KAAKA,EAAQ,IAC5BK,IAASD,IAAO,KAChBE,IAASR,KAAME,EAAQ,KAAKK,KAAUN,KAAMC,EAAQ,KAAKK,GACzDE,IACJL,MAAc,KAAA,KAAaA,IAAY,IACnC,KAAK,IAAIE,IAAOF,IAAY,CAAC,IAAI,OACjCE,KAAQH,IAAO;EACrB,IAAIK,KAAUC,GAAO,OAAO,CAACP,EAAQ,IAAIA,EAAQ,EAAE;CACrD;CACA,IAAMQ,KAAUV,IAAKC,KAAM;CAC3B,OAAO,CAACS,IAASP,IAAO,GAAGO,IAASP,IAAO,CAAC;AAC9C,GAOaQ,KACX,GACA,GACA,GACA,MAKO,CAACC,KAHK,OAAO,SAASC,CAAK,IAC9B,KAAK,IAAI,KAAK,IAAIR,GAASS,CAAM,GAAG,KAAK,IAAIA,GAAQF,IAAQC,CAAK,CAAC,IACnEC,IACkBF,CAAK,GAIhBG,KAAY,MAA0B;CACjD,IAAI,EAAEC,IAAQ,MAAM,CAAC,OAAO,SAASA,CAAK,GAAG,OAAO;CACpD,IAAMC,IAAQ,MAAM,KAAK,MAAM,KAAK,MAAMD,CAAK,CAAC;CAChD,KAAK,IAAME,KAAK;EAAC;EAAG;EAAG;EAAK;EAAG;CAAE,GAC/B,IAAIA,IAAID,KAASD,KAAS,IAAI,OAAO,OAAOE,IAAID;CAElD,OAAO,KAAKA;AACd"}
1
+ {"version":3,"file":"layout.js","names":["layoutAxisLabels","top","bottom","bounds","order","pinned","label","a","b","place","sum","item","block","k","ideal","blocks","i","last","previous","gap","shift","o","centers","overlaps","ah","bh","hover","y","shown","ticks","tickHeight","fitPriceRange","lo","hi","current","want","fixedSpan","minSpan","span","margin","inside","sized","center","fitTimeRange","right","first","window","fineCeil","value","power","m"],"sources":["../../../../../charts/src/engine/orderbook/layout.ts"],"sourcesContent":["// Pure layout helpers of the order book widgets: price-axis label collision\n// resolution and the view fitting of the liquidity heatmap.\n\n/** A label on a vertical axis: center and height, in pixels */\nexport interface AxisLabel {\n y: number;\n h: number;\n}\n\n/** Result of `layoutAxisLabels` */\nexport interface AxisLabelLayout {\n /** Centers of the pinned labels (moved apart), `null` when hidden by the hover label */\n pinned: (number | null)[];\n /** Whether each tick label stays visible */\n ticks: boolean[];\n}\n\n/**\n * Resolves the collisions of the labels of a price axis. Priority: the\n * hover label stays where it is and hides the pinned labels it covers;\n * pinned labels (best bid / ask, last trade) never overlap each other: a\n * group of overlapping ones is stacked, in order, around their desired\n * positions and kept within `bounds`; tick labels under any of them are\n * hidden.\n */\nexport const layoutAxisLabels = (\n pinned: readonly AxisLabel[],\n hover: AxisLabel | null,\n ticks: readonly number[],\n tickHeight: number,\n bounds: readonly [number, number],\n gap = 2,\n): AxisLabelLayout => {\n const [top, bottom] = bounds;\n // blocks of stacked labels, top to bottom\n interface Block {\n items: number[];\n /** Offset of each item's center from the block's top */\n offsets: number[];\n height: number;\n top: number;\n }\n const order = pinned\n .map((label, i) => ({ label, i }))\n .filter(({ label }) => Number.isFinite(label.y))\n .sort((a, b) => a.label.y - b.label.y || a.i - b.i);\n const place = (block: Block) => {\n let sum = 0;\n block.items.forEach((item, k) => {\n sum += pinned[item]!.y - block.offsets[k]!;\n });\n const ideal = sum / block.items.length;\n block.top = Math.max(top, Math.min(ideal, bottom - block.height));\n };\n const blocks: Block[] = [];\n for (const { label, i } of order) {\n const block: Block = {\n items: [i],\n offsets: [label.h / 2],\n height: label.h,\n top: label.y - label.h / 2,\n };\n place(block);\n blocks.push(block);\n // merge with the blocks above while they overlap\n while (blocks.length > 1) {\n const last = blocks[blocks.length - 1]!;\n const previous = blocks[blocks.length - 2]!;\n if (previous.top + previous.height + gap <= last.top) break;\n const shift = previous.height + gap;\n previous.items.push(...last.items);\n previous.offsets.push(...last.offsets.map((o) => o + shift));\n previous.height += gap + last.height;\n blocks.pop();\n place(previous);\n }\n }\n const centers: (number | null)[] = pinned.map(() => null);\n for (const block of blocks) {\n block.items.forEach((item, k) => {\n centers[item] = block.top + block.offsets[k]!;\n });\n }\n const overlaps = (a: number, ah: number, b: number, bh: number) =>\n Math.abs(a - b) < (ah + bh) / 2 + gap;\n if (hover) {\n centers.forEach((y, i) => {\n if (y !== null && overlaps(y, pinned[i]!.h, hover.y, hover.h))\n centers[i] = null;\n });\n }\n const shown: AxisLabel[] = [];\n centers.forEach((y, i) => {\n if (y !== null) shown.push({ y, h: pinned[i]!.h });\n });\n if (hover) shown.push(hover);\n return {\n pinned: centers,\n ticks: ticks.map(\n (y) =>\n y - tickHeight / 2 >= top &&\n y + tickHeight / 2 <= bottom &&\n !shown.some((label) => overlaps(y, tickHeight, label.y, label.h)),\n ),\n };\n};\n\n/**\n * Price range of a following heatmap view, with hysteresis: the current\n * range is kept while the traded prices (`lo` – `hi`, best bid / ask of the\n * window) stay inside its inner part and it is not much too wide; otherwise\n * a range centered on them, `minSpan` or 1.6 × their spread high. With\n * `fixedSpan` (the user zoomed the prices) only the center moves.\n */\nexport const fitPriceRange = (\n current: readonly [number, number] | null,\n lo: number,\n hi: number,\n minSpan: number,\n fixedSpan?: number,\n): [number, number] => {\n if (!Number.isFinite(lo) || !Number.isFinite(hi)) {\n return current ? [current[0], current[1]] : [NaN, NaN];\n }\n const want =\n fixedSpan !== undefined && fixedSpan > 0\n ? fixedSpan\n : Math.max(minSpan, (hi - lo) * 1.6);\n if (current && Number.isFinite(current[0]) && Number.isFinite(current[1])) {\n const span = current[1] - current[0];\n const margin = span * 0.12;\n const inside = lo >= current[0] + margin && hi <= current[1] - margin;\n const sized =\n fixedSpan !== undefined && fixedSpan > 0\n ? Math.abs(span / fixedSpan - 1) < 1e-6\n : span <= want * 1.8;\n if (inside && sized) return [current[0], current[1]];\n }\n const center = (lo + hi) / 2;\n return [center - want / 2, center + want / 2];\n};\n\n/**\n * Time range of a following heatmap view ending at `right`: `window` wide\n * once the data covers it; before that, the span of the data (at least\n * `minSpan`), so a short history fills the plot from the left.\n */\nexport const fitTimeRange = (\n first: number,\n right: number,\n window: number,\n minSpan: number,\n): [number, number] => {\n const span = Number.isFinite(first)\n ? Math.max(Math.min(minSpan, window), Math.min(window, right - first))\n : window;\n return [right - span, right];\n};\n\n/** Smallest \"nice\" number (1, 2, 2.5, 5 × 10ⁿ) at least `value` */\nexport const niceCeil = (value: number): number => {\n if (!(value > 0) || !Number.isFinite(value)) return 0;\n const power = 10 ** Math.floor(Math.log10(value));\n for (const m of [1, 2, 2.5, 5, 10]) {\n if (m * power >= value * (1 - 1e-9)) return m * power;\n }\n return 10 * power;\n};\n\n/**\n * Smallest number of a fine \"nice\" series (1, 1.2, 1.5, 2, 2.5, 3, 4, 5,\n * 6, 8 × 10ⁿ) at least `value`: a scale at most a third above the value\n */\nexport const fineCeil = (value: number): number => {\n if (!(value > 0) || !Number.isFinite(value)) return 0;\n const power = 10 ** Math.floor(Math.log10(value));\n for (const m of [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10]) {\n if (m * power >= value * (1 - 1e-9)) return +(m * power).toPrecision(12);\n }\n return 10 * power;\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("../color.cjs"),t=require("../locale.cjs"),n=require("./book.cjs"),r=require("./format.cjs"),i=require("./host.cjs");var a={en:{time:`Time`,price:`Price`,size:`Size`,side:`Side`,buy:`Buy`,sell:`Sell`,paused:`Paused`,newTrades:`{count} new`,name:`Time and sales`},zh:{time:`时间`,price:`价格`,size:`数量`,side:`方向`,buy:`买入`,sell:`卖出`,paused:`已暂停`,newTrades:`{count} 条新成交`,name:`逐笔成交`},ja:{time:`時刻`,price:`価格`,size:`数量`,side:`売買`,buy:`買い`,sell:`売り`,paused:`一時停止中`,newTrades:`新着 {count} 件`,name:`歩み値`},fr:{time:`Heure`,price:`Prix`,size:`Quantité`,side:`Sens`,buy:`Achat`,sell:`Vente`,paused:`En pause`,newTrades:`{count} nouvelles`,name:`Historique des transactions`}},o=[`time`,`price`,`size`],s=1,c=2,l=3,u=450,d=e=>{let t=Math.min(e,1024);return{time:new Float64Array(t),price:new Float64Array(t),size:new Float64Array(t),side:new Uint8Array(t),tick:new Int8Array(t),count:new Uint32Array(t),arrival:new Float64Array(t),start:0,length:0,max:e}},f=(e,t)=>(e.start+t)%e.time.length,p=e=>{let t=e.time.length;if(e.length<t){let n=(e.start+e.length)%t;return e.length++,n}if(t<e.max){let n=Math.min(e.max,t*2);for(let r of[`time`,`price`,`size`,`side`,`tick`,`count`,`arrival`]){let i=e[r],a=new i.constructor(n);a.set(i.subarray(e.start)),a.set(i.subarray(0,e.start),t-e.start),e[r]=a}return e.start=0,e.length++,t}let n=e.start;return e.start=(e.start+1)%t,n},m=(m,h={})=>{let g=h,_=i.createEmitter(),v=Math.max(1,Math.round(g.capacity??2e5)),y=d(v),b=d(v),x=null,S=0,C=0,w=NaN,T=0,E=r.createFormatters(g,2,4),D=0,O=0,k={up:[0,0,0,1],down:[0,0,0,1]},A=0,j=0,M=!1,N=!1,P=!1,ee=NaN,F=null,I=null,te=``,L=null,R=null,z={top:0,rh:20,visible:0,track:[0,0,0,0],badge:[0,0,0,0]},B=i.createHost(m,{className:`minerva-time-and-sales`,draw:fe,onTheme:()=>{k=r.sideColors(B.theme,g)}}),{root:V}=B;V.tabIndex=0,V.setAttribute(`role`,`log`),V.setAttribute(`aria-live`,`off`);let ne=t.localeLabels(a,g.locale,g.labels),re=()=>ne,ie=()=>{ne=t.localeLabels(a,g.locale,g.labels),V.setAttribute(`aria-label`,g.ariaLabel??ne.name)},H=()=>Math.max(0,g.minSize??0),U=()=>x!==null&&x.size>=H(),W=()=>b.length+ +!!U(),G=()=>{E=r.createFormatters(g,D,O)},K=e=>{if(y.length>64)return;let t=Math.min(8,n.decimalsOf(e.price)),r=Math.min(6,n.decimalsOf(e.size));(t>D||r>O)&&(D=Math.max(D,t),O=Math.max(O,r),G())},ae=e=>{let t=p(b);b.time[t]=e.time,b.price[t]=e.price,b.size[t]=e.size,b.side[t]=e.side,b.tick[t]=e.tick,b.count[t]=e.count,b.arrival[t]=e.arrival,C++},oe=(e,t,n,r,i,a)=>{if(g.aggregate){if(x&&x.side===r&&x.time===e){x.size+=n,x.price=t,x.tick=i,x.count++,x.arrival=a;return}x&&x.size>=H()&&ae(x),x={time:e,price:t,size:n,side:r,tick:i,count:1,arrival:a};return}n>=H()&&ae({time:e,price:t,size:n,side:r,tick:i,count:1,arrival:a})},se=e=>{let t=C+ +!!U(),n=t-e;if(S=t,n<=0)return;A+=n,P?j+=n:A=g.animate===!1?j:Math.min(A,j+l);let r=W();j=Math.min(j,Math.max(0,r-1)),A=Math.min(A,Math.max(0,r-1))},ce=(e,t)=>{let{time:n,price:r,size:i}=e;if(!Number.isFinite(r)||!Number.isFinite(i)||i<=0)return;K(e);let a=e.side===`sell`?c:s;Number.isFinite(w)&&r!==w&&(T=r>w?1:-1),w=r;let o=p(y);y.time[o]=n,y.price[o]=r,y.size[o]=i,y.side[o]=a,y.tick[o]=T,oe(n,r,i,a,T,t)},le=()=>{b=d(v),x=null,C=0;for(let e=0;e<y.length;e++){let t=f(y,e);oe(y.time[t],y.price[t],y.size[t],y.side[t],y.tick[t],-1/0)}S=W(),A=j=0,M=!1,I=null},ue=e=>{if(e<0)return null;let t=U();if(t&&e===0)return x;let n=b.length-1-(e-+!!t);if(n<0)return null;let r=f(b,n);return{time:b.time[r],price:b.price[r],size:b.size[r],side:b.side[r],tick:b.tick[r],count:b.count[r],arrival:b.arrival[r]}},de=(e,t)=>({trade:{time:e.time,price:e.price,size:e.size,side:e.side===c?`sell`:`buy`},count:e.count,index:t}),q=()=>{let e=N||M||I!==null;e!==P&&(P=e,P||(j=0,A=Math.min(A,Math.max(l,z.visible))),_.emit(`pause`,P))},J=(e,t=!0)=>{let n=Math.max(0,W()-z.visible);j=r.clamp(Math.round(e),0,n),t&&(M=j>0),q(),B.invalidate()};function fe(t){let n=B.ctx;if(!n)return!1;let{width:i,height:a,dpr:s,theme:l}=B,d=re(),f=i<240,p=g.fontSize??(f?11:12),m=Math.max(12,g.rowHeight??(f?18:20)),h=g.header===!1?0:m+2,v=h,y=Math.max(0,Math.ceil((a-v)/m)),b=W(),x=Number.isFinite(ee)?t-ee:16;ee=t;let C=!1;g.animate===!1||!Number.isFinite(A)?A=j:(A+=(j-A)*r.ease(x,70),Math.abs(A-j)<.01?A=j:C=!0),n.setTransform(s,0,0,s,0,0),n.clearRect(0,0,i,a);let w=e.toCss(l.text),T=e.toCss(l.textMuted),D=f?6:10,O=b>Math.floor((a-v)/m),ne=i-D-(O?6:0),ie=(g.columns??o).filter((e,t,n)=>n.indexOf(e)===t),H=f&&ie.length>3?ie.filter(e=>e!==`side`):ie,U={time:g.milliseconds===!1?1:1.25,price:1.1,size:1,side:.6},G=H.reduce((e,t)=>e+U[t],0),K=[],ae=D;for(let e of H)ae+=(ne-D)*U[e]/G,K.push(ae);let oe=e=>e===0?D:K[e-1],se=(e,t)=>t===0||e===`time`,ce=g.largeTradeThreshold??1/0,le=Math.max(0,Math.floor(A)),q=A-le,J=g.animate!==!1;L=null;let fe=-1;F&&F[1]>=v?fe=Math.floor((F[1]-v)/m+A):I!==null&&(fe=S-1-I),n.save(),n.beginPath(),n.rect(0,v,i,a-v),n.clip(),n.textBaseline=`middle`;for(let o=0;o<=y;o++){let s=le+o;if(s>=b)break;let h=ue(s);if(!h)break;let _=v+(o-q)*m;if(_>a)break;let y=h.side===c,x=y?k.down:k.up,S=h.size>=ce;if(s===fe&&(L=de(h,s),n.fillStyle=e.toCss(l.text,.08),n.fillRect(0,_,i,m)),S){let t=r.clamp(Math.log2(h.size/ce)/3,0,1);n.fillStyle=e.toCss(x,.12+.2*t),n.fillRect(0,_+1,i,m-2),n.fillStyle=e.toCss(x),n.fillRect(0,_+2,3,m-4)}if(J&&Number.isFinite(h.arrival)){let r=(t-h.arrival)/u;r<1&&r>=0&&(n.fillStyle=e.toCss(x,.18*(1-r)*(1-r)),n.fillRect(0,_,i,m),C=!0)}let D=_+m/2+.5,O=S?700:400;H.forEach((t,i)=>{let a=se(t,i);n.textAlign=a?`left`:`right`;let o=a?oe(i)+(i===0&&S?4:0):K[i];switch(t){case`time`:n.font=r.fontOf(l,g,400,p),n.fillStyle=T,n.fillText(g.formatTime?g.formatTime(h.time):r.formatClock(h.time,g.milliseconds!==!1,g.timeZone),o,D);break;case`price`:{let t=h.tick>0?k.up:h.tick<0?k.down:null;n.font=r.fontOf(l,g,S?700:500,p),n.fillStyle=g.priceColor===`tick`?t?e.toCss(t):w:e.toCss(x),n.fillText(E.price(h.price),o,D);break}case`size`:{n.font=r.fontOf(l,g,O,p),n.fillStyle=S?e.toCss(x):w;let t=E.size(h.size);if(n.fillText(t,o,D),h.count>1&&!f){let e=n.measureText(t).width;n.font=r.fontOf(l,g,400,p-2),n.fillStyle=T,n.fillText(`×${h.count}`,o-e-5,D)}break}case`side`:n.font=r.fontOf(l,g,500,p),n.fillStyle=e.toCss(x),n.fillText(y?d.sell:d.buy,o,D)}})}n.restore(),h&&(n.font=r.fontOf(l,g,400,p-1),n.fillStyle=T,n.textBaseline=`middle`,H.forEach((e,t)=>{let r=se(e,t);n.textAlign=r?`left`:`right`,n.fillText(d[e],r?oe(t):K[t],m/2+1)}),n.fillStyle=e.toCss(l.grid),n.fillRect(0,h-1,i,1));let X=a-v-4,pe=[0,0,0,0];if(O&&X>20){let t=Math.max(1,(a-v)/m),o=Math.max(18,X*t/b),s=Math.max(1,b-t),c=v+2+(X-o)*r.clamp(A/s,0,1),u=R!==null||F!==null&&F[0]>i-12;n.fillStyle=e.toCss(l.textMuted,u?.5:.28),r.roundRect(n,i-6,c,4,o,2),n.fill(),pe=[i-12,v,12,X+4]}let Z=[0,0,0,0],Q=Math.round(j);if(P||Q>0){let t=[];if(N&&!M&&t.push(d.paused),Q>0&&t.push(d.newTrades.replace(`{count}`,Q>9999?`9999+`:String(Q))),t.length){let a=t.join(` · `);n.font=r.fontOf(l,g,500,Math.max(10,p-1));let o=n.measureText(a).width+20,s=Math.min(22,m+2),c=(i-o)/2,u=v+6;n.fillStyle=e.toCss(l.primary,.92),r.roundRect(n,c,u,o,s,s/2),n.fill(),n.fillStyle=`#fff`,n.textAlign=`center`,n.textBaseline=`middle`,n.fillText(a,i/2,u+s/2+.5),Z=[c,u,o,s]}}z={top:v,rh:m,visible:Math.floor((a-v)/m),track:pe,badge:Z},V.style.cursor=Z[2]&&F&&Y(F,Z)?`pointer`:`default`;let me=L?`${S-1-L.index}|${L.trade.size}`:``;me!==te&&(te=me,_.emit(`hover`,L));let $=ue(0);return $&&B.describe(`${g.ariaLabel??d.name}. ${$.side===c?d.sell:d.buy} ${E.size($.size)} @ ${E.price($.price)}.`),C}let Y=(e,t)=>t[2]>0&&e[0]>=t[0]&&e[0]<=t[0]+t[2]&&e[1]>=t[1]&&e[1]<=t[1]+t[3],X=e=>{let[,t,,n]=z.track,i=W(),a=r.clamp((e-t)/Math.max(1,n),0,1);J(a*Math.max(0,i-z.visible))},pe=e=>{F=i.localPoint(V,e),R&&X(F[1]-R.offset),g.pauseOnHover!==!1&&!N&&(N=!0,q()),B.invalidate()},Z=()=>{F=null,N&&(N=!1,q()),B.invalidate()},Q=e=>{let t=i.localPoint(V,e);Y(t,z.track)&&!Y(t,z.badge)&&(R={offset:0},V.setPointerCapture?.(e.pointerId),X(t[1]),e.preventDefault())},me=e=>{R&&(R=null,V.releasePointerCapture?.(e.pointerId),B.invalidate())},$=e=>{let t=i.localPoint(V,e);if(Y(t,z.badge)){be.scrollToLatest();return}if(Y(t,z.track)||t[1]<z.top)return;let n=Math.floor((t[1]-z.top)/z.rh+A),r=ue(n);r&&n<W()&&_.emit(`tradeClick`,de(r,n))},he=e=>{let t=W(),n=Math.max(0,t-z.visible),r=e.deltaMode===1?e.deltaY:e.deltaMode===2?e.deltaY*z.visible:e.deltaY/z.rh;r<0&&j<=0||r>0&&j>=n||(e.preventDefault(),J(j+(Math.abs(r)<1?Math.sign(r):r)))},ge=e=>{let t=W();if(!t)return;let n=Math.max(1,z.visible-1),i=I===null?-1:S-1-I,a=e=>{let n=r.clamp(e,0,t-1);I=S-1-n,n<j?J(n):n>=j+z.visible?J(n-z.visible+1):q(),B.invalidate()};switch(e.key){case`ArrowDown`:a(i+1);break;case`ArrowUp`:a(Math.max(0,i-1));break;case`PageDown`:a(Math.max(0,i)+n);break;case`PageUp`:a(i-n);break;case`Home`:I=null,be.scrollToLatest();break;case`End`:a(t-1);break;case`Enter`:case` `:{let e=i>=0?ue(i):null;e&&_.emit(`tradeClick`,de(e,i));break}case`Escape`:I=null,be.scrollToLatest();break;default:return}e.preventDefault()},_e=()=>{I!==null&&(I=null,q(),B.invalidate())};V.addEventListener(`pointermove`,pe),V.addEventListener(`pointerleave`,Z),V.addEventListener(`pointerdown`,Q),V.addEventListener(`pointerup`,me),V.addEventListener(`click`,$),V.addEventListener(`wheel`,he,{passive:!1}),V.addEventListener(`keydown`,ge),V.addEventListener(`blur`,_e);let ve=()=>typeof performance<`u`?performance.now():Date.now(),ye=()=>{y=d(v),b=d(v),x=null,S=C=0,w=NaN,T=0,D=O=0,A=j=0,M=!1,I=null,q(),G()},be={addTrades(e){let t=Array.isArray(e)?e:[e];if(!t.length)return;let n=S,r=ve();for(let e of t)ce(e,r);se(n),B.invalidate()},setTrades(e){ye();for(let t of e)ce(t,-1/0);S=W(),B.invalidate()},clear(){ye(),B.invalidate()},setOptions(e){let t=g;g=e,ie(),k=r.sideColors(B.theme,g);let n=Math.max(1,Math.round(g.capacity??2e5));if(n!==v){let e=y;v=n,y=d(v);for(let t=Math.max(0,e.length-v);t<e.length;t++){let n=f(e,t),r=p(y);y.time[r]=e.time[n],y.price[r]=e.price[n],y.size[r]=e.size[n],y.side[r]=e.side[n],y.tick[r]=e.tick[n]}le()}else((t.minSize??0)!==(e.minSize??0)||!t.aggregate!=!e.aggregate)&&le();g.pauseOnHover===!1&&N&&(N=!1),q(),G(),B.invalidate()},scrollToLatest(){I=null,M=!1,j=0,q(),B.invalidate()},getCount:W,on:(e,t)=>_.on(e,t),resize(){B.invalidate()},destroy(){V.removeEventListener(`pointermove`,pe),V.removeEventListener(`pointerleave`,Z),V.removeEventListener(`pointerdown`,Q),V.removeEventListener(`pointerup`,me),V.removeEventListener(`click`,$),V.removeEventListener(`wheel`,he),V.removeEventListener(`keydown`,ge),V.removeEventListener(`blur`,_e),_.clear(),B.destroy()}};return ie(),k=r.sideColors(B.theme,g),G(),B.invalidate(),be};exports.createTimeAndSales=m;
1
+ const e=require("../color.cjs"),t=require("../locale.cjs"),n=require("./book.cjs"),r=require("./format.cjs"),i=require("./host.cjs");var a={en:{time:`Time`,price:`Price`,size:`Size`,side:`Side`,buy:`Buy`,sell:`Sell`,paused:`Paused`,newTrades:`{count} new`,name:`Time and sales`},zh:{time:`时间`,price:`价格`,size:`数量`,side:`方向`,buy:`买入`,sell:`卖出`,paused:`已暂停`,newTrades:`{count} 条新成交`,name:`逐笔成交`},ja:{time:`時刻`,price:`価格`,size:`数量`,side:`売買`,buy:`買い`,sell:`売り`,paused:`一時停止中`,newTrades:`新着 {count} 件`,name:`歩み値`},fr:{time:`Heure`,price:`Prix`,size:`Quantité`,side:`Sens`,buy:`Achat`,sell:`Vente`,paused:`En pause`,newTrades:`{count} nouvelles`,name:`Historique des transactions`}},o=[`time`,`price`,`size`],s=1,c=2,l=3,u=450,d=e=>{let t=Math.min(e,1024);return{time:new Float64Array(t),price:new Float64Array(t),size:new Float64Array(t),side:new Uint8Array(t),tick:new Int8Array(t),count:new Uint32Array(t),arrival:new Float64Array(t),start:0,length:0,max:e}},f=(e,t)=>(e.start+t)%e.time.length,p=e=>{let t=e.time.length;if(e.length<t){let n=(e.start+e.length)%t;return e.length++,n}if(t<e.max){let n=Math.min(e.max,t*2);for(let r of[`time`,`price`,`size`,`side`,`tick`,`count`,`arrival`]){let i=e[r],a=new i.constructor(n);a.set(i.subarray(e.start)),a.set(i.subarray(0,e.start),t-e.start),e[r]=a}return e.start=0,e.length++,t}let n=e.start;return e.start=(e.start+1)%t,n},m=(m,h={})=>{let g=h,_=i.createEmitter(),v=Math.max(1,Math.round(g.capacity??2e5)),y=d(v),b=d(v),x=null,S=0,C=0,w=NaN,T=0,E=r.createFormatters(g,2,4),D=0,O=0,k={up:[0,0,0,1],down:[0,0,0,1]},A=0,j=0,M=!1,N=!1,P=!1,ee=NaN,F=null,I=null,te=``,L=null,R=null,z={top:0,rh:20,visible:0,track:[0,0,0,0],badge:[0,0,0,0]},B=i.createHost(m,{className:`minerva-time-and-sales`,draw:fe,onTheme:()=>{k=r.sideColors(B.theme,g)}}),{root:V}=B;V.tabIndex=0,V.setAttribute(`role`,`log`),V.setAttribute(`aria-live`,`off`);let ne=t.localeLabels(a,g.locale,g.labels),re=()=>ne,ie=()=>{ne=t.localeLabels(a,g.locale,g.labels),V.setAttribute(`aria-label`,g.ariaLabel??ne.name)},H=()=>Math.max(0,g.minSize??0),U=()=>x!==null&&x.size>=H(),W=()=>b.length+ +!!U(),G=()=>{E=r.createFormatters(g,D,O)},K=e=>{if(y.length>64)return;let t=Math.min(8,n.decimalsOf(e.price)),r=Math.min(6,n.decimalsOf(e.size));(t>D||r>O)&&(D=Math.max(D,t),O=Math.max(O,r),G())},ae=e=>{let t=p(b);b.time[t]=e.time,b.price[t]=e.price,b.size[t]=e.size,b.side[t]=e.side,b.tick[t]=e.tick,b.count[t]=e.count,b.arrival[t]=e.arrival,C++},oe=(e,t,n,r,i,a)=>{if(g.aggregate){if(x&&x.side===r&&x.time===e){x.size+=n,x.price=t,x.tick=i,x.count++,x.arrival=a;return}x&&x.size>=H()&&ae(x),x={time:e,price:t,size:n,side:r,tick:i,count:1,arrival:a};return}n>=H()&&ae({time:e,price:t,size:n,side:r,tick:i,count:1,arrival:a})},se=e=>{let t=C+ +!!U(),n=t-e;if(S=t,n<=0)return;A+=n,P?j+=n:A=g.animate===!1?j:Math.min(A,j+l);let r=W();j=Math.min(j,Math.max(0,r-1)),A=Math.min(A,Math.max(0,r-1))},ce=(e,t)=>{let{time:n,price:r,size:i}=e;if(!Number.isFinite(r)||!Number.isFinite(i)||i<=0)return;K(e);let a=e.side===`sell`?c:s;Number.isFinite(w)&&r!==w&&(T=r>w?1:-1),w=r;let o=p(y);y.time[o]=n,y.price[o]=r,y.size[o]=i,y.side[o]=a,y.tick[o]=T,oe(n,r,i,a,T,t)},le=()=>{b=d(v),x=null,C=0;for(let e=0;e<y.length;e++){let t=f(y,e);oe(y.time[t],y.price[t],y.size[t],y.side[t],y.tick[t],-1/0)}S=W(),A=j=0,M=!1,I=null},ue=e=>{if(e<0)return null;let t=U();if(t&&e===0)return x;let n=b.length-1-(e-+!!t);if(n<0)return null;let r=f(b,n);return{time:b.time[r],price:b.price[r],size:b.size[r],side:b.side[r],tick:b.tick[r],count:b.count[r],arrival:b.arrival[r]}},de=(e,t)=>({trade:{time:e.time,price:e.price,size:e.size,side:e.side===c?`sell`:`buy`},count:e.count,index:t}),q=()=>{let e=N||M||I!==null;e!==P&&(P=e,P||(j=0,A=Math.min(A,Math.max(l,z.visible))),_.emit(`pause`,P))},J=(e,t=!0)=>{let n=Math.max(0,W()-z.visible);j=r.clamp(Math.round(e),0,n),t&&(M=j>0),q(),B.invalidate()};function fe(t){let n=B.ctx;if(!n)return!1;let{width:i,height:a,dpr:s,theme:l}=B,d=re(),f=i<240,p=g.fontSize??(f?11:12),m=Math.max(12,g.rowHeight??(f?18:20)),h=g.header===!1?0:m+2,v=h,y=Math.max(0,Math.ceil((a-v)/m)),b=W(),x=Number.isFinite(ee)?t-ee:16;ee=t;let C=!1;g.animate===!1||!Number.isFinite(A)?A=j:(A+=(j-A)*r.ease(x,70),Math.abs(A-j)<.01?A=j:C=!0),n.setTransform(s,0,0,s,0,0),n.clearRect(0,0,i,a);let w=e.toCss(l.text),T=e.toCss(l.textMuted),D=f?6:10,O=b>Math.floor((a-v)/m),ne=i-D-(O?6:0),ie=(g.columns??o).filter((e,t,n)=>n.indexOf(e)===t),H=f&&ie.length>3?ie.filter(e=>e!==`side`):ie,U={time:g.milliseconds===!1?1:1.25,price:1.1,size:1,side:.6},G=H.reduce((e,t)=>e+U[t],0),K=[],ae=D;for(let e of H)ae+=(ne-D)*U[e]/G,K.push(ae);let oe=e=>e===0?D:K[e-1],se=(e,t)=>t===0||e===`time`,ce=g.largeTradeThreshold??1/0,le=Math.max(0,Math.floor(A)),q=A-le,J=g.animate!==!1;L=null;let fe=-1;F&&F[1]>=v?fe=Math.floor((F[1]-v)/m+A):I!==null&&(fe=S-1-I),n.save(),n.beginPath(),n.rect(0,v,i,a-v),n.clip(),n.textBaseline=`middle`;for(let o=0;o<=y;o++){let s=le+o;if(s>=b)break;let h=ue(s);if(!h)break;let _=v+(o-q)*m;if(_>a)break;let y=h.side===c,x=y?k.down:k.up,S=h.size>=ce;if(s===fe&&(L=de(h,s),n.fillStyle=e.toCss(l.text,.08),n.fillRect(0,_,i,m)),S){let t=r.clamp(Math.log2(h.size/ce)/3,0,1);n.fillStyle=e.toCss(x,.12+.2*t),n.fillRect(0,_+1,i,m-2),n.fillStyle=e.toCss(x),n.beginPath(),n.arc(D/2,_+m/2,Math.min(2.5,D/2-1),0,Math.PI*2),n.fill()}if(J&&Number.isFinite(h.arrival)){let r=(t-h.arrival)/u;r<1&&r>=0&&(n.fillStyle=e.toCss(x,.18*(1-r)*(1-r)),n.fillRect(0,_,i,m),C=!0)}let O=_+m/2+.5,A=S?700:400;H.forEach((t,i)=>{let a=se(t,i);n.textAlign=a?`left`:`right`;let o=a?oe(i)+(i===0&&S?4:0):K[i];switch(t){case`time`:n.font=r.fontOf(l,g,400,p),n.fillStyle=T,n.fillText(g.formatTime?g.formatTime(h.time):r.formatClock(h.time,g.milliseconds!==!1,g.timeZone),o,O);break;case`price`:{let t=h.tick>0?k.up:h.tick<0?k.down:null;n.font=r.fontOf(l,g,S?700:500,p),n.fillStyle=g.priceColor===`tick`?t?e.toCss(t):w:e.toCss(x),n.fillText(E.price(h.price),o,O);break}case`size`:{n.font=r.fontOf(l,g,A,p),n.fillStyle=S?e.toCss(x):w;let t=E.size(h.size);if(n.fillText(t,o,O),h.count>1&&!f){let e=n.measureText(t).width;n.font=r.fontOf(l,g,400,p-2),n.fillStyle=T,n.fillText(`×${h.count}`,o-e-5,O)}break}case`side`:n.font=r.fontOf(l,g,500,p),n.fillStyle=e.toCss(x),n.fillText(y?d.sell:d.buy,o,O)}})}n.restore(),h&&(n.font=r.fontOf(l,g,400,p-1),n.fillStyle=T,n.textBaseline=`middle`,H.forEach((e,t)=>{let r=se(e,t);n.textAlign=r?`left`:`right`,n.fillText(d[e],r?oe(t):K[t],m/2+1)}),n.fillStyle=e.toCss(l.grid),n.fillRect(0,h-1,i,1));let X=a-v-4,pe=[0,0,0,0];if(O&&X>20){let t=Math.max(1,(a-v)/m),o=Math.max(18,X*t/b),s=Math.max(1,b-t),c=v+2+(X-o)*r.clamp(A/s,0,1),u=R!==null||F!==null&&F[0]>i-12;n.fillStyle=e.toCss(l.textMuted,u?.5:.28),r.roundRect(n,i-6,c,4,o,2),n.fill(),pe=[i-12,v,12,X+4]}let Z=[0,0,0,0],Q=Math.round(j);if(P||Q>0){let t=[];if(N&&!M&&t.push(d.paused),Q>0&&t.push(d.newTrades.replace(`{count}`,Q>9999?`9999+`:String(Q))),t.length){let a=t.join(` · `);n.font=r.fontOf(l,g,500,Math.max(10,p-1));let o=n.measureText(a).width+20,s=Math.min(22,m+2),c=(i-o)/2,u=v+6;n.fillStyle=e.toCss(l.primary,.92),r.roundRect(n,c,u,o,s,s/2),n.fill(),n.fillStyle=`#fff`,n.textAlign=`center`,n.textBaseline=`middle`,n.fillText(a,i/2,u+s/2+.5),Z=[c,u,o,s]}}z={top:v,rh:m,visible:Math.floor((a-v)/m),track:pe,badge:Z},V.style.cursor=Z[2]&&F&&Y(F,Z)?`pointer`:`default`;let me=L?`${S-1-L.index}|${L.trade.size}`:``;me!==te&&(te=me,_.emit(`hover`,L));let $=ue(0);return $&&B.describe(`${g.ariaLabel??d.name}. ${$.side===c?d.sell:d.buy} ${E.size($.size)} @ ${E.price($.price)}.`),C}let Y=(e,t)=>t[2]>0&&e[0]>=t[0]&&e[0]<=t[0]+t[2]&&e[1]>=t[1]&&e[1]<=t[1]+t[3],X=e=>{let[,t,,n]=z.track,i=W(),a=r.clamp((e-t)/Math.max(1,n),0,1);J(a*Math.max(0,i-z.visible))},pe=e=>{F=i.localPoint(V,e),R&&X(F[1]-R.offset),g.pauseOnHover!==!1&&!N&&(N=!0,q()),B.invalidate()},Z=()=>{F=null,N&&(N=!1,q()),B.invalidate()},Q=e=>{let t=i.localPoint(V,e);Y(t,z.track)&&!Y(t,z.badge)&&(R={offset:0},V.setPointerCapture?.(e.pointerId),X(t[1]),e.preventDefault())},me=e=>{R&&(R=null,V.releasePointerCapture?.(e.pointerId),B.invalidate())},$=e=>{let t=i.localPoint(V,e);if(Y(t,z.badge)){be.scrollToLatest();return}if(Y(t,z.track)||t[1]<z.top)return;let n=Math.floor((t[1]-z.top)/z.rh+A),r=ue(n);r&&n<W()&&_.emit(`tradeClick`,de(r,n))},he=e=>{let t=W(),n=Math.max(0,t-z.visible),r=e.deltaMode===1?e.deltaY:e.deltaMode===2?e.deltaY*z.visible:e.deltaY/z.rh;r<0&&j<=0||r>0&&j>=n||(e.preventDefault(),J(j+(Math.abs(r)<1?Math.sign(r):r)))},ge=e=>{let t=W();if(!t)return;let n=Math.max(1,z.visible-1),i=I===null?-1:S-1-I,a=e=>{let n=r.clamp(e,0,t-1);I=S-1-n,n<j?J(n):n>=j+z.visible?J(n-z.visible+1):q(),B.invalidate()};switch(e.key){case`ArrowDown`:a(i+1);break;case`ArrowUp`:a(Math.max(0,i-1));break;case`PageDown`:a(Math.max(0,i)+n);break;case`PageUp`:a(i-n);break;case`Home`:I=null,be.scrollToLatest();break;case`End`:a(t-1);break;case`Enter`:case` `:{let e=i>=0?ue(i):null;e&&_.emit(`tradeClick`,de(e,i));break}case`Escape`:I=null,be.scrollToLatest();break;default:return}e.preventDefault()},_e=()=>{I!==null&&(I=null,q(),B.invalidate())};V.addEventListener(`pointermove`,pe),V.addEventListener(`pointerleave`,Z),V.addEventListener(`pointerdown`,Q),V.addEventListener(`pointerup`,me),V.addEventListener(`click`,$),V.addEventListener(`wheel`,he,{passive:!1}),V.addEventListener(`keydown`,ge),V.addEventListener(`blur`,_e);let ve=()=>typeof performance<`u`?performance.now():Date.now(),ye=()=>{y=d(v),b=d(v),x=null,S=C=0,w=NaN,T=0,D=O=0,A=j=0,M=!1,I=null,q(),G()},be={addTrades(e){let t=Array.isArray(e)?e:[e];if(!t.length)return;let n=S,r=ve();for(let e of t)ce(e,r);se(n),B.invalidate()},setTrades(e){ye();for(let t of e)ce(t,-1/0);S=W(),B.invalidate()},clear(){ye(),B.invalidate()},setOptions(e){let t=g;g=e,ie(),k=r.sideColors(B.theme,g);let n=Math.max(1,Math.round(g.capacity??2e5));if(n!==v){let e=y;v=n,y=d(v);for(let t=Math.max(0,e.length-v);t<e.length;t++){let n=f(e,t),r=p(y);y.time[r]=e.time[n],y.price[r]=e.price[n],y.size[r]=e.size[n],y.side[r]=e.side[n],y.tick[r]=e.tick[n]}le()}else((t.minSize??0)!==(e.minSize??0)||!t.aggregate!=!e.aggregate)&&le();g.pauseOnHover===!1&&N&&(N=!1),q(),G(),B.invalidate()},scrollToLatest(){I=null,M=!1,j=0,q(),B.invalidate()},getCount:W,on:(e,t)=>_.on(e,t),resize(){B.invalidate()},destroy(){V.removeEventListener(`pointermove`,pe),V.removeEventListener(`pointerleave`,Z),V.removeEventListener(`pointerdown`,Q),V.removeEventListener(`pointerup`,me),V.removeEventListener(`click`,$),V.removeEventListener(`wheel`,he),V.removeEventListener(`keydown`,ge),V.removeEventListener(`blur`,_e),_.clear(),B.destroy()}};return ie(),k=r.sideColors(B.theme,g),G(),B.invalidate(),be};exports.createTimeAndSales=m;
2
2
  //# sourceMappingURL=tape.cjs.map