react-cheminfo 0.28.0 → 0.29.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 (691) hide show
  1. package/README.md +38 -25
  2. package/lib/chart/core/axisLabels.d.ts +82 -0
  3. package/lib/chart/core/axisLabels.d.ts.map +1 -0
  4. package/lib/chart/core/axisLabels.js +111 -0
  5. package/lib/chart/core/axisLabels.js.map +1 -0
  6. package/lib/chart/core/boxLayout.d.ts +53 -0
  7. package/lib/chart/core/boxLayout.d.ts.map +1 -0
  8. package/lib/chart/core/boxLayout.js +112 -0
  9. package/lib/chart/core/boxLayout.js.map +1 -0
  10. package/lib/chart/core/chartAxisScale.d.ts +23 -2
  11. package/lib/chart/core/chartAxisScale.d.ts.map +1 -1
  12. package/lib/chart/core/chartAxisScale.js +64 -13
  13. package/lib/chart/core/chartAxisScale.js.map +1 -1
  14. package/lib/chart/core/chartDomain.d.ts +160 -0
  15. package/lib/chart/core/chartDomain.d.ts.map +1 -0
  16. package/lib/chart/core/chartDomain.js +46 -0
  17. package/lib/chart/core/chartDomain.js.map +1 -0
  18. package/lib/chart/core/chartGeometry.d.ts +131 -0
  19. package/lib/chart/core/chartGeometry.d.ts.map +1 -0
  20. package/lib/chart/core/chartGeometry.js +101 -0
  21. package/lib/chart/core/chartGeometry.js.map +1 -0
  22. package/lib/chart/core/chartPane.d.ts +11 -0
  23. package/lib/chart/core/chartPane.d.ts.map +1 -0
  24. package/lib/chart/core/chartPane.js +11 -0
  25. package/lib/chart/core/chartPane.js.map +1 -0
  26. package/lib/chart/core/chartScale.d.ts +4 -1
  27. package/lib/chart/core/chartScale.d.ts.map +1 -1
  28. package/lib/chart/core/chartScale.js +8 -4
  29. package/lib/chart/core/chartScale.js.map +1 -1
  30. package/lib/chart/core/chartTheme.d.ts +156 -0
  31. package/lib/chart/core/chartTheme.d.ts.map +1 -0
  32. package/lib/chart/core/chartTheme.js +156 -0
  33. package/lib/chart/core/chartTheme.js.map +1 -0
  34. package/lib/chart/core/chartViewport.d.ts +32 -5
  35. package/lib/chart/core/chartViewport.d.ts.map +1 -1
  36. package/lib/chart/core/chartViewport.js +40 -11
  37. package/lib/chart/core/chartViewport.js.map +1 -1
  38. package/lib/chart/core/guidePlacement.d.ts +52 -0
  39. package/lib/chart/core/guidePlacement.d.ts.map +1 -0
  40. package/lib/chart/core/guidePlacement.js +52 -0
  41. package/lib/chart/core/guidePlacement.js.map +1 -0
  42. package/lib/chart/core/index.d.ts +29 -2
  43. package/lib/chart/core/index.d.ts.map +1 -1
  44. package/lib/chart/core/index.js +19 -2
  45. package/lib/chart/core/index.js.map +1 -1
  46. package/lib/chart/core/labelStack.d.ts +27 -0
  47. package/lib/chart/core/labelStack.d.ts.map +1 -0
  48. package/lib/chart/core/labelStack.js +62 -0
  49. package/lib/chart/core/labelStack.js.map +1 -0
  50. package/lib/chart/core/legendBox.d.ts +152 -0
  51. package/lib/chart/core/legendBox.d.ts.map +1 -0
  52. package/lib/chart/core/legendBox.js +169 -0
  53. package/lib/chart/core/legendBox.js.map +1 -0
  54. package/lib/chart/core/selectionGeometry.d.ts +45 -0
  55. package/lib/chart/core/selectionGeometry.d.ts.map +1 -0
  56. package/lib/chart/core/selectionGeometry.js +49 -0
  57. package/lib/chart/core/selectionGeometry.js.map +1 -0
  58. package/lib/chart/core/spectrumColor.d.ts +80 -0
  59. package/lib/chart/core/spectrumColor.d.ts.map +1 -0
  60. package/lib/chart/core/spectrumColor.js +120 -0
  61. package/lib/chart/core/spectrumColor.js.map +1 -0
  62. package/lib/chart/core/stackCapacity.d.ts +136 -0
  63. package/lib/chart/core/stackCapacity.d.ts.map +1 -0
  64. package/lib/chart/core/stackCapacity.js +153 -0
  65. package/lib/chart/core/stackCapacity.js.map +1 -0
  66. package/lib/chart/core/svgPoint.d.ts +62 -0
  67. package/lib/chart/core/svgPoint.d.ts.map +1 -0
  68. package/lib/chart/core/svgPoint.js +43 -0
  69. package/lib/chart/core/svgPoint.js.map +1 -0
  70. package/lib/chart/core/tracePath.d.ts +94 -0
  71. package/lib/chart/core/tracePath.d.ts.map +1 -0
  72. package/lib/chart/core/tracePath.js +191 -0
  73. package/lib/chart/core/tracePath.js.map +1 -0
  74. package/lib/chart/core/trackerReadout.d.ts +55 -0
  75. package/lib/chart/core/trackerReadout.d.ts.map +1 -0
  76. package/lib/chart/core/trackerReadout.js +53 -0
  77. package/lib/chart/core/trackerReadout.js.map +1 -0
  78. package/lib/chart/core/viewTransform.d.ts +167 -0
  79. package/lib/chart/core/viewTransform.d.ts.map +1 -0
  80. package/lib/chart/core/viewTransform.js +188 -0
  81. package/lib/chart/core/viewTransform.js.map +1 -0
  82. package/lib/chart/core/zoomDomain.d.ts +127 -0
  83. package/lib/chart/core/zoomDomain.d.ts.map +1 -0
  84. package/lib/chart/core/zoomDomain.js +175 -0
  85. package/lib/chart/core/zoomDomain.js.map +1 -0
  86. package/lib/chart/ui/Axes.d.ts +104 -0
  87. package/lib/chart/ui/Axes.d.ts.map +1 -0
  88. package/lib/chart/ui/Axes.js +155 -0
  89. package/lib/chart/ui/Axes.js.map +1 -0
  90. package/lib/chart/ui/AxisGuide.d.ts +60 -0
  91. package/lib/chart/ui/AxisGuide.d.ts.map +1 -0
  92. package/lib/chart/ui/AxisGuide.js +111 -0
  93. package/lib/chart/ui/AxisGuide.js.map +1 -0
  94. package/lib/chart/ui/ChartStack.d.ts +81 -0
  95. package/lib/chart/ui/ChartStack.d.ts.map +1 -0
  96. package/lib/chart/ui/ChartStack.js +42 -0
  97. package/lib/chart/ui/ChartStack.js.map +1 -0
  98. package/lib/chart/ui/ChartTracker.d.ts +36 -0
  99. package/lib/chart/ui/ChartTracker.d.ts.map +1 -0
  100. package/lib/chart/ui/ChartTracker.js +27 -0
  101. package/lib/chart/ui/ChartTracker.js.map +1 -0
  102. package/lib/chart/ui/PlotCaption.d.ts +44 -0
  103. package/lib/chart/ui/PlotCaption.d.ts.map +1 -0
  104. package/lib/chart/ui/PlotCaption.js +68 -0
  105. package/lib/chart/ui/PlotCaption.js.map +1 -0
  106. package/lib/chart/ui/SelectionRect.d.ts +27 -0
  107. package/lib/chart/ui/SelectionRect.d.ts.map +1 -0
  108. package/lib/chart/ui/SelectionRect.js +31 -0
  109. package/lib/chart/ui/SelectionRect.js.map +1 -0
  110. package/lib/chart/ui/TraceLegend.d.ts +99 -0
  111. package/lib/chart/ui/TraceLegend.d.ts.map +1 -0
  112. package/lib/chart/ui/TraceLegend.js +45 -0
  113. package/lib/chart/ui/TraceLegend.js.map +1 -0
  114. package/lib/chart/ui/chartGestures.d.ts +158 -0
  115. package/lib/chart/ui/chartGestures.d.ts.map +1 -0
  116. package/lib/chart/ui/chartGestures.js +145 -0
  117. package/lib/chart/ui/chartGestures.js.map +1 -0
  118. package/lib/chart/ui/chartStackLevel.d.ts +115 -0
  119. package/lib/chart/ui/chartStackLevel.d.ts.map +1 -0
  120. package/lib/chart/ui/chartStackLevel.js +96 -0
  121. package/lib/chart/ui/chartStackLevel.js.map +1 -0
  122. package/lib/chart/ui/chartSurface.d.ts +35 -0
  123. package/lib/chart/ui/chartSurface.d.ts.map +1 -0
  124. package/lib/chart/ui/chartSurface.js +58 -0
  125. package/lib/chart/ui/chartSurface.js.map +1 -0
  126. package/lib/chart/ui/index.d.ts +24 -0
  127. package/lib/chart/ui/index.d.ts.map +1 -1
  128. package/lib/chart/ui/index.js +13 -0
  129. package/lib/chart/ui/index.js.map +1 -1
  130. package/lib/chart/ui/useChartPointer.d.ts +124 -0
  131. package/lib/chart/ui/useChartPointer.d.ts.map +1 -0
  132. package/lib/chart/ui/useChartPointer.js +152 -0
  133. package/lib/chart/ui/useChartPointer.js.map +1 -0
  134. package/lib/chart/ui/useChartSize.d.ts +49 -0
  135. package/lib/chart/ui/useChartSize.d.ts.map +1 -0
  136. package/lib/chart/ui/useChartSize.js +91 -0
  137. package/lib/chart/ui/useChartSize.js.map +1 -0
  138. package/lib/chart/ui/useChartWindow.d.ts +147 -0
  139. package/lib/chart/ui/useChartWindow.d.ts.map +1 -0
  140. package/lib/chart/ui/useChartWindow.js +135 -0
  141. package/lib/chart/ui/useChartWindow.js.map +1 -0
  142. package/lib/chart/ui/useChartZoom.d.ts +88 -0
  143. package/lib/chart/ui/useChartZoom.d.ts.map +1 -0
  144. package/lib/chart/ui/useChartZoom.js +142 -0
  145. package/lib/chart/ui/useChartZoom.js.map +1 -0
  146. package/lib/chart/ui/useWheelListener.d.ts +30 -0
  147. package/lib/chart/ui/useWheelListener.d.ts.map +1 -0
  148. package/lib/chart/ui/useWheelListener.js +57 -0
  149. package/lib/chart/ui/useWheelListener.js.map +1 -0
  150. package/lib/clipboard/core/copyPng.d.ts +13 -0
  151. package/lib/clipboard/core/copyPng.d.ts.map +1 -0
  152. package/lib/clipboard/core/copyPng.js +19 -0
  153. package/lib/clipboard/core/copyPng.js.map +1 -0
  154. package/lib/clipboard/core/index.d.ts +1 -0
  155. package/lib/clipboard/core/index.d.ts.map +1 -1
  156. package/lib/clipboard/core/index.js +1 -0
  157. package/lib/clipboard/core/index.js.map +1 -1
  158. package/lib/core.d.ts +1 -0
  159. package/lib/core.d.ts.map +1 -1
  160. package/lib/core.js +1 -0
  161. package/lib/core.js.map +1 -1
  162. package/lib/download/core/exportStyles.d.ts +22 -0
  163. package/lib/download/core/exportStyles.d.ts.map +1 -0
  164. package/lib/download/core/exportStyles.js +19 -0
  165. package/lib/download/core/exportStyles.js.map +1 -0
  166. package/lib/download/core/imageResolution.d.ts +88 -0
  167. package/lib/download/core/imageResolution.d.ts.map +1 -0
  168. package/lib/download/core/imageResolution.js +77 -0
  169. package/lib/download/core/imageResolution.js.map +1 -0
  170. package/lib/download/core/index.d.ts +13 -0
  171. package/lib/download/core/index.d.ts.map +1 -1
  172. package/lib/download/core/index.js +8 -0
  173. package/lib/download/core/index.js.map +1 -1
  174. package/lib/download/core/pictureExport.d.ts +93 -0
  175. package/lib/download/core/pictureExport.d.ts.map +1 -0
  176. package/lib/download/core/pictureExport.js +116 -0
  177. package/lib/download/core/pictureExport.js.map +1 -0
  178. package/lib/download/core/stackedDrawing.d.ts +36 -0
  179. package/lib/download/core/stackedDrawing.d.ts.map +1 -0
  180. package/lib/download/core/stackedDrawing.js +98 -0
  181. package/lib/download/core/stackedDrawing.js.map +1 -0
  182. package/lib/download/core/svgBounds.d.ts +44 -0
  183. package/lib/download/core/svgBounds.d.ts.map +1 -0
  184. package/lib/download/core/svgBounds.js +69 -0
  185. package/lib/download/core/svgBounds.js.map +1 -0
  186. package/lib/download/core/svgNamespace.d.ts +9 -0
  187. package/lib/download/core/svgNamespace.d.ts.map +1 -0
  188. package/lib/download/core/svgNamespace.js +10 -0
  189. package/lib/download/core/svgNamespace.js.map +1 -0
  190. package/lib/download/core/svgToPng.d.ts +43 -0
  191. package/lib/download/core/svgToPng.d.ts.map +1 -0
  192. package/lib/download/core/svgToPng.js +79 -0
  193. package/lib/download/core/svgToPng.js.map +1 -0
  194. package/lib/download/core/svgToString.d.ts +45 -0
  195. package/lib/download/core/svgToString.d.ts.map +1 -0
  196. package/lib/download/core/svgToString.js +58 -0
  197. package/lib/download/core/svgToString.js.map +1 -0
  198. package/lib/download/ui/ExportDialogFrame.d.ts +46 -0
  199. package/lib/download/ui/ExportDialogFrame.d.ts.map +1 -0
  200. package/lib/download/ui/ExportDialogFrame.js +24 -0
  201. package/lib/download/ui/ExportDialogFrame.js.map +1 -0
  202. package/lib/download/ui/ExportImageDialog.d.ts +47 -0
  203. package/lib/download/ui/ExportImageDialog.d.ts.map +1 -0
  204. package/lib/download/ui/ExportImageDialog.js +25 -0
  205. package/lib/download/ui/ExportImageDialog.js.map +1 -0
  206. package/lib/download/ui/ExportNameField.d.ts +29 -0
  207. package/lib/download/ui/ExportNameField.d.ts.map +1 -0
  208. package/lib/download/ui/ExportNameField.js +99 -0
  209. package/lib/download/ui/ExportNameField.js.map +1 -0
  210. package/lib/download/ui/ExportPictureSection.d.ts +38 -0
  211. package/lib/download/ui/ExportPictureSection.d.ts.map +1 -0
  212. package/lib/download/ui/ExportPictureSection.js +48 -0
  213. package/lib/download/ui/ExportPictureSection.js.map +1 -0
  214. package/lib/download/ui/index.d.ts +10 -0
  215. package/lib/download/ui/index.d.ts.map +1 -1
  216. package/lib/download/ui/index.js +5 -0
  217. package/lib/download/ui/index.js.map +1 -1
  218. package/lib/download/ui/useDrawingBox.d.ts +23 -0
  219. package/lib/download/ui/useDrawingBox.d.ts.map +1 -0
  220. package/lib/download/ui/useDrawingBox.js +21 -0
  221. package/lib/download/ui/useDrawingBox.js.map +1 -0
  222. package/lib/error/core/describeSource.d.ts +17 -0
  223. package/lib/error/core/describeSource.d.ts.map +1 -0
  224. package/lib/error/core/describeSource.js +19 -0
  225. package/lib/error/core/describeSource.js.map +1 -0
  226. package/lib/error/core/index.d.ts +1 -0
  227. package/lib/error/core/index.d.ts.map +1 -1
  228. package/lib/error/core/index.js +1 -0
  229. package/lib/error/core/index.js.map +1 -1
  230. package/lib/help/ui/HelpBody.d.ts +10 -1
  231. package/lib/help/ui/HelpBody.d.ts.map +1 -1
  232. package/lib/help/ui/HelpBody.js +24 -1
  233. package/lib/help/ui/HelpBody.js.map +1 -1
  234. package/lib/help/ui/index.d.ts +1 -1
  235. package/lib/help/ui/index.d.ts.map +1 -1
  236. package/lib/help/ui/index.js.map +1 -1
  237. package/lib/ir/core/analysisSpectra.d.ts +46 -0
  238. package/lib/ir/core/analysisSpectra.d.ts.map +1 -0
  239. package/lib/ir/core/analysisSpectra.js +187 -0
  240. package/lib/ir/core/analysisSpectra.js.map +1 -0
  241. package/lib/ir/core/assignBands.d.ts +83 -0
  242. package/lib/ir/core/assignBands.d.ts.map +1 -0
  243. package/lib/ir/core/assignBands.js +83 -0
  244. package/lib/ir/core/assignBands.js.map +1 -0
  245. package/lib/ir/core/bandAssignments.d.ts +47 -0
  246. package/lib/ir/core/bandAssignments.d.ts.map +1 -0
  247. package/lib/ir/core/bandAssignments.js +305 -0
  248. package/lib/ir/core/bandAssignments.js.map +1 -0
  249. package/lib/ir/core/bandLabelPlan.d.ts +93 -0
  250. package/lib/ir/core/bandLabelPlan.d.ts.map +1 -0
  251. package/lib/ir/core/bandLabelPlan.js +104 -0
  252. package/lib/ir/core/bandLabelPlan.js.map +1 -0
  253. package/lib/ir/core/detectIrFormat.d.ts +23 -0
  254. package/lib/ir/core/detectIrFormat.d.ts.map +1 -0
  255. package/lib/ir/core/detectIrFormat.js +133 -0
  256. package/lib/ir/core/detectIrFormat.js.map +1 -0
  257. package/lib/ir/core/downloadSpectra.d.ts +26 -0
  258. package/lib/ir/core/downloadSpectra.d.ts.map +1 -0
  259. package/lib/ir/core/downloadSpectra.js +37 -0
  260. package/lib/ir/core/downloadSpectra.js.map +1 -0
  261. package/lib/ir/core/fromJcamp.d.ts +35 -0
  262. package/lib/ir/core/fromJcamp.d.ts.map +1 -0
  263. package/lib/ir/core/fromJcamp.js +48 -0
  264. package/lib/ir/core/fromJcamp.js.map +1 -0
  265. package/lib/ir/core/fromSpc.d.ts +30 -0
  266. package/lib/ir/core/fromSpc.d.ts.map +1 -0
  267. package/lib/ir/core/fromSpc.js +40 -0
  268. package/lib/ir/core/fromSpc.js.map +1 -0
  269. package/lib/ir/core/index.d.ts +51 -0
  270. package/lib/ir/core/index.d.ts.map +1 -0
  271. package/lib/ir/core/index.js +35 -0
  272. package/lib/ir/core/index.js.map +1 -0
  273. package/lib/ir/core/irBand.d.ts +45 -0
  274. package/lib/ir/core/irBand.d.ts.map +1 -0
  275. package/lib/ir/core/irBand.js +30 -0
  276. package/lib/ir/core/irBand.js.map +1 -0
  277. package/lib/ir/core/irCommands.d.ts +168 -0
  278. package/lib/ir/core/irCommands.d.ts.map +1 -0
  279. package/lib/ir/core/irCommands.js +94 -0
  280. package/lib/ir/core/irCommands.js.map +1 -0
  281. package/lib/ir/core/irDomain.d.ts +63 -0
  282. package/lib/ir/core/irDomain.d.ts.map +1 -0
  283. package/lib/ir/core/irDomain.js +136 -0
  284. package/lib/ir/core/irDomain.js.map +1 -0
  285. package/lib/ir/core/irEditorApi.d.ts +42 -0
  286. package/lib/ir/core/irEditorApi.d.ts.map +1 -0
  287. package/lib/ir/core/irEditorApi.js +10 -0
  288. package/lib/ir/core/irEditorApi.js.map +1 -0
  289. package/lib/ir/core/irFormat.d.ts +42 -0
  290. package/lib/ir/core/irFormat.d.ts.map +1 -0
  291. package/lib/ir/core/irFormat.js +51 -0
  292. package/lib/ir/core/irFormat.js.map +1 -0
  293. package/lib/ir/core/irMode.d.ts +160 -0
  294. package/lib/ir/core/irMode.d.ts.map +1 -0
  295. package/lib/ir/core/irMode.js +175 -0
  296. package/lib/ir/core/irMode.js.map +1 -0
  297. package/lib/ir/core/irReducer.d.ts +101 -0
  298. package/lib/ir/core/irReducer.d.ts.map +1 -0
  299. package/lib/ir/core/irReducer.js +207 -0
  300. package/lib/ir/core/irReducer.js.map +1 -0
  301. package/lib/ir/core/irSidePanels.d.ts +22 -0
  302. package/lib/ir/core/irSidePanels.d.ts.map +1 -0
  303. package/lib/ir/core/irSidePanels.js +12 -0
  304. package/lib/ir/core/irSidePanels.js.map +1 -0
  305. package/lib/ir/core/irSpectrum.d.ts +140 -0
  306. package/lib/ir/core/irSpectrum.d.ts.map +1 -0
  307. package/lib/ir/core/irSpectrum.js +34 -0
  308. package/lib/ir/core/irSpectrum.js.map +1 -0
  309. package/lib/ir/core/irState.d.ts +119 -0
  310. package/lib/ir/core/irState.d.ts.map +1 -0
  311. package/lib/ir/core/irState.js +92 -0
  312. package/lib/ir/core/irState.js.map +1 -0
  313. package/lib/ir/core/loadIrSpectra.d.ts +36 -0
  314. package/lib/ir/core/loadIrSpectra.d.ts.map +1 -0
  315. package/lib/ir/core/loadIrSpectra.js +44 -0
  316. package/lib/ir/core/loadIrSpectra.js.map +1 -0
  317. package/lib/ir/core/nearestBand.d.ts +35 -0
  318. package/lib/ir/core/nearestBand.d.ts.map +1 -0
  319. package/lib/ir/core/nearestBand.js +47 -0
  320. package/lib/ir/core/nearestBand.js.map +1 -0
  321. package/lib/ir/core/pickBands.d.ts +70 -0
  322. package/lib/ir/core/pickBands.d.ts.map +1 -0
  323. package/lib/ir/core/pickBands.js +125 -0
  324. package/lib/ir/core/pickBands.js.map +1 -0
  325. package/lib/ir/core/spectrumJcamp.d.ts +58 -0
  326. package/lib/ir/core/spectrumJcamp.d.ts.map +1 -0
  327. package/lib/ir/core/spectrumJcamp.js +156 -0
  328. package/lib/ir/core/spectrumJcamp.js.map +1 -0
  329. package/lib/ir/core/toIrSpectrum.d.ts +59 -0
  330. package/lib/ir/core/toIrSpectrum.d.ts.map +1 -0
  331. package/lib/ir/core/toIrSpectrum.js +56 -0
  332. package/lib/ir/core/toIrSpectrum.js.map +1 -0
  333. package/lib/ir/ui/BandMarks.d.ts +52 -0
  334. package/lib/ir/ui/BandMarks.d.ts.map +1 -0
  335. package/lib/ir/ui/BandMarks.js +71 -0
  336. package/lib/ir/ui/BandMarks.js.map +1 -0
  337. package/lib/ir/ui/BandsPanel.d.ts +31 -0
  338. package/lib/ir/ui/BandsPanel.d.ts.map +1 -0
  339. package/lib/ir/ui/BandsPanel.js +94 -0
  340. package/lib/ir/ui/BandsPanel.js.map +1 -0
  341. package/lib/ir/ui/IrAboutDialog.d.ts +18 -0
  342. package/lib/ir/ui/IrAboutDialog.d.ts.map +1 -0
  343. package/lib/ir/ui/IrAboutDialog.js +32 -0
  344. package/lib/ir/ui/IrAboutDialog.js.map +1 -0
  345. package/lib/ir/ui/IrCanvas.d.ts +38 -0
  346. package/lib/ir/ui/IrCanvas.d.ts.map +1 -0
  347. package/lib/ir/ui/IrCanvas.js +41 -0
  348. package/lib/ir/ui/IrCanvas.js.map +1 -0
  349. package/lib/ir/ui/IrChart.d.ts +28 -0
  350. package/lib/ir/ui/IrChart.d.ts.map +1 -0
  351. package/lib/ir/ui/IrChart.js +114 -0
  352. package/lib/ir/ui/IrChart.js.map +1 -0
  353. package/lib/ir/ui/IrCommandProvider.d.ts +15 -0
  354. package/lib/ir/ui/IrCommandProvider.d.ts.map +1 -0
  355. package/lib/ir/ui/IrCommandProvider.js +14 -0
  356. package/lib/ir/ui/IrCommandProvider.js.map +1 -0
  357. package/lib/ir/ui/IrCommandTooltip.d.ts +16 -0
  358. package/lib/ir/ui/IrCommandTooltip.d.ts.map +1 -0
  359. package/lib/ir/ui/IrCommandTooltip.js +22 -0
  360. package/lib/ir/ui/IrCommandTooltip.js.map +1 -0
  361. package/lib/ir/ui/IrDocumentationDialog.d.ts +18 -0
  362. package/lib/ir/ui/IrDocumentationDialog.d.ts.map +1 -0
  363. package/lib/ir/ui/IrDocumentationDialog.js +68 -0
  364. package/lib/ir/ui/IrDocumentationDialog.js.map +1 -0
  365. package/lib/ir/ui/IrEditor.d.ts +60 -0
  366. package/lib/ir/ui/IrEditor.d.ts.map +1 -0
  367. package/lib/ir/ui/IrEditor.js +42 -0
  368. package/lib/ir/ui/IrEditor.js.map +1 -0
  369. package/lib/ir/ui/IrHeader.d.ts +13 -0
  370. package/lib/ir/ui/IrHeader.d.ts.map +1 -0
  371. package/lib/ir/ui/IrHeader.js +21 -0
  372. package/lib/ir/ui/IrHeader.js.map +1 -0
  373. package/lib/ir/ui/IrLogo.d.ts +20 -0
  374. package/lib/ir/ui/IrLogo.d.ts.map +1 -0
  375. package/lib/ir/ui/IrLogo.js +17 -0
  376. package/lib/ir/ui/IrLogo.js.map +1 -0
  377. package/lib/ir/ui/IrPointerTracker.d.ts +29 -0
  378. package/lib/ir/ui/IrPointerTracker.d.ts.map +1 -0
  379. package/lib/ir/ui/IrPointerTracker.js +47 -0
  380. package/lib/ir/ui/IrPointerTracker.js.map +1 -0
  381. package/lib/ir/ui/IrShell.d.ts +25 -0
  382. package/lib/ir/ui/IrShell.d.ts.map +1 -0
  383. package/lib/ir/ui/IrShell.js +178 -0
  384. package/lib/ir/ui/IrShell.js.map +1 -0
  385. package/lib/ir/ui/IrSidePanel.d.ts +26 -0
  386. package/lib/ir/ui/IrSidePanel.d.ts.map +1 -0
  387. package/lib/ir/ui/IrSidePanel.js +39 -0
  388. package/lib/ir/ui/IrSidePanel.js.map +1 -0
  389. package/lib/ir/ui/IrStateProvider.d.ts +19 -0
  390. package/lib/ir/ui/IrStateProvider.d.ts.map +1 -0
  391. package/lib/ir/ui/IrStateProvider.js +16 -0
  392. package/lib/ir/ui/IrStateProvider.js.map +1 -0
  393. package/lib/ir/ui/IrStatusBar.d.ts +14 -0
  394. package/lib/ir/ui/IrStatusBar.d.ts.map +1 -0
  395. package/lib/ir/ui/IrStatusBar.js +48 -0
  396. package/lib/ir/ui/IrStatusBar.js.map +1 -0
  397. package/lib/ir/ui/IrToolbar.d.ts +18 -0
  398. package/lib/ir/ui/IrToolbar.d.ts.map +1 -0
  399. package/lib/ir/ui/IrToolbar.js +32 -0
  400. package/lib/ir/ui/IrToolbar.js.map +1 -0
  401. package/lib/ir/ui/IrTraces.d.ts +63 -0
  402. package/lib/ir/ui/IrTraces.d.ts.map +1 -0
  403. package/lib/ir/ui/IrTraces.js +72 -0
  404. package/lib/ir/ui/IrTraces.js.map +1 -0
  405. package/lib/ir/ui/MetadataPanel.d.ts +15 -0
  406. package/lib/ir/ui/MetadataPanel.d.ts.map +1 -0
  407. package/lib/ir/ui/MetadataPanel.js +49 -0
  408. package/lib/ir/ui/MetadataPanel.js.map +1 -0
  409. package/lib/ir/ui/SpectraPanel.d.ts +20 -0
  410. package/lib/ir/ui/SpectraPanel.d.ts.map +1 -0
  411. package/lib/ir/ui/SpectraPanel.js +42 -0
  412. package/lib/ir/ui/SpectraPanel.js.map +1 -0
  413. package/lib/ir/ui/SpectrumRow.d.ts +26 -0
  414. package/lib/ir/ui/SpectrumRow.d.ts.map +1 -0
  415. package/lib/ir/ui/SpectrumRow.js +41 -0
  416. package/lib/ir/ui/SpectrumRow.js.map +1 -0
  417. package/lib/ir/ui/index.d.ts +56 -0
  418. package/lib/ir/ui/index.d.ts.map +1 -0
  419. package/lib/ir/ui/index.js +36 -0
  420. package/lib/ir/ui/index.js.map +1 -0
  421. package/lib/ir/ui/irActions.d.ts +52 -0
  422. package/lib/ir/ui/irActions.d.ts.map +1 -0
  423. package/lib/ir/ui/irActions.js +62 -0
  424. package/lib/ir/ui/irActions.js.map +1 -0
  425. package/lib/ir/ui/irChartProps.d.ts +116 -0
  426. package/lib/ir/ui/irChartProps.d.ts.map +1 -0
  427. package/lib/ir/ui/irChartProps.js +14 -0
  428. package/lib/ir/ui/irChartProps.js.map +1 -0
  429. package/lib/ir/ui/irCommandContext.d.ts +35 -0
  430. package/lib/ir/ui/irCommandContext.d.ts.map +1 -0
  431. package/lib/ir/ui/irCommandContext.js +44 -0
  432. package/lib/ir/ui/irCommandContext.js.map +1 -0
  433. package/lib/ir/ui/irStateContext.d.ts +26 -0
  434. package/lib/ir/ui/irStateContext.d.ts.map +1 -0
  435. package/lib/ir/ui/irStateContext.js +37 -0
  436. package/lib/ir/ui/irStateContext.js.map +1 -0
  437. package/lib/ir/ui/useIrEditor.d.ts +51 -0
  438. package/lib/ir/ui/useIrEditor.d.ts.map +1 -0
  439. package/lib/ir/ui/useIrEditor.js +88 -0
  440. package/lib/ir/ui/useIrEditor.js.map +1 -0
  441. package/lib/ir/ui/useIrPointer.d.ts +66 -0
  442. package/lib/ir/ui/useIrPointer.d.ts.map +1 -0
  443. package/lib/ir/ui/useIrPointer.js +53 -0
  444. package/lib/ir/ui/useIrPointer.js.map +1 -0
  445. package/lib/ir/ui/useIrShortcuts.d.ts +24 -0
  446. package/lib/ir/ui/useIrShortcuts.d.ts.map +1 -0
  447. package/lib/ir/ui/useIrShortcuts.js +73 -0
  448. package/lib/ir/ui/useIrShortcuts.js.map +1 -0
  449. package/lib/ir/ui/useIrZoom.d.ts +51 -0
  450. package/lib/ir/ui/useIrZoom.d.ts.map +1 -0
  451. package/lib/ir/ui/useIrZoom.js +46 -0
  452. package/lib/ir/ui/useIrZoom.js.map +1 -0
  453. package/lib/ir.d.ts +13 -0
  454. package/lib/ir.d.ts.map +1 -0
  455. package/lib/ir.js +13 -0
  456. package/lib/ir.js.map +1 -0
  457. package/lib/panel/core/dialogStyles.d.ts +13 -0
  458. package/lib/panel/core/dialogStyles.d.ts.map +1 -0
  459. package/lib/panel/core/dialogStyles.js +11 -0
  460. package/lib/panel/core/dialogStyles.js.map +1 -0
  461. package/lib/panel/core/index.d.ts +19 -0
  462. package/lib/panel/core/index.d.ts.map +1 -0
  463. package/lib/panel/core/index.js +18 -0
  464. package/lib/panel/core/index.js.map +1 -0
  465. package/lib/panel/core/isEditingField.d.ts +17 -0
  466. package/lib/panel/core/isEditingField.d.ts.map +1 -0
  467. package/lib/panel/core/isEditingField.js +25 -0
  468. package/lib/panel/core/isEditingField.js.map +1 -0
  469. package/lib/panel/core/panelStyles.d.ts +242 -0
  470. package/lib/panel/core/panelStyles.d.ts.map +1 -0
  471. package/lib/panel/core/panelStyles.js +228 -0
  472. package/lib/panel/core/panelStyles.js.map +1 -0
  473. package/lib/panel/core/rowSpacers.d.ts +38 -0
  474. package/lib/panel/core/rowSpacers.d.ts.map +1 -0
  475. package/lib/panel/core/rowSpacers.js +31 -0
  476. package/lib/panel/core/rowSpacers.js.map +1 -0
  477. package/lib/panel/core/statusBar.d.ts +44 -0
  478. package/lib/panel/core/statusBar.d.ts.map +1 -0
  479. package/lib/panel/core/statusBar.js +40 -0
  480. package/lib/panel/core/statusBar.js.map +1 -0
  481. package/lib/panel/core/textFilter.d.ts +22 -0
  482. package/lib/panel/core/textFilter.d.ts.map +1 -0
  483. package/lib/panel/core/textFilter.js +32 -0
  484. package/lib/panel/core/textFilter.js.map +1 -0
  485. package/lib/panel/core/yieldToPainting.d.ts +17 -0
  486. package/lib/panel/core/yieldToPainting.d.ts.map +1 -0
  487. package/lib/panel/core/yieldToPainting.js +21 -0
  488. package/lib/panel/core/yieldToPainting.js.map +1 -0
  489. package/lib/panel/ui/AboutDialogFrame.d.ts +36 -0
  490. package/lib/panel/ui/AboutDialogFrame.d.ts.map +1 -0
  491. package/lib/panel/ui/AboutDialogFrame.js +43 -0
  492. package/lib/panel/ui/AboutDialogFrame.js.map +1 -0
  493. package/lib/panel/ui/ClearButton.d.ts +28 -0
  494. package/lib/panel/ui/ClearButton.d.ts.map +1 -0
  495. package/lib/panel/ui/ClearButton.js +23 -0
  496. package/lib/panel/ui/ClearButton.js.map +1 -0
  497. package/lib/panel/ui/DocumentationDialogFrame.d.ts +39 -0
  498. package/lib/panel/ui/DocumentationDialogFrame.d.ts.map +1 -0
  499. package/lib/panel/ui/DocumentationDialogFrame.js +29 -0
  500. package/lib/panel/ui/DocumentationDialogFrame.js.map +1 -0
  501. package/lib/panel/ui/FilterInput.d.ts +31 -0
  502. package/lib/panel/ui/FilterInput.d.ts.map +1 -0
  503. package/lib/panel/ui/FilterInput.js +23 -0
  504. package/lib/panel/ui/FilterInput.js.map +1 -0
  505. package/lib/panel/ui/HelpLabel.d.ts +24 -0
  506. package/lib/panel/ui/HelpLabel.d.ts.map +1 -0
  507. package/lib/panel/ui/HelpLabel.js +23 -0
  508. package/lib/panel/ui/HelpLabel.js.map +1 -0
  509. package/lib/panel/ui/PanelMessage.d.ts +41 -0
  510. package/lib/panel/ui/PanelMessage.d.ts.map +1 -0
  511. package/lib/panel/ui/PanelMessage.js +30 -0
  512. package/lib/panel/ui/PanelMessage.js.map +1 -0
  513. package/lib/panel/ui/PanelRail.d.ts +41 -0
  514. package/lib/panel/ui/PanelRail.d.ts.map +1 -0
  515. package/lib/panel/ui/PanelRail.js +12 -0
  516. package/lib/panel/ui/PanelRail.js.map +1 -0
  517. package/lib/panel/ui/Section.d.ts +25 -0
  518. package/lib/panel/ui/Section.d.ts.map +1 -0
  519. package/lib/panel/ui/Section.js +41 -0
  520. package/lib/panel/ui/Section.js.map +1 -0
  521. package/lib/panel/ui/SidePanelStack.d.ts +62 -0
  522. package/lib/panel/ui/SidePanelStack.d.ts.map +1 -0
  523. package/lib/panel/ui/SidePanelStack.js +40 -0
  524. package/lib/panel/ui/SidePanelStack.js.map +1 -0
  525. package/lib/panel/ui/SpectrumColorSwatch.d.ts +33 -0
  526. package/lib/panel/ui/SpectrumColorSwatch.d.ts.map +1 -0
  527. package/lib/panel/ui/SpectrumColorSwatch.js +76 -0
  528. package/lib/panel/ui/SpectrumColorSwatch.js.map +1 -0
  529. package/lib/panel/ui/index.d.ts +37 -0
  530. package/lib/panel/ui/index.d.ts.map +1 -0
  531. package/lib/panel/ui/index.js +24 -0
  532. package/lib/panel/ui/index.js.map +1 -0
  533. package/lib/panel/ui/useConfirmOnEnter.d.ts +19 -0
  534. package/lib/panel/ui/useConfirmOnEnter.d.ts.map +1 -0
  535. package/lib/panel/ui/useConfirmOnEnter.js +64 -0
  536. package/lib/panel/ui/useConfirmOnEnter.js.map +1 -0
  537. package/lib/panel/ui/useFilterBox.d.ts +23 -0
  538. package/lib/panel/ui/useFilterBox.d.ts.map +1 -0
  539. package/lib/panel/ui/useFilterBox.js +22 -0
  540. package/lib/panel/ui/useFilterBox.js.map +1 -0
  541. package/lib/panel/ui/useVirtualRows.d.ts +46 -0
  542. package/lib/panel/ui/useVirtualRows.d.ts.map +1 -0
  543. package/lib/panel/ui/useVirtualRows.js +56 -0
  544. package/lib/panel/ui/useVirtualRows.js.map +1 -0
  545. package/lib/panel/ui/useVirtualWindowRows.d.ts +40 -0
  546. package/lib/panel/ui/useVirtualWindowRows.d.ts.map +1 -0
  547. package/lib/panel/ui/useVirtualWindowRows.js +65 -0
  548. package/lib/panel/ui/useVirtualWindowRows.js.map +1 -0
  549. package/lib/ui.d.ts +1 -0
  550. package/lib/ui.d.ts.map +1 -1
  551. package/lib/ui.js +1 -0
  552. package/lib/ui.js.map +1 -1
  553. package/package.json +8 -1
  554. package/src/chart/core/axisLabels.ts +117 -0
  555. package/src/chart/core/boxLayout.ts +126 -0
  556. package/src/chart/core/chartAxisScale.ts +92 -10
  557. package/src/chart/core/chartDomain.ts +185 -0
  558. package/src/chart/core/chartGeometry.ts +159 -0
  559. package/src/chart/core/chartPane.ts +10 -0
  560. package/src/chart/core/chartScale.ts +7 -4
  561. package/src/chart/core/chartTheme.ts +161 -0
  562. package/src/chart/core/chartViewport.ts +40 -13
  563. package/src/chart/core/guidePlacement.ts +66 -0
  564. package/src/chart/core/index.ts +121 -2
  565. package/src/chart/core/labelStack.ts +72 -0
  566. package/src/chart/core/legendBox.ts +263 -0
  567. package/src/chart/core/selectionGeometry.ts +68 -0
  568. package/src/chart/core/spectrumColor.ts +129 -0
  569. package/src/chart/core/stackCapacity.ts +162 -0
  570. package/src/chart/core/svgPoint.ts +77 -0
  571. package/src/chart/core/tracePath.ts +228 -0
  572. package/src/chart/core/trackerReadout.ts +78 -0
  573. package/src/chart/core/viewTransform.ts +287 -0
  574. package/src/chart/core/zoomDomain.ts +235 -0
  575. package/src/chart/ui/Axes.tsx +361 -0
  576. package/src/chart/ui/AxisGuide.tsx +187 -0
  577. package/src/chart/ui/ChartStack.tsx +130 -0
  578. package/src/chart/ui/ChartTracker.tsx +101 -0
  579. package/src/chart/ui/PlotCaption.tsx +108 -0
  580. package/src/chart/ui/SelectionRect.tsx +52 -0
  581. package/src/chart/ui/TraceLegend.tsx +193 -0
  582. package/src/chart/ui/chartGestures.ts +270 -0
  583. package/src/chart/ui/chartStackLevel.tsx +210 -0
  584. package/src/chart/ui/chartSurface.ts +66 -0
  585. package/src/chart/ui/index.ts +35 -0
  586. package/src/chart/ui/useChartPointer.ts +223 -0
  587. package/src/chart/ui/useChartSize.ts +115 -0
  588. package/src/chart/ui/useChartWindow.ts +240 -0
  589. package/src/chart/ui/useChartZoom.ts +255 -0
  590. package/src/chart/ui/useWheelListener.ts +62 -0
  591. package/src/clipboard/core/copyPng.ts +20 -0
  592. package/src/clipboard/core/index.ts +1 -0
  593. package/src/core.ts +1 -0
  594. package/src/download/core/exportStyles.ts +20 -0
  595. package/src/download/core/imageResolution.ts +118 -0
  596. package/src/download/core/index.ts +34 -0
  597. package/src/download/core/pictureExport.ts +207 -0
  598. package/src/download/core/stackedDrawing.ts +108 -0
  599. package/src/download/core/svgBounds.ts +80 -0
  600. package/src/download/core/svgNamespace.ts +9 -0
  601. package/src/download/core/svgToPng.ts +121 -0
  602. package/src/download/core/svgToString.ts +95 -0
  603. package/src/download/ui/ExportDialogFrame.tsx +86 -0
  604. package/src/download/ui/ExportImageDialog.tsx +91 -0
  605. package/src/download/ui/ExportNameField.tsx +148 -0
  606. package/src/download/ui/ExportPictureSection.tsx +142 -0
  607. package/src/download/ui/index.ts +11 -0
  608. package/src/download/ui/useDrawingBox.ts +37 -0
  609. package/src/error/core/describeSource.ts +18 -0
  610. package/src/error/core/index.ts +1 -0
  611. package/src/help/ui/HelpBody.tsx +41 -2
  612. package/src/help/ui/index.ts +6 -1
  613. package/src/ir/core/analysisSpectra.ts +231 -0
  614. package/src/ir/core/assignBands.ts +144 -0
  615. package/src/ir/core/bandAssignments.ts +329 -0
  616. package/src/ir/core/bandLabelPlan.ts +194 -0
  617. package/src/ir/core/detectIrFormat.ts +139 -0
  618. package/src/ir/core/downloadSpectra.ts +57 -0
  619. package/src/ir/core/fromJcamp.ts +70 -0
  620. package/src/ir/core/fromSpc.ts +61 -0
  621. package/src/ir/core/index.ts +113 -0
  622. package/src/ir/core/irBand.ts +57 -0
  623. package/src/ir/core/irCommands.ts +154 -0
  624. package/src/ir/core/irDomain.ts +163 -0
  625. package/src/ir/core/irEditorApi.ts +44 -0
  626. package/src/ir/core/irFormat.ts +57 -0
  627. package/src/ir/core/irMode.ts +203 -0
  628. package/src/ir/core/irReducer.ts +273 -0
  629. package/src/ir/core/irSidePanels.ts +20 -0
  630. package/src/ir/core/irSpectrum.ts +155 -0
  631. package/src/ir/core/irState.ts +173 -0
  632. package/src/ir/core/loadIrSpectra.ts +79 -0
  633. package/src/ir/core/nearestBand.ts +57 -0
  634. package/src/ir/core/pickBands.ts +181 -0
  635. package/src/ir/core/spectrumJcamp.ts +178 -0
  636. package/src/ir/core/toIrSpectrum.ts +102 -0
  637. package/src/ir/ui/BandMarks.tsx +166 -0
  638. package/src/ir/ui/BandsPanel.tsx +271 -0
  639. package/src/ir/ui/IrAboutDialog.tsx +121 -0
  640. package/src/ir/ui/IrCanvas.tsx +91 -0
  641. package/src/ir/ui/IrChart.tsx +215 -0
  642. package/src/ir/ui/IrCommandProvider.tsx +32 -0
  643. package/src/ir/ui/IrCommandTooltip.tsx +36 -0
  644. package/src/ir/ui/IrDocumentationDialog.tsx +174 -0
  645. package/src/ir/ui/IrEditor.tsx +99 -0
  646. package/src/ir/ui/IrHeader.tsx +39 -0
  647. package/src/ir/ui/IrLogo.tsx +49 -0
  648. package/src/ir/ui/IrPointerTracker.tsx +102 -0
  649. package/src/ir/ui/IrShell.tsx +285 -0
  650. package/src/ir/ui/IrSidePanel.tsx +78 -0
  651. package/src/ir/ui/IrStateProvider.tsx +32 -0
  652. package/src/ir/ui/IrStatusBar.tsx +97 -0
  653. package/src/ir/ui/IrToolbar.tsx +102 -0
  654. package/src/ir/ui/IrTraces.tsx +134 -0
  655. package/src/ir/ui/MetadataPanel.tsx +88 -0
  656. package/src/ir/ui/SpectraPanel.tsx +114 -0
  657. package/src/ir/ui/SpectrumRow.tsx +127 -0
  658. package/src/ir/ui/index.ts +56 -0
  659. package/src/ir/ui/irActions.ts +103 -0
  660. package/src/ir/ui/irChartProps.ts +118 -0
  661. package/src/ir/ui/irCommandContext.tsx +62 -0
  662. package/src/ir/ui/irStateContext.ts +48 -0
  663. package/src/ir/ui/useIrEditor.ts +139 -0
  664. package/src/ir/ui/useIrPointer.ts +109 -0
  665. package/src/ir/ui/useIrShortcuts.ts +95 -0
  666. package/src/ir/ui/useIrZoom.ts +86 -0
  667. package/src/ir.ts +13 -0
  668. package/src/panel/core/dialogStyles.ts +11 -0
  669. package/src/panel/core/index.ts +47 -0
  670. package/src/panel/core/isEditingField.ts +23 -0
  671. package/src/panel/core/panelStyles.ts +248 -0
  672. package/src/panel/core/rowSpacers.ts +50 -0
  673. package/src/panel/core/statusBar.ts +48 -0
  674. package/src/panel/core/textFilter.ts +33 -0
  675. package/src/panel/core/yieldToPainting.ts +20 -0
  676. package/src/panel/ui/AboutDialogFrame.tsx +100 -0
  677. package/src/panel/ui/ClearButton.tsx +42 -0
  678. package/src/panel/ui/DocumentationDialogFrame.tsx +86 -0
  679. package/src/panel/ui/FilterInput.tsx +60 -0
  680. package/src/panel/ui/HelpLabel.tsx +43 -0
  681. package/src/panel/ui/PanelMessage.tsx +64 -0
  682. package/src/panel/ui/PanelRail.tsx +64 -0
  683. package/src/panel/ui/Section.tsx +66 -0
  684. package/src/panel/ui/SidePanelStack.tsx +109 -0
  685. package/src/panel/ui/SpectrumColorSwatch.tsx +119 -0
  686. package/src/panel/ui/index.ts +47 -0
  687. package/src/panel/ui/useConfirmOnEnter.ts +68 -0
  688. package/src/panel/ui/useFilterBox.ts +35 -0
  689. package/src/panel/ui/useVirtualRows.ts +82 -0
  690. package/src/panel/ui/useVirtualWindowRows.ts +86 -0
  691. package/src/ui.ts +1 -0
@@ -0,0 +1,361 @@
1
+ import type { ReactElement } from 'react';
2
+ import { useMemo } from 'react';
3
+
4
+ import { axisLabeller } from '../core/axisLabels.ts';
5
+ import type { ChartAxisScale } from '../core/chartAxisScale.ts';
6
+ import { chartAxisScale } from '../core/chartAxisScale.ts';
7
+ import type { PlotRect } from '../core/chartGeometry.ts';
8
+ import type { ChartScale } from '../core/chartScale.ts';
9
+ import { chartPixel } from '../core/chartScale.ts';
10
+ import { CHART_COLORS, CHART_FONT } from '../core/chartTheme.ts';
11
+
12
+ export interface AxesProps {
13
+ /** Where the plot sits inside the SVG. */
14
+ plot: PlotRect;
15
+ /** The window on screen, which the ticks along the bottom are chosen for. */
16
+ xDomain: readonly [number, number];
17
+ /** The window on screen, which the ticks up the side are chosen for. */
18
+ yDomain: readonly [number, number];
19
+ /**
20
+ * The horizontal axis as it is currently zoomed. A scale built onto a
21
+ * reversed pixel range is drawn reversed with no further ceremony, which is
22
+ * what an infrared spectrum running from 4000 down to 400 needs.
23
+ */
24
+ xScale: ChartScale;
25
+ /** The vertical axis as it is currently zoomed. */
26
+ yScale: ChartScale;
27
+ /**
28
+ * Whether the vertical labels are written by magnitude, so the half below
29
+ * the rule reads `100 50 0 50 100` rather than `-100 -50 0 50 100`. What the
30
+ * lower half of a mirrored pair means is a second spectrum drawn downwards,
31
+ * never a negative value, and a minus sign in front of every one of its
32
+ * labels says otherwise.
33
+ * @default false
34
+ */
35
+ absYTicks?: boolean;
36
+ /**
37
+ * Whether the numbers along the bottom are written.
38
+ *
39
+ * Panes stacked over one window would each repeat `2.5 5.0 7.5` and spend a
40
+ * tick row of height on it, so only the pane at the foot writes them. The
41
+ * grid and the axis line stay — they are what a peak's height is read against.
42
+ * @default true
43
+ */
44
+ showXTicks?: boolean;
45
+ /**
46
+ * Whether the name of the horizontal axis is written under it.
47
+ *
48
+ * Separate from `showXTicks` because the two go at different moments — a pane
49
+ * above the foot of a stack keeps neither, a chart in a narrow panel keeps its
50
+ * numbers. `xTitle` stays required either way: which pane is the foot changes.
51
+ * @default true
52
+ */
53
+ showXTitle?: boolean;
54
+ /**
55
+ * What the horizontal axis is called — `m/z`, `wavenumber (cm⁻¹)`.
56
+ *
57
+ * Required rather than defaulted, because there is no name that is right for
58
+ * every spectrum and a default would be one viewer's units silently drawn
59
+ * under another's data.
60
+ */
61
+ xTitle: string;
62
+ /** What the vertical axis is called — `intensity`, `absorbance`, `%T`. */
63
+ yTitle: string;
64
+ /**
65
+ * How much room one label along the bottom is given, in pixels.
66
+ *
67
+ * The default is the width of the widest number a spectrum axis writes — a
68
+ * mass at four decimals — so that a chart in a narrow panel carries three
69
+ * labels rather than six run together. A chart whose numbers are known to be
70
+ * short says so and gets more of them: a fixed axis over a few hundred mass
71
+ * units writes `400 600 800`, and at the default spacing a column that narrow
72
+ * is given a single tick, which says nothing about the range at all.
73
+ * @default 90
74
+ */
75
+ xTickSpacing?: number;
76
+ /**
77
+ * How much room one label up the side is given, in pixels.
78
+ * @default 44
79
+ */
80
+ yTickSpacing?: number;
81
+ }
82
+
83
+ /**
84
+ * The frame the spectra are read against: two axis lines, a grid, and titles.
85
+ *
86
+ * The ticks are rules across the whole plot rather than dashes at its edge. A
87
+ * feature is read for its height against the ones around it — is this the base
88
+ * peak, is that band half of it — and a dash on the far left is a measuring
89
+ * stick nobody can lay across the peak they are looking at. The rules
90
+ * are drawn in the palest colour the theme carries and under the data band, so
91
+ * a grid line is never mistaken for a trace.
92
+ *
93
+ * Every number is written outside the plot, and every line inside it. That is
94
+ * what lets the data band be clipped without a label being cut in half, and it
95
+ * keeps the plot itself free for the only thing it is about.
96
+ *
97
+ * The axis pair is one L rather than a box: the top and the right of a spectrum
98
+ * are open, because a peak that runs out of the top is a peak the zoom has cut
99
+ * off, and a rule along the top would read as a ceiling the measurement stopped
100
+ * at.
101
+ *
102
+ * How many ticks there are follows the room there is for them — a chart in a
103
+ * narrow panel is given fewer, rather than the same six labels overprinting one
104
+ * another — and the precision each is written to comes from the step, so a
105
+ * window two millimass units wide is labelled to four decimals and a full scan
106
+ * to none. The notation is settled once per axis rather than per label, so an
107
+ * intensity axis running to two hundred million reads `5e+7 1e+8 1.5e+8 2e+8`
108
+ * and not a column of nine digits the title has to be read around.
109
+ * @param props - Component props.
110
+ * @returns The axes, as SVG.
111
+ */
112
+ export function Axes(props: AxesProps): ReactElement {
113
+ const {
114
+ plot,
115
+ xDomain,
116
+ yDomain,
117
+ xScale,
118
+ yScale,
119
+ absYTicks = false,
120
+ showXTicks = true,
121
+ showXTitle = true,
122
+ xTitle,
123
+ yTitle,
124
+ xTickSpacing = X_TICK_SPACING,
125
+ yTickSpacing = Y_TICK_SPACING,
126
+ } = props;
127
+
128
+ const xTicks = useMemo(
129
+ () => spectrumAxis(xDomain, tickCount(plot.width, xTickSpacing)),
130
+ [xDomain, plot.width, xTickSpacing],
131
+ );
132
+ const yTicks = useMemo(
133
+ () => spectrumAxis(yDomain, tickCount(plot.height, yTickSpacing)),
134
+ [yDomain, plot.height, yTickSpacing],
135
+ );
136
+ const writeXTick = useMemo(() => axisLabeller(xTicks), [xTicks]);
137
+ const writeYTick = useMemo(() => axisLabeller(yTicks), [yTicks]);
138
+
139
+ const middleX = plot.left + plot.width / 2;
140
+ const middleY = plot.top + plot.height / 2;
141
+ // Beside the numbers rather than in a fixed column at the edge of the margin.
142
+ // One gutter holds `100` on a spectrum and `1.5e+8` on a chromatogram, and a
143
+ // title pinned where the wider of the two would leave it stands twenty pixels
144
+ // clear of the narrower — far enough to read as naming the chart rather than
145
+ // the axis.
146
+ const titleColumn = useMemo(
147
+ () => valueTitleColumn(yTicks.values, writeYTick, absYTicks, plot.left),
148
+ [yTicks, writeYTick, absYTicks, plot.left],
149
+ );
150
+ // The rule a mirrored pair is reflected in only exists while both halves are
151
+ // on screen; on an ordinary chart zero is the baseline and already drawn.
152
+ const zero = chartPixel(yScale, 0);
153
+ const showsZeroRule = yDomain[0] < 0 && yDomain[1] > 0;
154
+
155
+ return (
156
+ <g pointerEvents="none">
157
+ {xTicks.values.map((tick) => (
158
+ <line
159
+ key={tick}
160
+ x1={chartPixel(xScale, tick)}
161
+ y1={plot.top}
162
+ x2={chartPixel(xScale, tick)}
163
+ y2={plot.bottom}
164
+ style={gridStyle}
165
+ />
166
+ ))}
167
+ {yTicks.values.map((tick) => (
168
+ <line
169
+ key={tick}
170
+ x1={plot.left}
171
+ y1={chartPixel(yScale, tick)}
172
+ x2={plot.right}
173
+ y2={chartPixel(yScale, tick)}
174
+ style={gridStyle}
175
+ />
176
+ ))}
177
+ {showsZeroRule ? (
178
+ <line
179
+ x1={plot.left}
180
+ y1={zero}
181
+ x2={plot.right}
182
+ y2={zero}
183
+ style={zeroRuleStyle}
184
+ />
185
+ ) : null}
186
+ <path
187
+ d={`M${plot.left} ${plot.top}V${plot.bottom}H${plot.right}`}
188
+ fill="none"
189
+ style={axisStyle}
190
+ />
191
+ {showXTicks &&
192
+ xTicks.values.map((tick) => (
193
+ <text
194
+ key={tick}
195
+ x={chartPixel(xScale, tick)}
196
+ y={plot.bottom + TICK_LABEL_GAP}
197
+ textAnchor="middle"
198
+ dominantBaseline="hanging"
199
+ style={tickStyle}
200
+ >
201
+ {writeXTick(tick)}
202
+ </text>
203
+ ))}
204
+ {yTicks.values.map((tick) => (
205
+ <text
206
+ key={tick}
207
+ x={plot.left - TICK_LABEL_GAP}
208
+ y={chartPixel(yScale, tick)}
209
+ textAnchor="end"
210
+ dominantBaseline="central"
211
+ style={tickStyle}
212
+ >
213
+ {writeYTick(absYTicks ? Math.abs(tick) : tick)}
214
+ </text>
215
+ ))}
216
+ {showXTitle && (
217
+ <text
218
+ x={middleX}
219
+ y={plot.bottom + TITLE_GAP}
220
+ textAnchor="middle"
221
+ dominantBaseline="hanging"
222
+ style={titleStyle}
223
+ >
224
+ {xTitle}
225
+ </text>
226
+ )}
227
+ <text
228
+ x={titleColumn}
229
+ y={middleY}
230
+ transform={`rotate(-90 ${titleColumn} ${middleY})`}
231
+ textAnchor="middle"
232
+ dominantBaseline="central"
233
+ style={titleStyle}
234
+ >
235
+ {yTitle}
236
+ </text>
237
+ </g>
238
+ );
239
+ }
240
+
241
+ /**
242
+ * The ticks of one axis of a chart a reader has zoomed for themselves.
243
+ *
244
+ * The window is exactly what the reader dragged out, so it is never widened to
245
+ * end on a round tick — an axis that jumped outward as the drag was released
246
+ * would show data the reader had just excluded. And the count is a budget
247
+ * worked out from the room the panel has, so the step is rounded up rather than
248
+ * to the nearest: one tick more than the room allows is two labels touching.
249
+ * @param domain - The window on screen, `[from, to]`.
250
+ * @param count - The most intervals the axis has room for.
251
+ * @returns The axis, divided.
252
+ */
253
+ function spectrumAxis(
254
+ domain: readonly [number, number],
255
+ count: number,
256
+ ): ChartAxisScale {
257
+ return chartAxisScale(domain[0], domain[1], {
258
+ count,
259
+ nice: false,
260
+ step: 'atMost',
261
+ });
262
+ }
263
+
264
+ /**
265
+ * How many intervals an axis of a given length has room to name.
266
+ *
267
+ * A label at a deep zoom is eight characters wide, so the spacings are the width
268
+ * of a label and not a fraction of the axis: a chart in a side panel then
269
+ * carries three labels rather than the same six run together.
270
+ * @param length - How long the axis is, in pixels.
271
+ * @param spacing - The room one label wants along it.
272
+ * @returns The number of intervals to aim for, never below two.
273
+ */
274
+ function tickCount(length: number, spacing: number): number {
275
+ return Math.max(2, Math.round(length / spacing));
276
+ }
277
+
278
+ /**
279
+ * Where the rotated value title stands, given the numbers it has to clear.
280
+ *
281
+ * The widest label is measured in characters rather than in pixels, because the
282
+ * chart has no font to measure against — `CHART_FONT` sets sizes and leaves the
283
+ * family to the host — and a rendered measurement would mean laying the text out
284
+ * and reading it back on every zoom.
285
+ * @param ticks - The ticks up the side, as `chartAxisScale` chose them.
286
+ * @param write - How this axis writes one of them.
287
+ * @param absolute - Whether the labels are written by magnitude, which is one
288
+ * character narrower on the half of a mirrored chart that runs negative.
289
+ * @param left - Where the plot begins, which is the far side of the gutter.
290
+ * @returns The column to centre the title on, never left of `TITLE_COLUMN`.
291
+ */
292
+ function valueTitleColumn(
293
+ ticks: readonly number[],
294
+ write: (value: number) => string,
295
+ absolute: boolean,
296
+ left: number,
297
+ ): number {
298
+ let widest = 0;
299
+ for (const tick of ticks) {
300
+ const width = write(absolute ? Math.abs(tick) : tick).length;
301
+ if (width > widest) widest = width;
302
+ }
303
+ const beside =
304
+ left - TICK_LABEL_GAP - widest * TICK_CHARACTER - TITLE_ASIDE - HALF_TITLE;
305
+ return Math.max(TITLE_COLUMN, beside);
306
+ }
307
+
308
+ /** Half the height of the title, which is what its rotated glyphs claim. */
309
+ const HALF_TITLE = CHART_FONT.title / 2;
310
+
311
+ /** The room a label wants along the bottom, at its widest. */
312
+ const X_TICK_SPACING = 90;
313
+
314
+ /** The room a label wants up the side. */
315
+ const Y_TICK_SPACING = 44;
316
+
317
+ /** The clear space between the plot and the numbers written outside it. */
318
+ const TICK_LABEL_GAP = 5;
319
+
320
+ /** How far under the plot the horizontal title hangs, clear of the numbers. */
321
+ const TITLE_GAP = 18;
322
+
323
+ /**
324
+ * The column the rotated value title stands in when the numbers leave it no
325
+ * room, inside the left margin.
326
+ *
327
+ * A floor rather than the place it is written: `valueTitleColumn` puts the
328
+ * title beside the widest number instead, and this is where an axis whose
329
+ * labels fill the whole gutter pushes it back to.
330
+ */
331
+ const TITLE_COLUMN = 8;
332
+
333
+ /** The clear space between the widest number up the side and the title. */
334
+ const TITLE_ASIDE = 4;
335
+
336
+ /**
337
+ * How wide one character of a tick label is, at the size the ticks are written.
338
+ *
339
+ * Six tenths of the type size, which is a shade wider than a digit is in any of
340
+ * the sans faces a host is likely to be set in — the chart sets no family of its
341
+ * own, so this is an estimate and is deliberately the generous one. Too wide
342
+ * writes the value title a pixel or two further from the numbers than it had to
343
+ * be; too narrow writes it over them.
344
+ */
345
+ const TICK_CHARACTER = 0.6 * CHART_FONT.tick;
346
+
347
+ const gridStyle = { stroke: CHART_COLORS.grid } as const;
348
+
349
+ const zeroRuleStyle = { stroke: CHART_COLORS.zeroRule } as const;
350
+
351
+ const axisStyle = { stroke: CHART_COLORS.axis } as const;
352
+
353
+ const tickStyle = {
354
+ fill: CHART_COLORS.tick,
355
+ fontSize: CHART_FONT.tick,
356
+ } as const;
357
+
358
+ const titleStyle = {
359
+ fill: CHART_COLORS.title,
360
+ fontSize: CHART_FONT.title,
361
+ } as const;
@@ -0,0 +1,187 @@
1
+ import type { ReactElement } from 'react';
2
+ import { useMemo } from 'react';
3
+
4
+ import type { PlotRect } from '../core/chartGeometry.ts';
5
+ import type { ChartScale } from '../core/chartScale.ts';
6
+ import { CHART_COLORS, CHART_FONT, LABEL_HALO } from '../core/chartTheme.ts';
7
+ import type { GuidePlacement } from '../core/guidePlacement.ts';
8
+ import { guidePlacement } from '../core/guidePlacement.ts';
9
+
10
+ /** What the rule is drawn at, and what it says about itself. */
11
+ export interface AxisGuideProps {
12
+ /**
13
+ * The place on the horizontal axis being pointed at, in whatever that axis
14
+ * measures, and `null` when nothing is being looked at.
15
+ */
16
+ value: number | null;
17
+ /** Where the plot sits inside the SVG. */
18
+ plot: PlotRect;
19
+ /** The horizontal axis as it is currently zoomed. */
20
+ xScale: ChartScale;
21
+ /**
22
+ * What the guide is drawn in.
23
+ * @default the theme's highlight colour
24
+ */
25
+ color?: string;
26
+ /**
27
+ * A few words written beside the rule, for a chart carrying more than one of
28
+ * them — `MS2 456.7`, `scan 314`. Nothing is written when it is absent, which
29
+ * is right for a chart whose single guide answers a hover the reader is
30
+ * already making.
31
+ * @default nothing is written
32
+ */
33
+ label?: string;
34
+ }
35
+
36
+ /**
37
+ * The vertical rule marking the place on the horizontal axis being looked at.
38
+ *
39
+ * A peak hovered in a table, a fragment hovered on a structure beside the chart,
40
+ * a search result rested on, the retention time whose scan is drawn in the pane
41
+ * below: each of them asks the chart the same question, and this is its whole
42
+ * answer. It sits below the viewers rather than inside one of them because a
43
+ * mass viewer's precursor rule and a chromatogram's time cursor are not two
44
+ * pictures that resemble each other — they are one picture, drawn from a value
45
+ * and a scale, and neither half of it can tell what it is measuring.
46
+ *
47
+ * When the value is inside the window the rule stands on it, solid. When it is
48
+ * not, the rule is parked on the edge the value went out of, dashed, and
49
+ * carries an arrow pointing that way. That is the case the component exists
50
+ * for: a chart zoomed onto one isotopologue cluster has almost everything a
51
+ * panel can point at outside its window, and answering with nothing drawn
52
+ * leaves a fragment the spectrum does not carry looking exactly like one that
53
+ * is two hundred mass units to the left. Dashed says *not here*, and the arrow
54
+ * says where to go.
55
+ *
56
+ * The arrow is a triangle rather than a `◀` glyph, because whether that
57
+ * character has one is the host's font's business and a missing one draws a
58
+ * hollow box in the middle of the chart. It sits just under the top edge, the
59
+ * strip of the plot a trace is least often in.
60
+ *
61
+ * Nothing here takes a pointer event: the guide is an answer, never a target.
62
+ * @param props - Component props.
63
+ * @returns The guide, or nothing when there is no value to point at and when
64
+ * the scale maps it nowhere.
65
+ */
66
+ export function AxisGuide(props: AxisGuideProps): ReactElement | null {
67
+ const { value, plot, xScale, color = CHART_COLORS.highlight, label } = props;
68
+
69
+ const placement = value === null ? null : guidePlacement(value, plot, xScale);
70
+ const lineStyle = useMemo(() => ({ stroke: color }), [color]);
71
+ const arrowStyle = useMemo(() => ({ fill: color }), [color]);
72
+ const labelStyle = useMemo(
73
+ () => ({ fill: color, fontSize: CHART_FONT.label, ...LABEL_HALO }),
74
+ [color],
75
+ );
76
+
77
+ if (placement === null) return null;
78
+ const { x, direction } = placement;
79
+ const labelPlace = labelPlacement(placement, plot);
80
+
81
+ return (
82
+ <g pointerEvents="none">
83
+ <line
84
+ x1={x}
85
+ y1={plot.top}
86
+ x2={x}
87
+ y2={plot.bottom}
88
+ strokeWidth={GUIDE_WIDTH}
89
+ strokeDasharray={direction === null ? undefined : PARKED_DASH}
90
+ style={lineStyle}
91
+ />
92
+ {direction === null ? null : (
93
+ <path d={arrowPath({ x, direction }, plot)} style={arrowStyle} />
94
+ )}
95
+ {label === undefined ? null : (
96
+ <text
97
+ x={labelPlace.x}
98
+ y={plot.top + ARROW_TOP_INSET}
99
+ textAnchor={labelPlace.anchor}
100
+ dominantBaseline="central"
101
+ style={labelStyle}
102
+ >
103
+ {label}
104
+ </text>
105
+ )}
106
+ </g>
107
+ );
108
+ }
109
+
110
+ /** How thick the rule is: thin enough to read a peak beside, not through. */
111
+ const GUIDE_WIDTH = 1.5;
112
+
113
+ /** What a parked guide is dashed with. */
114
+ const PARKED_DASH = '4 3';
115
+
116
+ /** How far the arrow reaches back into the plot from its point. */
117
+ const ARROW_LENGTH = 7;
118
+
119
+ /** Half the width of its base. */
120
+ const ARROW_HALF_HEIGHT = 5;
121
+
122
+ /** How far below the top of the plot it sits. */
123
+ const ARROW_TOP_INSET = 8;
124
+
125
+ /** The clear space between the rule, or its arrow, and the label beside it. */
126
+ const LABEL_GAP = 4;
127
+
128
+ /**
129
+ * How much room a label is assumed to want.
130
+ *
131
+ * Measuring the text would mean rendering it first, which is a whole layout
132
+ * pass for a decision that only has to be right at the edges. Sixty pixels is
133
+ * about eight characters at the label size — `MS2 456.7` — and a label longer
134
+ * than that is one written for a panel rather than for a plot.
135
+ */
136
+ const LABEL_ROOM = 60;
137
+
138
+ /**
139
+ * The triangle a parked guide carries, pointing off the edge it is parked on.
140
+ *
141
+ * Only a parked guide has one, and the parameter says so rather than a guard
142
+ * inside: a guide standing on its own value has no edge to point at, and the
143
+ * caller has already told the two apart to decide whether to draw a path at all.
144
+ * @param placement - Where the guide is parked, and which edge its value lies past.
145
+ * @param plot - The plotting area, whose top the arrow hangs under.
146
+ * @returns The `d` of the triangle.
147
+ */
148
+ function arrowPath(
149
+ placement: GuidePlacement & { direction: 'left' | 'right' },
150
+ plot: PlotRect,
151
+ ): string {
152
+ const { x, direction } = placement;
153
+ const back = direction === 'left' ? x + ARROW_LENGTH : x - ARROW_LENGTH;
154
+ const y = plot.top + ARROW_TOP_INSET;
155
+ return `M${x} ${y}L${back} ${y - ARROW_HALF_HEIGHT}L${back} ${y + ARROW_HALF_HEIGHT}Z`;
156
+ }
157
+
158
+ /**
159
+ * Which side of the rule the label is written on.
160
+ *
161
+ * It runs to the right and flips to the left as soon as it would otherwise
162
+ * cross the right edge — flipping rather than sliding, for the reason the
163
+ * pointer readout flips: a label pinned to the edge drifts away from the rule
164
+ * it belongs to and the pair stops reading as one thing. A guide parked on an
165
+ * edge has only one side that is inside the plot at all, so there the flip is
166
+ * forced, and the gap clears the arrow rather than the rule.
167
+ * @param placement - Where the guide ended up, and which way its value lies.
168
+ * @param plot - The plotting area the label has to stay inside.
169
+ * @returns The anchor, and which way the text runs from it.
170
+ */
171
+ function labelPlacement(
172
+ placement: GuidePlacement,
173
+ plot: PlotRect,
174
+ ): { x: number; anchor: 'start' | 'end' } {
175
+ const { x, direction } = placement;
176
+ if (direction === 'left') {
177
+ return { x: x + ARROW_LENGTH + LABEL_GAP, anchor: 'start' };
178
+ }
179
+ if (direction === 'right') {
180
+ return { x: x - ARROW_LENGTH - LABEL_GAP, anchor: 'end' };
181
+ }
182
+ const runsRight = x + LABEL_GAP + LABEL_ROOM <= plot.right;
183
+ return {
184
+ x: runsRight ? x + LABEL_GAP : x - LABEL_GAP,
185
+ anchor: runsRight ? 'start' : 'end',
186
+ };
187
+ }
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Charts stacked one above another, each resized by the splitter under it.
3
+ *
4
+ * One measurement is often read on more than one chart at once — the separation
5
+ * a sample was run through, the spectrum taken where the cursor stands, and what
6
+ * that spectrum broke into — and those are windows over different axes rather
7
+ * than traces on one. Stacking them is layout and nothing else, which is the
8
+ * whole of what this component knows: N panes, one above another, sharing the
9
+ * gutter their value axes are drawn in, the one at the foot writing the
10
+ * horizontal axis under all of them. Which pane holds what, and what makes one
11
+ * appear at all, is a fact about the measurement and stays in the viewer.
12
+ *
13
+ * How N panes become N nested splits is in `chartStackLevel.tsx`; what is held
14
+ * here is the one thing that outlives a render, which is how tall each of them
15
+ * was last left.
16
+ *
17
+ * Two things `SplitPane` does not do, and both of them draw a plausible wrong
18
+ * picture rather than failing outright:
19
+ *
20
+ * - **It has no minimum.** `useSplitPaneSize` clamps a drag to
21
+ * `{ min: 0, max: parentDimension }`, so a splitter dragged to the top of the
22
+ * stack leaves the pane above it at nothing at all; `plotRect` then holds the
23
+ * plot at `MINIMUM_PLOT_SIDE` and what is left is a ten-pixel stub with a full
24
+ * set of axes over it. Every height is held above the pane's own minimum —
25
+ * the default it starts at as much as the one a drag arrives at — because
26
+ * nothing underneath will do it.
27
+ * - **Its controlled side gets no `min-height: 0`.** `getItemStyle` resets that
28
+ * on the *other* side only, and a chart is an `<svg>` carrying a real `height`
29
+ * attribute, so the controlled pane's min-content height is whatever the
30
+ * chart was last measured at: the pane grows and then refuses to shrink back.
31
+ * Every pane is wrapped in a box that carries the reset itself.
32
+ *
33
+ * A pane keeps its children mounted whether it is open or shut — `unmountChildren`
34
+ * stays false — so a closed pane measures 0 × 0 behind a `display: none`, its
35
+ * `ResizeObserver` fires again the moment it is revealed, and it comes back
36
+ * through the window it was being looked at through. A remounted chart is empty.
37
+ */
38
+
39
+ import type { ReactElement } from 'react';
40
+ import { useCallback, useMemo, useState } from 'react';
41
+ import type { SplitPaneSize } from 'react-science/ui';
42
+
43
+ import type { ChartStackPane, StackLevel } from './chartStackLevel.tsx';
44
+ import { keptHeight, paneHeight, stackFrom } from './chartStackLevel.tsx';
45
+
46
+ export type { ChartStackPane } from './chartStackLevel.tsx';
47
+
48
+ /** What the stack is drawn from. */
49
+ export interface ChartStackProps {
50
+ /**
51
+ * The panes, in the order they are stacked, top to bottom.
52
+ *
53
+ * A pane with nothing to draw is left out of this array rather than handed in
54
+ * empty — that is what makes its splitter go away with it. Appending a pane,
55
+ * and dropping the one at the foot, cost nothing: every pane is a split
56
+ * whether or not anything follows it, so no chart already stacked is stood up
57
+ * again. Taking one out of the *middle* still is expensive — every split
58
+ * below it takes on the identity of the one that was under it, and the charts
59
+ * in them are all remounted, coming back fitted to what they draw rather than
60
+ * through the window they were left at. So a pane is still better dropped
61
+ * from the foot of the stack than out of its middle.
62
+ */
63
+ panes: readonly ChartStackPane[];
64
+ /**
65
+ * Told when a splitter is let go, with the height the pane came to rest at.
66
+ *
67
+ * On release rather than on every pixel of the drag, because a viewer that
68
+ * hears this puts it in its own state, and a store per pointer move renders
69
+ * every pane of the stack again on each one. The height reported is the one
70
+ * that was kept, minimum already applied.
71
+ * @default the height is remembered inside the stack and nowhere else
72
+ * @param id - Which pane was resized.
73
+ * @param height - How tall it now stands, in pixels.
74
+ */
75
+ onHeightChange?: (id: string, height: number) => void;
76
+ }
77
+
78
+ /**
79
+ * Stack charts vertically, with a splitter between each pair.
80
+ *
81
+ * Everything a level of the nesting is handed is memoised, and for the reason
82
+ * the release is told apart from the drag: `resize` fires on every pointer move,
83
+ * and a `StackLevel` rebuilt there would recurse through every `SplitPane` of
84
+ * the stack on each one, taking every chart in it with them.
85
+ * @param props - Component props.
86
+ * @returns The stack, filling the box it is given.
87
+ */
88
+ export function ChartStack(props: ChartStackProps): ReactElement {
89
+ const { panes, onHeightChange } = props;
90
+ const [heights, setHeights] = useState<Readonly<Record<string, number>>>({});
91
+
92
+ const heightOf = useCallback(
93
+ (pane: ChartStackPane) => paneHeight(pane, heights[pane.id]),
94
+ [heights],
95
+ );
96
+
97
+ const resize = useCallback((pane: ChartStackPane, asked: SplitPaneSize) => {
98
+ const height = keptHeight(asked, pane);
99
+ if (height === null) return;
100
+ setHeights((current) =>
101
+ current[pane.id] === height ? current : { ...current, [pane.id]: height },
102
+ );
103
+ }, []);
104
+
105
+ const rest = useCallback(
106
+ (pane: ChartStackPane, asked: SplitPaneSize) => {
107
+ const height = keptHeight(asked, pane);
108
+ if (height !== null) onHeightChange?.(pane.id, height);
109
+ },
110
+ [onHeightChange],
111
+ );
112
+
113
+ const level = useMemo<StackLevel>(
114
+ () => ({ panes, heightOf, resize, rest }),
115
+ [panes, heightOf, resize, rest],
116
+ );
117
+
118
+ return <div style={stackStyle}>{stackFrom(level, 0)}</div>;
119
+ }
120
+
121
+ /** The box the whole stack fills, whatever it was given by way of a parent. */
122
+ const stackStyle = {
123
+ display: 'flex',
124
+ flexDirection: 'column',
125
+ width: '100%',
126
+ height: '100%',
127
+ minWidth: 0,
128
+ minHeight: 0,
129
+ overflow: 'hidden',
130
+ } as const;