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,57 @@
1
+ /**
2
+ * Which band the pointer is asking about.
3
+ *
4
+ * Found in pixels rather than in wavenumbers, because what a user means by
5
+ * "that band" is what is under the pointer on screen: at a full-scan zoom two
6
+ * bands thirty wavenumbers apart are three pixels apart and either will do,
7
+ * while at a deep zoom the same thirty wavenumbers is half the plot and only one
8
+ * of them is being pointed at.
9
+ */
10
+
11
+ import type { ChartScale } from '../../chart/core/chartScale.ts';
12
+ import { chartPixel } from '../../chart/core/chartScale.ts';
13
+
14
+ import type { IrBand } from './irBand.ts';
15
+
16
+ /**
17
+ * How close the pointer has to be to a band, in pixels.
18
+ *
19
+ * Eight is about a fingertip's worth of aim on a trackpad. Wider and the readout
20
+ * claims a band while the pointer is plainly on the baseline beside it; narrower
21
+ * and a band has to be hit exactly, which on a dense fingerprint region is not
22
+ * a gesture anyone can make.
23
+ */
24
+ export const BAND_HIT_RADIUS = 8;
25
+
26
+ /**
27
+ * The band nearest a place on the axis, when one is within reach.
28
+ *
29
+ * A plain scan rather than a binary search: a spectrum is picked down to a few
30
+ * dozen bands, so the whole list is shorter than the setup a search would need,
31
+ * and it stays correct if the bands ever arrive in another order.
32
+ * @param bands - The bands of every spectrum currently drawn.
33
+ * @param xScale - The wavenumber axis as it is currently zoomed, which may run
34
+ * either way round.
35
+ * @param pixelX - Where the pointer is, in user units of the SVG.
36
+ * @param radius - How close it has to be. Defaults to `BAND_HIT_RADIUS`.
37
+ * @returns The band, or `null` when none is within reach.
38
+ */
39
+ export function nearestBandAt(
40
+ bands: readonly IrBand[],
41
+ xScale: ChartScale,
42
+ pixelX: number,
43
+ radius = BAND_HIT_RADIUS,
44
+ ): IrBand | null {
45
+ let found: IrBand | null = null;
46
+ let bestDistance = radius;
47
+ for (const band of bands) {
48
+ const distance = Math.abs(chartPixel(xScale, band.wavenumber) - pixelX);
49
+ // Strictly nearer, so the first of two bands at one wavenumber wins and the
50
+ // answer does not flicker between them as the pointer rests still.
51
+ if (distance < bestDistance) {
52
+ bestDistance = distance;
53
+ found = band;
54
+ }
55
+ }
56
+ return found;
57
+ }
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Finding the bands in a spectrum, which `ir-spectrum` does.
3
+ *
4
+ * Everything here is the two things that call needs and does not have: a
5
+ * `MeasurementXY` built out of the arrays the viewer holds, and the decision to
6
+ * pick on **absorbance** rather than on transmittance. That second one is the
7
+ * only judgement in the file and it is not a preference — peak picking finds
8
+ * maxima, and a band is a maximum in absorbance but a *minimum* in transmittance,
9
+ * so picking on transmittance would return the flat baseline between the bands
10
+ * and miss every band there is.
11
+ */
12
+
13
+ import type { MeasurementXY } from 'cheminfo-types';
14
+ import { autoPeakPicking } from 'ir-spectrum';
15
+ import { xMaxValue, xMinValue } from 'ml-spectra-processing';
16
+
17
+ import type { IrBand, IrBandStrength } from './irBand.ts';
18
+ import type { IrSpectrum } from './irSpectrum.ts';
19
+
20
+ /** How the bands are picked. */
21
+ export interface PickBandsOptions {
22
+ /**
23
+ * Lowest wavenumber to pick in, in cm⁻¹.
24
+ * @default the start of the spectrum
25
+ */
26
+ from?: number;
27
+ /**
28
+ * Highest wavenumber to pick in, in cm⁻¹.
29
+ * @default the end of the spectrum
30
+ */
31
+ to?: number;
32
+ /**
33
+ * How tall a band must be against the tallest one to count, as a fraction.
34
+ *
35
+ * Two percent by default, which on a real ATR spectrum is a little above the
36
+ * noise and a long way below any band worth naming. Lowered, the fingerprint
37
+ * region fills with shoulders that have no assignment; raised past about a
38
+ * tenth, weak but diagnostic bands — a nitrile, an alkyne — stop being found.
39
+ * @default 0.02
40
+ */
41
+ minRelativeHeight?: number;
42
+ /**
43
+ * Narrowest band to keep, in cm⁻¹.
44
+ *
45
+ * A spike one point wide is a detector glitch rather than a vibration: real
46
+ * infrared bands are several wavenumbers across even at their sharpest.
47
+ * @default 4
48
+ */
49
+ minPeakWidth?: number;
50
+ /**
51
+ * At most how many bands to keep, the strongest first.
52
+ * @default every band found
53
+ */
54
+ limit?: number;
55
+ }
56
+
57
+ /**
58
+ * Pick the bands of one spectrum.
59
+ *
60
+ * The bands come back in ascending wavenumber, which is the order a spectrum is
61
+ * read in rather than the order they were found — `limit` cuts by height, and
62
+ * then what survives is put back in axis order, so a table of them reads like
63
+ * the chart.
64
+ *
65
+ * **A band centre is a sampled point, not an interpolated one.** `ir-spectrum`
66
+ * reports each picked band at the wavenumber of the sample it peaked on, so on a
67
+ * bench instrument's 4 cm⁻¹ grid a carbonyl centred at 1710 is reported at 1708
68
+ * or 1712. That is within the tolerance the assignment table is matched with, and
69
+ * refining it here would mean re-deriving a peak position this package has
70
+ * deliberately delegated — but it is why a band should never be quoted as though
71
+ * it were measured to the wavenumber.
72
+ * @param spectrum - The spectrum to pick from.
73
+ * @param options - Where to pick, and what to keep.
74
+ * @returns The bands, ascending by wavenumber.
75
+ */
76
+ export function pickBands(
77
+ spectrum: IrSpectrum,
78
+ options: PickBandsOptions = {},
79
+ ): IrBand[] {
80
+ const {
81
+ from,
82
+ to,
83
+ minRelativeHeight = 0.02,
84
+ minPeakWidth = 4,
85
+ limit,
86
+ } = options;
87
+ if (spectrum.wavenumber.length < 2) return [];
88
+
89
+ const picked = autoPeakPicking(measurementOf(spectrum), {
90
+ // Absorbance, because a band is a maximum there and a minimum in the other.
91
+ yVariable: 'a',
92
+ minMaxRatio: minRelativeHeight,
93
+ minPeakWidth,
94
+ ...(from === undefined ? {} : { from }),
95
+ ...(to === undefined ? {} : { to }),
96
+ });
97
+
98
+ const bands: IrBand[] = [];
99
+ for (const peak of picked) {
100
+ if (!Number.isFinite(peak.wavenumber)) continue;
101
+ bands.push({
102
+ spectrumId: spectrum.id,
103
+ wavenumber: peak.wavenumber,
104
+ absorbance: peak.absorbance,
105
+ // `ConvertedPeak.transmittance` is a fraction where the spectrum's own
106
+ // transmittance is a percentage; brought onto the one scale here so that
107
+ // nothing downstream has to remember which of the two it is holding.
108
+ transmittance: peak.transmittance * 100,
109
+ strength: peak.kind as IrBandStrength,
110
+ });
111
+ }
112
+
113
+ const kept =
114
+ limit === undefined || bands.length <= limit
115
+ ? bands
116
+ : bands.toSorted(byDescendingAbsorbance).slice(0, limit);
117
+ return kept.toSorted(byAscendingWavenumber);
118
+ }
119
+
120
+ /**
121
+ * The spectrum as `ir-spectrum` wants it.
122
+ *
123
+ * The `t` variable is given its extremes, because that is what the strength
124
+ * letter is worked out from: without them the conversion assumes a spectrum
125
+ * running the full 0 to 100 percent, and every band of a shallow ATR trace that
126
+ * never leaves the eighties comes back weak.
127
+ * @param spectrum - The spectrum the viewer holds.
128
+ * @returns A measurement carrying all three variables.
129
+ */
130
+ function measurementOf(spectrum: IrSpectrum): MeasurementXY {
131
+ const transmittance = {
132
+ label: 'Transmittance (%)',
133
+ units: '%',
134
+ symbol: 't' as const,
135
+ data: spectrum.transmittance,
136
+ min: xMinValue(spectrum.transmittance),
137
+ max: xMaxValue(spectrum.transmittance),
138
+ };
139
+ return {
140
+ variables: {
141
+ x: {
142
+ label: 'Wavenumber',
143
+ units: '1/cm',
144
+ symbol: 'x',
145
+ data: spectrum.wavenumber,
146
+ },
147
+ // `y` is required of every measurement, and stands for whichever axis was
148
+ // recorded. Nothing here reads it — the picking is told to use `a` and the
149
+ // strength letter is read off `t` — so it carries the transmittance rather
150
+ // than a third copy of anything.
151
+ y: transmittance,
152
+ a: {
153
+ label: 'Absorbance',
154
+ units: '',
155
+ symbol: 'a',
156
+ data: spectrum.absorbance,
157
+ },
158
+ t: transmittance,
159
+ },
160
+ };
161
+ }
162
+
163
+ /**
164
+ * Order two bands by height, tallest first.
165
+ * @param first - One band.
166
+ * @param second - The other.
167
+ * @returns The comparison.
168
+ */
169
+ function byDescendingAbsorbance(first: IrBand, second: IrBand): number {
170
+ return second.absorbance - first.absorbance;
171
+ }
172
+
173
+ /**
174
+ * Order two bands along the axis, lowest wavenumber first.
175
+ * @param first - One band.
176
+ * @param second - The other.
177
+ * @returns The comparison.
178
+ */
179
+ function byAscendingWavenumber(first: IrBand, second: IrBand): number {
180
+ return first.wavenumber - second.wavenumber;
181
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Writing spectra back out as JCAMP-DX, so what was loaded can be taken away.
3
+ *
4
+ * JCAMP is the format to write rather than two columns of text because it says
5
+ * what its second column means: an infrared spectrum is read either as
6
+ * absorbance or as percent transmittance, the two are the same measurement
7
+ * turned inside out, and a bare column of numbers leaves whoever opens it next
8
+ * to guess which. `##YUNITS=` states it, and `ir-spectrum` reads it back and
9
+ * derives the other axis from it, so a spectrum written here returns carrying
10
+ * both.
11
+ *
12
+ * The points are written as an `##PEAK TABLE=` of explicit `x y` pairs rather
13
+ * than as a compressed `##XYDATA=` record. An XYDATA record states a first
14
+ * wavenumber and an increment and lets the reader rebuild the axis, which is
15
+ * exact only for an evenly sampled trace — and an interferogram transformed onto
16
+ * a wavenumber grid is evenly sampled only until somebody trims or splices it.
17
+ * Explicit pairs round trip whatever the spacing.
18
+ */
19
+
20
+ import { fromJSON } from 'convert-to-jcamp';
21
+
22
+ import type { IrMode, IrSpectrum } from './irSpectrum.ts';
23
+
24
+ /** The extension a written spectrum is saved under. */
25
+ export const JCAMP_EXTENSION = '.jdx';
26
+
27
+ /** What a JCAMP-DX file is served as. */
28
+ export const JCAMP_MIME_TYPE = 'chemical/x-jcamp-dx';
29
+
30
+ /** How the technique is named when the file that was read named nothing. */
31
+ export const DEFAULT_DATA_TYPE = 'INFRARED SPECTRUM';
32
+
33
+ /**
34
+ * Write one spectrum as a JCAMP-DX block.
35
+ *
36
+ * The axis written is the one the instrument recorded wherever the file said
37
+ * which that was, and only otherwise the one being read. Writing what is on
38
+ * screen instead would export a spectrum that had been through a logarithm it
39
+ * was never measured with — and, where a band bottoms out at zero transmittance,
40
+ * an absorbance of infinity that no reader can take back.
41
+ * @param spectrum - The spectrum.
42
+ * @param mode - The axis being read, used when the file named none.
43
+ * @returns The block, `##TITLE=` through `##END=`.
44
+ */
45
+ export function irSpectrumToJcamp(spectrum: IrSpectrum, mode: IrMode): string {
46
+ const written = spectrum.origin.recorded ?? mode;
47
+ const values =
48
+ written === 'absorbance' ? spectrum.absorbance : spectrum.transmittance;
49
+ return fromJSON(
50
+ { x: spectrum.wavenumber, y: values },
51
+ { info: infoRecords(spectrum, written), meta: metaRecords(spectrum) },
52
+ );
53
+ }
54
+
55
+ /**
56
+ * Write every spectrum of a list as one JCAMP-DX file.
57
+ *
58
+ * One file rather than one download per spectrum: a browser asked for six files
59
+ * in a row blocks all but the first, and a sample and its background are wanted
60
+ * back as the pair they were compared as. The blocks go inside a `LINK` block,
61
+ * which is what JCAMP has for a container and what the instruments that write a
62
+ * pair already use, so dropping the file back on the chart brings the whole list
63
+ * back.
64
+ *
65
+ * A list of one is written as that block alone: wrapping a single spectrum in a
66
+ * container gains nothing, and the file is then exactly what asking for that one
67
+ * spectrum would have written.
68
+ * @param spectra - The spectra, in the order the list holds them.
69
+ * @param mode - The axis being read, used for a spectrum whose file named none.
70
+ * @param title - What to call the file's own outer block.
71
+ * @returns The file.
72
+ */
73
+ export function irSpectraToJcamp(
74
+ spectra: readonly IrSpectrum[],
75
+ mode: IrMode,
76
+ title = `${spectra.length} infrared spectra`,
77
+ ): string {
78
+ const only = spectra.length === 1 ? spectra[0] : undefined;
79
+ if (only !== undefined) return irSpectrumToJcamp(only, mode);
80
+
81
+ const blocks: string[] = [];
82
+ for (const spectrum of spectra) {
83
+ blocks.push(irSpectrumToJcamp(spectrum, mode));
84
+ }
85
+ return `##TITLE=${recordValue(title)}
86
+ ##JCAMP-DX=4.24
87
+ ##DATA TYPE=LINK
88
+ ##BLOCKS=${blocks.length}
89
+ ${blocks.join('\n')}
90
+ ##END=
91
+ `;
92
+ }
93
+
94
+ /**
95
+ * The standard records of a block: what it is called, and what its axes are.
96
+ * @param spectrum - The spectrum.
97
+ * @param written - The axis being written.
98
+ * @returns The records, as `convert-to-jcamp` takes them.
99
+ */
100
+ function infoRecords(
101
+ spectrum: IrSpectrum,
102
+ written: IrMode,
103
+ ): Record<string, string> {
104
+ return {
105
+ title: recordValue(spectrum.name),
106
+ // The technique as the file stated it, so a Raman spectrum that was opened
107
+ // here is not written back out claiming to be infrared.
108
+ dataType: technique(spectrum) ?? DEFAULT_DATA_TYPE,
109
+ xUnits: '1/CM',
110
+ // Spelled the way `ir-spectrum` reads it: it takes the axis to be
111
+ // transmittance when the label says `trans`, and to be a percentage rather
112
+ // than a fraction when it carries a `%`.
113
+ yUnits: written === 'absorbance' ? 'ABSORBANCE' : 'Transmittance (%)',
114
+ };
115
+ }
116
+
117
+ /**
118
+ * The `$`-prefixed records of a block: the acquisition, as the file stated it.
119
+ *
120
+ * The table's labels are the record names themselves — the reader lists whatever
121
+ * `##$` records a block carried, under their own names — so writing it back is a
122
+ * matter of putting the `$` in front again. `Technique` is the one row that is
123
+ * not a record of that bag: it is the block's `##DATA TYPE=`, and it goes back
124
+ * there rather than becoming a user-defined record of its own.
125
+ * @param spectrum - The spectrum.
126
+ * @returns The records, keyed without their `##$`.
127
+ */
128
+ function metaRecords(spectrum: IrSpectrum): Record<string, string> {
129
+ const records: Record<string, string> = {};
130
+ const fields = spectrum.meta?.fields ?? [];
131
+ for (const field of fields) {
132
+ if (field.label === TECHNIQUE) continue;
133
+ records[recordKey(field.label)] = recordValue(field.value);
134
+ }
135
+ return records;
136
+ }
137
+
138
+ /** The row of the table that holds the block's own data type. */
139
+ const TECHNIQUE = 'Technique';
140
+
141
+ /**
142
+ * What the file said the spectrum was, if it said.
143
+ * @param spectrum - The spectrum.
144
+ * @returns The technique, or `undefined` when the file stated none.
145
+ */
146
+ function technique(spectrum: IrSpectrum): string | undefined {
147
+ for (const field of spectrum.meta?.fields ?? []) {
148
+ if (field.label === TECHNIQUE) return recordValue(field.value);
149
+ }
150
+ return undefined;
151
+ }
152
+
153
+ /**
154
+ * A label put where a JCAMP record's name goes.
155
+ *
156
+ * A record name runs to the `=` and holds no whitespace, so a label that picked
157
+ * up a space on its way through some other tool would otherwise write a record
158
+ * whose name is its first word and whose value starts with the rest of it.
159
+ * @param label - The row's label.
160
+ * @returns It as a record name.
161
+ */
162
+ function recordKey(label: string): string {
163
+ return label.replaceAll(/[\s=]+/g, '_');
164
+ }
165
+
166
+ /**
167
+ * A value put where a JCAMP record's value goes.
168
+ *
169
+ * A record is one line and `$$` opens a comment that runs to the end of it, so a
170
+ * value with a newline in it would otherwise either break the file in two or
171
+ * lose its tail. Both failures are silent on the way back in, which is why this
172
+ * is done to every value rather than to the ones known to be long.
173
+ * @param value - The value as it is held.
174
+ * @returns The value as one line, with no comment marker in it.
175
+ */
176
+ function recordValue(value: string): string {
177
+ return value.replaceAll(/\s+/g, ' ').replaceAll('$$', '$').trim();
178
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Turning what a reader produced into what the viewer holds.
3
+ *
4
+ * A reader answers about a file and knows nothing about the session it is being
5
+ * read into — which spectra are already open, what colours they took, what this
6
+ * one should be called. That is the gap this closes, and it is the only place an
7
+ * identity or a colour is invented.
8
+ */
9
+
10
+ import { nextSpectrumColor } from '../../chart/core/spectrumColor.ts';
11
+
12
+ import type { LoadedIrSpectrum } from './analysisSpectra.ts';
13
+ import type { IrSpectrum } from './irSpectrum.ts';
14
+
15
+ /** What has to be decided for a loaded spectrum to become a held one. */
16
+ export interface ToIrSpectrumOptions {
17
+ /**
18
+ * Identity, which every later edit and selection is keyed on.
19
+ * @default a fresh UUID
20
+ */
21
+ id?: string;
22
+ /**
23
+ * The colour to draw it in.
24
+ * @default the lowest hue not in `taken`
25
+ */
26
+ color?: string;
27
+ /**
28
+ * The colours the spectra already open have taken, so a new one is told apart
29
+ * from them. Ignored when `color` says outright.
30
+ * @default no colours taken
31
+ */
32
+ taken?: readonly string[];
33
+ /**
34
+ * What to call it, overriding the file's own title.
35
+ * @default the file's title, then its name, then `spectrum`
36
+ */
37
+ name?: string;
38
+ /**
39
+ * Whether it is drawn as soon as it is added.
40
+ * @default true
41
+ */
42
+ visible?: boolean;
43
+ }
44
+
45
+ /**
46
+ * Make a held spectrum out of a read one.
47
+ * @param loaded - What the reader produced.
48
+ * @param options - The identity, colour and name to give it.
49
+ * @returns The spectrum as the viewer holds it.
50
+ */
51
+ export function toIrSpectrum(
52
+ loaded: LoadedIrSpectrum,
53
+ options: ToIrSpectrumOptions = {},
54
+ ): IrSpectrum {
55
+ const {
56
+ id = crypto.randomUUID(),
57
+ taken = [],
58
+ name,
59
+ visible = true,
60
+ } = options;
61
+ const color = options.color ?? nextSpectrumColor(taken);
62
+ return {
63
+ id,
64
+ name: name ?? loaded.name ?? loaded.origin.fileName ?? 'spectrum',
65
+ color,
66
+ wavenumber: loaded.wavenumber,
67
+ absorbance: loaded.absorbance,
68
+ transmittance: loaded.transmittance,
69
+ meta: loaded.meta,
70
+ origin: loaded.origin,
71
+ visible,
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Make held spectra out of everything one file held.
77
+ *
78
+ * The colours are handed out one at a time against a growing list, so a file
79
+ * carrying a sample and its background gives two spectra of two colours rather
80
+ * than two of the same — `nextSpectrumColor` can only answer that if it is told
81
+ * what the previous call took.
82
+ * @param loaded - What the reader produced, in file order.
83
+ * @param options - The colours already taken, and whether the spectra are drawn.
84
+ * @returns The spectra, in the same order.
85
+ */
86
+ export function toIrSpectra(
87
+ loaded: readonly LoadedIrSpectrum[],
88
+ options: Pick<ToIrSpectrumOptions, 'taken' | 'visible'> = {},
89
+ ): IrSpectrum[] {
90
+ const { taken = [], visible } = options;
91
+ const colors = [...taken];
92
+ const spectra: IrSpectrum[] = [];
93
+ for (const entry of loaded) {
94
+ const spectrum = toIrSpectrum(entry, {
95
+ taken: colors,
96
+ ...(visible === undefined ? {} : { visible }),
97
+ });
98
+ colors.push(spectrum.color);
99
+ spectra.push(spectrum);
100
+ }
101
+ return spectra;
102
+ }
@@ -0,0 +1,166 @@
1
+ import type { ReactElement } from 'react';
2
+ import { useMemo } from 'react';
3
+
4
+ import type { PlotRect } from '../../chart/core/chartGeometry.ts';
5
+ import type { ChartScale } from '../../chart/core/chartScale.ts';
6
+ import {
7
+ CHART_COLORS,
8
+ CHART_FONT,
9
+ LABEL_HALO,
10
+ } from '../../chart/core/chartTheme.ts';
11
+ import type { AssignedBand } from '../core/assignBands.ts';
12
+ import { BAND_MARK, planBandLabels } from '../core/bandLabelPlan.ts';
13
+ import type { IrBand } from '../core/irBand.ts';
14
+ import { sameIrBand } from '../core/irBand.ts';
15
+ import { bandsPointDown } from '../core/irMode.ts';
16
+ import type { IrMode } from '../core/irSpectrum.ts';
17
+
18
+ export interface BandMarksProps {
19
+ /** The bands to mark, with whatever the table said about them. */
20
+ assigned: readonly AssignedBand[];
21
+ /** Where the plot sits inside the SVG. */
22
+ plot: PlotRect;
23
+ /** The wavenumber axis as it is currently zoomed. */
24
+ xScale: ChartScale;
25
+ /** The value axis as it is currently zoomed. */
26
+ yScale: ChartScale;
27
+ /** Which value axis is being drawn. */
28
+ mode: IrMode;
29
+ /**
30
+ * Whether each label names the assignment as well as the wavenumber.
31
+ * @default false
32
+ */
33
+ showAssignments?: boolean;
34
+ /**
35
+ * At most how many bands are named. Marks are drawn on all of them.
36
+ * @default 12
37
+ */
38
+ limit?: number;
39
+ /**
40
+ * The band the pointer has come to rest on, drawn larger, `null` for none.
41
+ * @default null
42
+ */
43
+ highlight?: IrBand | null;
44
+ }
45
+
46
+ /**
47
+ * A mark on every band, and a label on the ones there is room for.
48
+ *
49
+ * The mark reaches *away* from the label, into the band, because the clear space
50
+ * on the label's side is where the numbers are written and the mark is there to
51
+ * say which band they are about. So in transmittance both hang downwards from a
52
+ * dip and in absorbance both rise from a maximum, and the pair reads the same way
53
+ * up in either.
54
+ *
55
+ * A leader line is drawn only when a label had to be slid off its band to clear
56
+ * its neighbours — a leader from a label that is already directly above its band
57
+ * is a line saying what the position already said. A label slid too far is not
58
+ * drawn at all; the mark still says the band is there, which is the honest
59
+ * outcome, where a label hanging over a band it says nothing about is not.
60
+ * @param props - Component props.
61
+ * @returns The marks and labels, as SVG.
62
+ */
63
+ export function BandMarks(props: BandMarksProps): ReactElement {
64
+ const {
65
+ assigned,
66
+ plot,
67
+ xScale,
68
+ yScale,
69
+ mode,
70
+ showAssignments = false,
71
+ limit = 12,
72
+ highlight = null,
73
+ } = props;
74
+
75
+ const plans = useMemo(
76
+ () =>
77
+ planBandLabels({
78
+ assigned,
79
+ plot,
80
+ xScale,
81
+ yScale,
82
+ mode,
83
+ showAssignments,
84
+ limit,
85
+ }),
86
+ [assigned, plot, xScale, yScale, mode, showAssignments, limit],
87
+ );
88
+
89
+ const down = bandsPointDown(mode);
90
+ const reach = down ? BAND_MARK : -BAND_MARK;
91
+
92
+ return (
93
+ <g pointerEvents="none">
94
+ {plans.map((plan) => {
95
+ const highlighted = sameIrBand(plan.band, highlight);
96
+ const dropped = !Number.isFinite(plan.labelX);
97
+ const firstBaseline = plan.baselines[0];
98
+ const slid = !dropped && Math.abs(plan.labelX - plan.tipX) > LEADER_AT;
99
+ return (
100
+ <g key={`${plan.band.spectrumId} ${plan.band.wavenumber}`}>
101
+ <line
102
+ x1={plan.tipX}
103
+ y1={plan.tipY}
104
+ x2={plan.tipX}
105
+ y2={plan.tipY + reach}
106
+ style={highlighted ? highlightMarkStyle : markStyle}
107
+ strokeWidth={highlighted ? 2 : 1}
108
+ />
109
+ {slid && firstBaseline !== undefined ? (
110
+ <line
111
+ x1={plan.tipX}
112
+ y1={plan.tipY + reach}
113
+ x2={plan.labelX}
114
+ y2={firstBaseline}
115
+ style={leaderStyle}
116
+ />
117
+ ) : null}
118
+ {dropped
119
+ ? null
120
+ : plan.lines.map((line, index) => (
121
+ <text
122
+ key={line}
123
+ x={plan.labelX}
124
+ y={plan.baselines[index]}
125
+ textAnchor="middle"
126
+ style={highlighted ? highlightTextStyle : textStyle}
127
+ >
128
+ {line}
129
+ </text>
130
+ ))}
131
+ </g>
132
+ );
133
+ })}
134
+ </g>
135
+ );
136
+ }
137
+
138
+ /**
139
+ * How far a label may sit from its band before a leader is drawn to it.
140
+ *
141
+ * Two pixels: below that the label is over its band and a leader would be a
142
+ * line nobody needs, and the declutter sweep leaves most labels within a pixel
143
+ * of where they wanted to be.
144
+ */
145
+ const LEADER_AT = 2;
146
+
147
+ const markStyle = { stroke: CHART_COLORS.annotation } as const;
148
+
149
+ const highlightMarkStyle = { stroke: CHART_COLORS.highlight } as const;
150
+
151
+ const leaderStyle = { stroke: CHART_COLORS.leader } as const;
152
+
153
+ // Haloed: an infrared label is written over the trace as often as beside it,
154
+ // since a band is named where it dips and the neighbouring bands dip too.
155
+ const textStyle = {
156
+ fill: CHART_COLORS.labelText,
157
+ fontSize: CHART_FONT.label,
158
+ ...LABEL_HALO,
159
+ } as const;
160
+
161
+ const highlightTextStyle = {
162
+ fill: CHART_COLORS.highlight,
163
+ fontSize: CHART_FONT.label,
164
+ fontWeight: 600,
165
+ ...LABEL_HALO,
166
+ } as const;