react-cheminfo 0.69.0 → 0.71.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 (616) hide show
  1. package/README.md +70 -2
  2. package/lib/about/core/providers.d.ts +6 -0
  3. package/lib/about/core/providers.d.ts.map +1 -1
  4. package/lib/about/core/providers.js +7 -0
  5. package/lib/about/core/providers.js.map +1 -1
  6. package/lib/about/ui/AboutProvidedBy.js +34 -0
  7. package/lib/about/ui/AboutProvidedBy.js.map +1 -1
  8. package/lib/chart/ui/useChartPointer.d.ts +9 -1
  9. package/lib/chart/ui/useChartPointer.d.ts.map +1 -1
  10. package/lib/chart/ui/useChartPointer.js +11 -3
  11. package/lib/chart/ui/useChartPointer.js.map +1 -1
  12. package/lib/credits/core/credits.d.ts +41 -0
  13. package/lib/credits/core/credits.d.ts.map +1 -1
  14. package/lib/credits/core/credits.js +50 -0
  15. package/lib/credits/core/credits.js.map +1 -1
  16. package/lib/download/core/drawingMarkup.d.ts +8 -1
  17. package/lib/download/core/drawingMarkup.d.ts.map +1 -1
  18. package/lib/download/core/drawingMarkup.js +13 -1
  19. package/lib/download/core/drawingMarkup.js.map +1 -1
  20. package/lib/download/core/figurePng.d.ts +14 -0
  21. package/lib/download/core/figurePng.d.ts.map +1 -1
  22. package/lib/download/core/figurePng.js +21 -6
  23. package/lib/download/core/figurePng.js.map +1 -1
  24. package/lib/download/core/figureSvg.d.ts.map +1 -1
  25. package/lib/download/core/figureSvg.js +5 -3
  26. package/lib/download/core/figureSvg.js.map +1 -1
  27. package/lib/download/core/figureTarget.d.ts +13 -0
  28. package/lib/download/core/figureTarget.d.ts.map +1 -1
  29. package/lib/download/core/figureTarget.js +25 -5
  30. package/lib/download/core/figureTarget.js.map +1 -1
  31. package/lib/download/core/svgBounds.d.ts +15 -0
  32. package/lib/download/core/svgBounds.d.ts.map +1 -1
  33. package/lib/download/core/svgBounds.js +20 -0
  34. package/lib/download/core/svgBounds.js.map +1 -1
  35. package/lib/download/core/svgToPng.d.ts.map +1 -1
  36. package/lib/download/core/svgToPng.js +4 -2
  37. package/lib/download/core/svgToPng.js.map +1 -1
  38. package/lib/format/core/relativeTime.d.ts +8 -3
  39. package/lib/format/core/relativeTime.d.ts.map +1 -1
  40. package/lib/format/core/relativeTime.js +19 -7
  41. package/lib/format/core/relativeTime.js.map +1 -1
  42. package/lib/host/core/connectHost.d.ts +25 -34
  43. package/lib/host/core/connectHost.d.ts.map +1 -1
  44. package/lib/host/core/connectHost.js +43 -89
  45. package/lib/host/core/connectHost.js.map +1 -1
  46. package/lib/host/core/hostOutputs.d.ts +58 -0
  47. package/lib/host/core/hostOutputs.d.ts.map +1 -0
  48. package/lib/host/core/hostOutputs.js +151 -0
  49. package/lib/host/core/hostOutputs.js.map +1 -0
  50. package/lib/host/core/index.d.ts +9 -3
  51. package/lib/host/core/index.d.ts.map +1 -1
  52. package/lib/host/core/index.js +4 -1
  53. package/lib/host/core/index.js.map +1 -1
  54. package/lib/host/core/irKinds.d.ts +124 -0
  55. package/lib/host/core/irKinds.d.ts.map +1 -0
  56. package/lib/host/core/irKinds.js +46 -0
  57. package/lib/host/core/irKinds.js.map +1 -0
  58. package/lib/host/core/kinds.d.ts +13 -5
  59. package/lib/host/core/kinds.d.ts.map +1 -1
  60. package/lib/host/core/kinds.js +11 -5
  61. package/lib/host/core/kinds.js.map +1 -1
  62. package/lib/host/core/protocol.d.ts +50 -7
  63. package/lib/host/core/protocol.d.ts.map +1 -1
  64. package/lib/host/core/protocol.js +10 -6
  65. package/lib/host/core/protocol.js.map +1 -1
  66. package/lib/host/core/selectInputs.d.ts +37 -0
  67. package/lib/host/core/selectInputs.d.ts.map +1 -0
  68. package/lib/host/core/selectInputs.js +110 -0
  69. package/lib/host/core/selectInputs.js.map +1 -0
  70. package/lib/host/testing/sciPeaks.d.ts +31 -0
  71. package/lib/host/testing/sciPeaks.d.ts.map +1 -1
  72. package/lib/host/testing/sciPeaks.js +73 -0
  73. package/lib/host/testing/sciPeaks.js.map +1 -1
  74. package/lib/host/testing/standInHost.d.ts +9 -1
  75. package/lib/host/testing/standInHost.d.ts.map +1 -1
  76. package/lib/host/testing/standInHost.js +19 -1
  77. package/lib/host/testing/standInHost.js.map +1 -1
  78. package/lib/host/ui/useHostConnection.d.ts +13 -5
  79. package/lib/host/ui/useHostConnection.d.ts.map +1 -1
  80. package/lib/host/ui/useHostConnection.js +4 -3
  81. package/lib/host/ui/useHostConnection.js.map +1 -1
  82. package/lib/host-testing.d.ts +2 -2
  83. package/lib/host-testing.d.ts.map +1 -1
  84. package/lib/host-testing.js +2 -2
  85. package/lib/host-testing.js.map +1 -1
  86. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  87. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  88. package/lib/ir/core/handPicking.d.ts +58 -0
  89. package/lib/ir/core/handPicking.d.ts.map +1 -0
  90. package/lib/ir/core/handPicking.js +130 -0
  91. package/lib/ir/core/handPicking.js.map +1 -0
  92. package/lib/ir/core/index.d.ts +3 -0
  93. package/lib/ir/core/index.d.ts.map +1 -1
  94. package/lib/ir/core/index.js +3 -0
  95. package/lib/ir/core/index.js.map +1 -1
  96. package/lib/ir/core/irBandState.d.ts +57 -0
  97. package/lib/ir/core/irBandState.d.ts.map +1 -0
  98. package/lib/ir/core/irBandState.js +119 -0
  99. package/lib/ir/core/irBandState.js.map +1 -0
  100. package/lib/ir/core/irCommands.d.ts +11 -0
  101. package/lib/ir/core/irCommands.d.ts.map +1 -1
  102. package/lib/ir/core/irCommands.js +6 -0
  103. package/lib/ir/core/irCommands.js.map +1 -1
  104. package/lib/ir/core/irPeaks.d.ts +28 -0
  105. package/lib/ir/core/irPeaks.d.ts.map +1 -0
  106. package/lib/ir/core/irPeaks.js +66 -0
  107. package/lib/ir/core/irPeaks.js.map +1 -0
  108. package/lib/ir/core/irReducer.d.ts +8 -0
  109. package/lib/ir/core/irReducer.d.ts.map +1 -1
  110. package/lib/ir/core/irReducer.js +15 -32
  111. package/lib/ir/core/irReducer.js.map +1 -1
  112. package/lib/ir/core/irSpectrum.d.ts +15 -0
  113. package/lib/ir/core/irSpectrum.d.ts.map +1 -1
  114. package/lib/ir/core/irSpectrum.js.map +1 -1
  115. package/lib/ir/core/irState.d.ts +9 -6
  116. package/lib/ir/core/irState.d.ts.map +1 -1
  117. package/lib/ir/core/irState.js +10 -6
  118. package/lib/ir/core/irState.js.map +1 -1
  119. package/lib/ir/core/pickBands.d.ts +14 -0
  120. package/lib/ir/core/pickBands.d.ts.map +1 -1
  121. package/lib/ir/core/pickBands.js +39 -33
  122. package/lib/ir/core/pickBands.js.map +1 -1
  123. package/lib/ir/core/ramanBands.d.ts +9 -1
  124. package/lib/ir/core/ramanBands.d.ts.map +1 -1
  125. package/lib/ir/core/ramanBands.js +2 -2
  126. package/lib/ir/core/ramanBands.js.map +1 -1
  127. package/lib/ir/core/spectrumBands.d.ts +46 -0
  128. package/lib/ir/core/spectrumBands.d.ts.map +1 -0
  129. package/lib/ir/core/spectrumBands.js +98 -0
  130. package/lib/ir/core/spectrumBands.js.map +1 -0
  131. package/lib/ir/ui/BandRow.d.ts +5 -0
  132. package/lib/ir/ui/BandRow.d.ts.map +1 -1
  133. package/lib/ir/ui/BandRow.js +4 -3
  134. package/lib/ir/ui/BandRow.js.map +1 -1
  135. package/lib/ir/ui/BandsPanel.d.ts +5 -0
  136. package/lib/ir/ui/BandsPanel.d.ts.map +1 -1
  137. package/lib/ir/ui/BandsPanel.js +36 -16
  138. package/lib/ir/ui/BandsPanel.js.map +1 -1
  139. package/lib/ir/ui/BandsToolbar.d.ts +9 -0
  140. package/lib/ir/ui/BandsToolbar.d.ts.map +1 -0
  141. package/lib/ir/ui/BandsToolbar.js +61 -0
  142. package/lib/ir/ui/BandsToolbar.js.map +1 -0
  143. package/lib/ir/ui/IrCanvas.d.ts +2 -1
  144. package/lib/ir/ui/IrCanvas.d.ts.map +1 -1
  145. package/lib/ir/ui/IrCanvas.js +19 -5
  146. package/lib/ir/ui/IrCanvas.js.map +1 -1
  147. package/lib/ir/ui/IrChart.d.ts.map +1 -1
  148. package/lib/ir/ui/IrChart.js +8 -1
  149. package/lib/ir/ui/IrChart.js.map +1 -1
  150. package/lib/ir/ui/IrDocumentationDialog.js +1 -1
  151. package/lib/ir/ui/IrDocumentationDialog.js.map +1 -1
  152. package/lib/ir/ui/IrEditor.d.ts +4 -2
  153. package/lib/ir/ui/IrEditor.d.ts.map +1 -1
  154. package/lib/ir/ui/IrEditor.js.map +1 -1
  155. package/lib/ir/ui/IrShell.d.ts.map +1 -1
  156. package/lib/ir/ui/IrShell.js +6 -0
  157. package/lib/ir/ui/IrShell.js.map +1 -1
  158. package/lib/ir/ui/IrStatusBar.d.ts.map +1 -1
  159. package/lib/ir/ui/IrStatusBar.js +1 -1
  160. package/lib/ir/ui/IrStatusBar.js.map +1 -1
  161. package/lib/ir/ui/IrToolbar.d.ts +4 -3
  162. package/lib/ir/ui/IrToolbar.d.ts.map +1 -1
  163. package/lib/ir/ui/IrToolbar.js +5 -4
  164. package/lib/ir/ui/IrToolbar.js.map +1 -1
  165. package/lib/ir/ui/VibrationalEditor.d.ts +2 -1
  166. package/lib/ir/ui/VibrationalEditor.d.ts.map +1 -1
  167. package/lib/ir/ui/VibrationalEditor.js.map +1 -1
  168. package/lib/ir/ui/irActions.d.ts +5 -0
  169. package/lib/ir/ui/irActions.d.ts.map +1 -1
  170. package/lib/ir/ui/irActions.js +6 -0
  171. package/lib/ir/ui/irActions.js.map +1 -1
  172. package/lib/ir/ui/irChartProps.d.ts +4 -1
  173. package/lib/ir/ui/irChartProps.d.ts.map +1 -1
  174. package/lib/ir/ui/useIrEditor.d.ts +5 -11
  175. package/lib/ir/ui/useIrEditor.d.ts.map +1 -1
  176. package/lib/ir/ui/useIrEditor.js +17 -18
  177. package/lib/ir/ui/useIrEditor.js.map +1 -1
  178. package/lib/locales/de.json +63 -0
  179. package/lib/locales/en.json +63 -0
  180. package/lib/locales/es.json +63 -0
  181. package/lib/locales/fr.json +63 -0
  182. package/lib/locales/it.json +63 -0
  183. package/lib/mass/core/analyseSpectrum.d.ts +85 -0
  184. package/lib/mass/core/analyseSpectrum.d.ts.map +1 -0
  185. package/lib/mass/core/analyseSpectrum.js +101 -0
  186. package/lib/mass/core/analyseSpectrum.js.map +1 -0
  187. package/lib/mass/core/ascendingTrace.d.ts +24 -0
  188. package/lib/mass/core/ascendingTrace.d.ts.map +1 -0
  189. package/lib/mass/core/ascendingTrace.js +57 -0
  190. package/lib/mass/core/ascendingTrace.js.map +1 -0
  191. package/lib/mass/core/centroidPeaks.d.ts +77 -0
  192. package/lib/mass/core/centroidPeaks.d.ts.map +1 -0
  193. package/lib/mass/core/centroidPeaks.js +62 -0
  194. package/lib/mass/core/centroidPeaks.js.map +1 -0
  195. package/lib/mass/core/detectMassFormat.d.ts +24 -0
  196. package/lib/mass/core/detectMassFormat.d.ts.map +1 -0
  197. package/lib/mass/core/detectMassFormat.js +105 -0
  198. package/lib/mass/core/detectMassFormat.js.map +1 -0
  199. package/lib/mass/core/downloadSpectra.d.ts +24 -0
  200. package/lib/mass/core/downloadSpectra.d.ts.map +1 -0
  201. package/lib/mass/core/downloadSpectra.js +35 -0
  202. package/lib/mass/core/downloadSpectra.js.map +1 -0
  203. package/lib/mass/core/fromJcamp.d.ts +46 -0
  204. package/lib/mass/core/fromJcamp.d.ts.map +1 -0
  205. package/lib/mass/core/fromJcamp.js +123 -0
  206. package/lib/mass/core/fromJcamp.js.map +1 -0
  207. package/lib/mass/core/fromText.d.ts +30 -0
  208. package/lib/mass/core/fromText.d.ts.map +1 -0
  209. package/lib/mass/core/fromText.js +39 -0
  210. package/lib/mass/core/fromText.js.map +1 -0
  211. package/lib/mass/core/index.d.ts +70 -0
  212. package/lib/mass/core/index.d.ts.map +1 -0
  213. package/lib/mass/core/index.js +42 -0
  214. package/lib/mass/core/index.js.map +1 -0
  215. package/lib/mass/core/jcampTechnique.d.ts +38 -0
  216. package/lib/mass/core/jcampTechnique.d.ts.map +1 -0
  217. package/lib/mass/core/jcampTechnique.js +70 -0
  218. package/lib/mass/core/jcampTechnique.js.map +1 -0
  219. package/lib/mass/core/labelStackBox.d.ts +49 -0
  220. package/lib/mass/core/labelStackBox.d.ts.map +1 -0
  221. package/lib/mass/core/labelStackBox.js +44 -0
  222. package/lib/mass/core/labelStackBox.js.map +1 -0
  223. package/lib/mass/core/labelledPeaks.d.ts +79 -0
  224. package/lib/mass/core/labelledPeaks.d.ts.map +1 -0
  225. package/lib/mass/core/labelledPeaks.js +74 -0
  226. package/lib/mass/core/labelledPeaks.js.map +1 -0
  227. package/lib/mass/core/loadMassSpectra.d.ts +57 -0
  228. package/lib/mass/core/loadMassSpectra.d.ts.map +1 -0
  229. package/lib/mass/core/loadMassSpectra.js +45 -0
  230. package/lib/mass/core/loadMassSpectra.js.map +1 -0
  231. package/lib/mass/core/loadedMassSpectrum.d.ts +42 -0
  232. package/lib/mass/core/loadedMassSpectrum.d.ts.map +1 -0
  233. package/lib/mass/core/loadedMassSpectrum.js +15 -0
  234. package/lib/mass/core/loadedMassSpectrum.js.map +1 -0
  235. package/lib/mass/core/massCommands.d.ts +170 -0
  236. package/lib/mass/core/massCommands.d.ts.map +1 -0
  237. package/lib/mass/core/massCommands.js +95 -0
  238. package/lib/mass/core/massCommands.js.map +1 -0
  239. package/lib/mass/core/massDomain.d.ts +121 -0
  240. package/lib/mass/core/massDomain.d.ts.map +1 -0
  241. package/lib/mass/core/massDomain.js +179 -0
  242. package/lib/mass/core/massDomain.js.map +1 -0
  243. package/lib/mass/core/massEditorApi.d.ts +65 -0
  244. package/lib/mass/core/massEditorApi.d.ts.map +1 -0
  245. package/lib/mass/core/massEditorApi.js +10 -0
  246. package/lib/mass/core/massEditorApi.js.map +1 -0
  247. package/lib/mass/core/massFormat.d.ts +78 -0
  248. package/lib/mass/core/massFormat.d.ts.map +1 -0
  249. package/lib/mass/core/massFormat.js +168 -0
  250. package/lib/mass/core/massFormat.js.map +1 -0
  251. package/lib/mass/core/massMeta.d.ts +85 -0
  252. package/lib/mass/core/massMeta.d.ts.map +1 -0
  253. package/lib/mass/core/massMeta.js +182 -0
  254. package/lib/mass/core/massMeta.js.map +1 -0
  255. package/lib/mass/core/massReducer.d.ts +82 -0
  256. package/lib/mass/core/massReducer.d.ts.map +1 -0
  257. package/lib/mass/core/massReducer.js +163 -0
  258. package/lib/mass/core/massReducer.js.map +1 -0
  259. package/lib/mass/core/massResolution.d.ts +92 -0
  260. package/lib/mass/core/massResolution.d.ts.map +1 -0
  261. package/lib/mass/core/massResolution.js +126 -0
  262. package/lib/mass/core/massResolution.js.map +1 -0
  263. package/lib/mass/core/massSidePanels.d.ts +28 -0
  264. package/lib/mass/core/massSidePanels.d.ts.map +1 -0
  265. package/lib/mass/core/massSidePanels.js +12 -0
  266. package/lib/mass/core/massSidePanels.js.map +1 -0
  267. package/lib/mass/core/massSpectrum.d.ts +206 -0
  268. package/lib/mass/core/massSpectrum.d.ts.map +1 -0
  269. package/lib/mass/core/massSpectrum.js +41 -0
  270. package/lib/mass/core/massSpectrum.js.map +1 -0
  271. package/lib/mass/core/massState.d.ts +145 -0
  272. package/lib/mass/core/massState.d.ts.map +1 -0
  273. package/lib/mass/core/massState.js +102 -0
  274. package/lib/mass/core/massState.js.map +1 -0
  275. package/lib/mass/core/massStateEdits.d.ts +51 -0
  276. package/lib/mass/core/massStateEdits.d.ts.map +1 -0
  277. package/lib/mass/core/massStateEdits.js +90 -0
  278. package/lib/mass/core/massStateEdits.js.map +1 -0
  279. package/lib/mass/core/massSummary.d.ts +77 -0
  280. package/lib/mass/core/massSummary.d.ts.map +1 -0
  281. package/lib/mass/core/massSummary.js +174 -0
  282. package/lib/mass/core/massSummary.js.map +1 -0
  283. package/lib/mass/core/mzDecimalsSetting.d.ts +36 -0
  284. package/lib/mass/core/mzDecimalsSetting.d.ts.map +1 -0
  285. package/lib/mass/core/mzDecimalsSetting.js +42 -0
  286. package/lib/mass/core/mzDecimalsSetting.js.map +1 -0
  287. package/lib/mass/core/nearestPeak.d.ts +75 -0
  288. package/lib/mass/core/nearestPeak.d.ts.map +1 -0
  289. package/lib/mass/core/nearestPeak.js +99 -0
  290. package/lib/mass/core/nearestPeak.js.map +1 -0
  291. package/lib/mass/core/peakLabelLines.d.ts +77 -0
  292. package/lib/mass/core/peakLabelLines.d.ts.map +1 -0
  293. package/lib/mass/core/peakLabelLines.js +54 -0
  294. package/lib/mass/core/peakLabelLines.js.map +1 -0
  295. package/lib/mass/core/peakLabelPlan.d.ts +109 -0
  296. package/lib/mass/core/peakLabelPlan.d.ts.map +1 -0
  297. package/lib/mass/core/peakLabelPlan.js +143 -0
  298. package/lib/mass/core/peakLabelPlan.js.map +1 -0
  299. package/lib/mass/core/peakTable.d.ts +54 -0
  300. package/lib/mass/core/peakTable.d.ts.map +1 -0
  301. package/lib/mass/core/peakTable.js +53 -0
  302. package/lib/mass/core/peakTable.js.map +1 -0
  303. package/lib/mass/core/resolutionOf.d.ts +60 -0
  304. package/lib/mass/core/resolutionOf.d.ts.map +1 -0
  305. package/lib/mass/core/resolutionOf.js +84 -0
  306. package/lib/mass/core/resolutionOf.js.map +1 -0
  307. package/lib/mass/core/scanFilter.d.ts +25 -0
  308. package/lib/mass/core/scanFilter.d.ts.map +1 -0
  309. package/lib/mass/core/scanFilter.js +107 -0
  310. package/lib/mass/core/scanFilter.js.map +1 -0
  311. package/lib/mass/core/spectrumJcamp.d.ts +47 -0
  312. package/lib/mass/core/spectrumJcamp.d.ts.map +1 -0
  313. package/lib/mass/core/spectrumJcamp.js +167 -0
  314. package/lib/mass/core/spectrumJcamp.js.map +1 -0
  315. package/lib/mass/core/toMassSpectrum.d.ts +67 -0
  316. package/lib/mass/core/toMassSpectrum.d.ts.map +1 -0
  317. package/lib/mass/core/toMassSpectrum.js +78 -0
  318. package/lib/mass/core/toMassSpectrum.js.map +1 -0
  319. package/lib/mass/core/traceIcon.d.ts +82 -0
  320. package/lib/mass/core/traceIcon.d.ts.map +1 -0
  321. package/lib/mass/core/traceIcon.js +66 -0
  322. package/lib/mass/core/traceIcon.js.map +1 -0
  323. package/lib/mass/core/writtenResolution.d.ts +40 -0
  324. package/lib/mass/core/writtenResolution.d.ts.map +1 -0
  325. package/lib/mass/core/writtenResolution.js +77 -0
  326. package/lib/mass/core/writtenResolution.js.map +1 -0
  327. package/lib/mass/ui/MassAboutDialog.d.ts +16 -0
  328. package/lib/mass/ui/MassAboutDialog.d.ts.map +1 -0
  329. package/lib/mass/ui/MassAboutDialog.js +44 -0
  330. package/lib/mass/ui/MassAboutDialog.js.map +1 -0
  331. package/lib/mass/ui/MassCanvas.d.ts +46 -0
  332. package/lib/mass/ui/MassCanvas.d.ts.map +1 -0
  333. package/lib/mass/ui/MassCanvas.js +84 -0
  334. package/lib/mass/ui/MassCanvas.js.map +1 -0
  335. package/lib/mass/ui/MassChart.d.ts +21 -0
  336. package/lib/mass/ui/MassChart.d.ts.map +1 -0
  337. package/lib/mass/ui/MassChart.js +139 -0
  338. package/lib/mass/ui/MassChart.js.map +1 -0
  339. package/lib/mass/ui/MassCommandProvider.d.ts +15 -0
  340. package/lib/mass/ui/MassCommandProvider.d.ts.map +1 -0
  341. package/lib/mass/ui/MassCommandProvider.js +14 -0
  342. package/lib/mass/ui/MassCommandProvider.js.map +1 -0
  343. package/lib/mass/ui/MassCommandTooltip.d.ts +16 -0
  344. package/lib/mass/ui/MassCommandTooltip.d.ts.map +1 -0
  345. package/lib/mass/ui/MassCommandTooltip.js +22 -0
  346. package/lib/mass/ui/MassCommandTooltip.js.map +1 -0
  347. package/lib/mass/ui/MassDocumentationDialog.d.ts +18 -0
  348. package/lib/mass/ui/MassDocumentationDialog.d.ts.map +1 -0
  349. package/lib/mass/ui/MassDocumentationDialog.js +70 -0
  350. package/lib/mass/ui/MassDocumentationDialog.js.map +1 -0
  351. package/lib/mass/ui/MassEditor.d.ts +78 -0
  352. package/lib/mass/ui/MassEditor.d.ts.map +1 -0
  353. package/lib/mass/ui/MassEditor.js +42 -0
  354. package/lib/mass/ui/MassEditor.js.map +1 -0
  355. package/lib/mass/ui/MassHeader.d.ts +12 -0
  356. package/lib/mass/ui/MassHeader.d.ts.map +1 -0
  357. package/lib/mass/ui/MassHeader.js +20 -0
  358. package/lib/mass/ui/MassHeader.js.map +1 -0
  359. package/lib/mass/ui/MassLogo.d.ts +21 -0
  360. package/lib/mass/ui/MassLogo.d.ts.map +1 -0
  361. package/lib/mass/ui/MassLogo.js +36 -0
  362. package/lib/mass/ui/MassLogo.js.map +1 -0
  363. package/lib/mass/ui/MassPointerTracker.d.ts +44 -0
  364. package/lib/mass/ui/MassPointerTracker.d.ts.map +1 -0
  365. package/lib/mass/ui/MassPointerTracker.js +29 -0
  366. package/lib/mass/ui/MassPointerTracker.js.map +1 -0
  367. package/lib/mass/ui/MassShell.d.ts +29 -0
  368. package/lib/mass/ui/MassShell.d.ts.map +1 -0
  369. package/lib/mass/ui/MassShell.js +133 -0
  370. package/lib/mass/ui/MassShell.js.map +1 -0
  371. package/lib/mass/ui/MassSidePanel.d.ts +32 -0
  372. package/lib/mass/ui/MassSidePanel.d.ts.map +1 -0
  373. package/lib/mass/ui/MassSidePanel.js +44 -0
  374. package/lib/mass/ui/MassSidePanel.js.map +1 -0
  375. package/lib/mass/ui/MassStateProvider.d.ts +19 -0
  376. package/lib/mass/ui/MassStateProvider.d.ts.map +1 -0
  377. package/lib/mass/ui/MassStateProvider.js +16 -0
  378. package/lib/mass/ui/MassStateProvider.js.map +1 -0
  379. package/lib/mass/ui/MassStatusBar.d.ts +15 -0
  380. package/lib/mass/ui/MassStatusBar.d.ts.map +1 -0
  381. package/lib/mass/ui/MassStatusBar.js +50 -0
  382. package/lib/mass/ui/MassStatusBar.js.map +1 -0
  383. package/lib/mass/ui/MassToolbar.d.ts +24 -0
  384. package/lib/mass/ui/MassToolbar.d.ts.map +1 -0
  385. package/lib/mass/ui/MassToolbar.js +36 -0
  386. package/lib/mass/ui/MassToolbar.js.map +1 -0
  387. package/lib/mass/ui/MetadataPanel.d.ts +35 -0
  388. package/lib/mass/ui/MetadataPanel.d.ts.map +1 -0
  389. package/lib/mass/ui/MetadataPanel.js +100 -0
  390. package/lib/mass/ui/MetadataPanel.js.map +1 -0
  391. package/lib/mass/ui/MzDecimalsMenu.d.ts +28 -0
  392. package/lib/mass/ui/MzDecimalsMenu.d.ts.map +1 -0
  393. package/lib/mass/ui/MzDecimalsMenu.js +40 -0
  394. package/lib/mass/ui/MzDecimalsMenu.js.map +1 -0
  395. package/lib/mass/ui/PeakLabels.d.ts +93 -0
  396. package/lib/mass/ui/PeakLabels.d.ts.map +1 -0
  397. package/lib/mass/ui/PeakLabels.js +91 -0
  398. package/lib/mass/ui/PeakLabels.js.map +1 -0
  399. package/lib/mass/ui/PeakTable.d.ts +34 -0
  400. package/lib/mass/ui/PeakTable.d.ts.map +1 -0
  401. package/lib/mass/ui/PeakTable.js +49 -0
  402. package/lib/mass/ui/PeakTable.js.map +1 -0
  403. package/lib/mass/ui/PeaksPanel.d.ts +31 -0
  404. package/lib/mass/ui/PeaksPanel.d.ts.map +1 -0
  405. package/lib/mass/ui/PeaksPanel.js +53 -0
  406. package/lib/mass/ui/PeaksPanel.js.map +1 -0
  407. package/lib/mass/ui/SpectraPanel.d.ts +17 -0
  408. package/lib/mass/ui/SpectraPanel.d.ts.map +1 -0
  409. package/lib/mass/ui/SpectraPanel.js +76 -0
  410. package/lib/mass/ui/SpectraPanel.js.map +1 -0
  411. package/lib/mass/ui/SpectrumRow.d.ts +26 -0
  412. package/lib/mass/ui/SpectrumRow.d.ts.map +1 -0
  413. package/lib/mass/ui/SpectrumRow.js +141 -0
  414. package/lib/mass/ui/SpectrumRow.js.map +1 -0
  415. package/lib/mass/ui/SpectrumTrace.d.ts +46 -0
  416. package/lib/mass/ui/SpectrumTrace.d.ts.map +1 -0
  417. package/lib/mass/ui/SpectrumTrace.js +68 -0
  418. package/lib/mass/ui/SpectrumTrace.js.map +1 -0
  419. package/lib/mass/ui/index.d.ts +69 -0
  420. package/lib/mass/ui/index.d.ts.map +1 -0
  421. package/lib/mass/ui/index.js +42 -0
  422. package/lib/mass/ui/index.js.map +1 -0
  423. package/lib/mass/ui/massActions.d.ts +52 -0
  424. package/lib/mass/ui/massActions.d.ts.map +1 -0
  425. package/lib/mass/ui/massActions.js +62 -0
  426. package/lib/mass/ui/massActions.js.map +1 -0
  427. package/lib/mass/ui/massChartProps.d.ts +128 -0
  428. package/lib/mass/ui/massChartProps.d.ts.map +1 -0
  429. package/lib/mass/ui/massChartProps.js +14 -0
  430. package/lib/mass/ui/massChartProps.js.map +1 -0
  431. package/lib/mass/ui/massCommandContext.d.ts +36 -0
  432. package/lib/mass/ui/massCommandContext.d.ts.map +1 -0
  433. package/lib/mass/ui/massCommandContext.js +45 -0
  434. package/lib/mass/ui/massCommandContext.js.map +1 -0
  435. package/lib/mass/ui/massHostPanels.d.ts +48 -0
  436. package/lib/mass/ui/massHostPanels.d.ts.map +1 -0
  437. package/lib/mass/ui/massHostPanels.js +41 -0
  438. package/lib/mass/ui/massHostPanels.js.map +1 -0
  439. package/lib/mass/ui/massStateContext.d.ts +26 -0
  440. package/lib/mass/ui/massStateContext.d.ts.map +1 -0
  441. package/lib/mass/ui/massStateContext.js +37 -0
  442. package/lib/mass/ui/massStateContext.js.map +1 -0
  443. package/lib/mass/ui/useIntensityZoom.d.ts +20 -0
  444. package/lib/mass/ui/useIntensityZoom.d.ts.map +1 -0
  445. package/lib/mass/ui/useIntensityZoom.js +42 -0
  446. package/lib/mass/ui/useIntensityZoom.js.map +1 -0
  447. package/lib/mass/ui/useMassEditor.d.ts +52 -0
  448. package/lib/mass/ui/useMassEditor.d.ts.map +1 -0
  449. package/lib/mass/ui/useMassEditor.js +93 -0
  450. package/lib/mass/ui/useMassEditor.js.map +1 -0
  451. package/lib/mass/ui/useMassFiles.d.ts +22 -0
  452. package/lib/mass/ui/useMassFiles.d.ts.map +1 -0
  453. package/lib/mass/ui/useMassFiles.js +71 -0
  454. package/lib/mass/ui/useMassFiles.js.map +1 -0
  455. package/lib/mass/ui/useMassHandle.d.ts +15 -0
  456. package/lib/mass/ui/useMassHandle.d.ts.map +1 -0
  457. package/lib/mass/ui/useMassHandle.js +35 -0
  458. package/lib/mass/ui/useMassHandle.js.map +1 -0
  459. package/lib/mass/ui/useMassPointer.d.ts +70 -0
  460. package/lib/mass/ui/useMassPointer.d.ts.map +1 -0
  461. package/lib/mass/ui/useMassPointer.js +57 -0
  462. package/lib/mass/ui/useMassPointer.js.map +1 -0
  463. package/lib/mass/ui/useMassShortcuts.d.ts +21 -0
  464. package/lib/mass/ui/useMassShortcuts.d.ts.map +1 -0
  465. package/lib/mass/ui/useMassShortcuts.js +66 -0
  466. package/lib/mass/ui/useMassShortcuts.js.map +1 -0
  467. package/lib/mass/ui/useMassSide.d.ts +27 -0
  468. package/lib/mass/ui/useMassSide.d.ts.map +1 -0
  469. package/lib/mass/ui/useMassSide.js +45 -0
  470. package/lib/mass/ui/useMassSide.js.map +1 -0
  471. package/lib/mass/ui/useMassZoom.d.ts +92 -0
  472. package/lib/mass/ui/useMassZoom.d.ts.map +1 -0
  473. package/lib/mass/ui/useMassZoom.js +65 -0
  474. package/lib/mass/ui/useMassZoom.js.map +1 -0
  475. package/lib/mass.d.ts +16 -0
  476. package/lib/mass.d.ts.map +1 -0
  477. package/lib/mass.js +16 -0
  478. package/lib/mass.js.map +1 -0
  479. package/lib/panel/ui/PanelRail.d.ts.map +1 -1
  480. package/lib/panel/ui/PanelRail.js +6 -1
  481. package/lib/panel/ui/PanelRail.js.map +1 -1
  482. package/lib/slides/ui/slideSanitizeSchema.d.ts +3 -2
  483. package/lib/slides/ui/slideSanitizeSchema.d.ts.map +1 -1
  484. package/lib/slides/ui/slideSanitizeSchema.js +82 -2
  485. package/lib/slides/ui/slideSanitizeSchema.js.map +1 -1
  486. package/package.json +6 -1
  487. package/src/about/core/providers.ts +7 -0
  488. package/src/about/ui/AboutProvidedBy.tsx +49 -0
  489. package/src/chart/ui/useChartPointer.ts +18 -4
  490. package/src/credits/core/credits.ts +53 -0
  491. package/src/download/core/drawingMarkup.ts +18 -1
  492. package/src/download/core/figurePng.ts +21 -8
  493. package/src/download/core/figureSvg.ts +5 -2
  494. package/src/download/core/figureTarget.ts +28 -3
  495. package/src/download/core/svgBounds.ts +21 -0
  496. package/src/download/core/svgToPng.ts +3 -4
  497. package/src/format/core/relativeTime.ts +29 -7
  498. package/src/host/core/connectHost.ts +77 -120
  499. package/src/host/core/hostOutputs.ts +197 -0
  500. package/src/host/core/index.ts +13 -7
  501. package/src/host/core/irKinds.ts +92 -0
  502. package/src/host/core/kinds.ts +16 -6
  503. package/src/host/core/protocol.ts +50 -8
  504. package/src/host/core/selectInputs.ts +145 -0
  505. package/src/host/testing/sciPeaks.ts +140 -0
  506. package/src/host/testing/standInHost.ts +30 -5
  507. package/src/host/ui/useHostConnection.ts +17 -8
  508. package/src/host-testing.ts +4 -0
  509. package/src/ir/core/handPicking.ts +154 -0
  510. package/src/ir/core/index.ts +14 -0
  511. package/src/ir/core/irBandState.ts +155 -0
  512. package/src/ir/core/irCommands.ts +7 -0
  513. package/src/ir/core/irPeaks.ts +79 -0
  514. package/src/ir/core/irReducer.ts +27 -34
  515. package/src/ir/core/irSpectrum.ts +16 -0
  516. package/src/ir/core/irState.ts +15 -8
  517. package/src/ir/core/pickBands.ts +46 -39
  518. package/src/ir/core/ramanBands.ts +2 -2
  519. package/src/ir/core/spectrumBands.ts +113 -0
  520. package/src/ir/ui/BandRow.tsx +20 -2
  521. package/src/ir/ui/BandsPanel.tsx +46 -88
  522. package/src/ir/ui/BandsToolbar.tsx +152 -0
  523. package/src/ir/ui/IrCanvas.tsx +22 -11
  524. package/src/ir/ui/IrChart.tsx +10 -1
  525. package/src/ir/ui/IrDocumentationDialog.tsx +7 -0
  526. package/src/ir/ui/IrEditor.tsx +4 -2
  527. package/src/ir/ui/IrShell.tsx +5 -0
  528. package/src/ir/ui/IrStatusBar.tsx +4 -1
  529. package/src/ir/ui/IrToolbar.tsx +14 -5
  530. package/src/ir/ui/VibrationalEditor.tsx +2 -1
  531. package/src/ir/ui/irActions.ts +11 -0
  532. package/src/ir/ui/irChartProps.ts +4 -1
  533. package/src/ir/ui/useIrEditor.ts +21 -21
  534. package/src/locales/de.json +63 -0
  535. package/src/locales/en.json +63 -0
  536. package/src/locales/es.json +63 -0
  537. package/src/locales/fr.json +63 -0
  538. package/src/locales/it.json +63 -0
  539. package/src/mass/core/analyseSpectrum.ts +191 -0
  540. package/src/mass/core/ascendingTrace.ts +62 -0
  541. package/src/mass/core/centroidPeaks.ts +114 -0
  542. package/src/mass/core/detectMassFormat.ts +113 -0
  543. package/src/mass/core/downloadSpectra.ts +52 -0
  544. package/src/mass/core/fromJcamp.ts +151 -0
  545. package/src/mass/core/fromText.ts +58 -0
  546. package/src/mass/core/index.ts +194 -0
  547. package/src/mass/core/jcampTechnique.ts +87 -0
  548. package/src/mass/core/labelStackBox.ts +75 -0
  549. package/src/mass/core/labelledPeaks.ts +135 -0
  550. package/src/mass/core/loadMassSpectra.ts +86 -0
  551. package/src/mass/core/loadedMassSpectrum.ts +43 -0
  552. package/src/mass/core/massCommands.ts +156 -0
  553. package/src/mass/core/massDomain.ts +229 -0
  554. package/src/mass/core/massEditorApi.ts +68 -0
  555. package/src/mass/core/massFormat.ts +187 -0
  556. package/src/mass/core/massMeta.ts +239 -0
  557. package/src/mass/core/massReducer.ts +232 -0
  558. package/src/mass/core/massResolution.ts +169 -0
  559. package/src/mass/core/massSidePanels.ts +27 -0
  560. package/src/mass/core/massSpectrum.ts +220 -0
  561. package/src/mass/core/massState.ts +206 -0
  562. package/src/mass/core/massStateEdits.ts +104 -0
  563. package/src/mass/core/massSummary.ts +213 -0
  564. package/src/mass/core/mzDecimalsSetting.ts +52 -0
  565. package/src/mass/core/nearestPeak.ts +130 -0
  566. package/src/mass/core/peakLabelLines.ts +112 -0
  567. package/src/mass/core/peakLabelPlan.ts +246 -0
  568. package/src/mass/core/peakTable.ts +82 -0
  569. package/src/mass/core/resolutionOf.ts +100 -0
  570. package/src/mass/core/scanFilter.ts +119 -0
  571. package/src/mass/core/spectrumJcamp.ts +186 -0
  572. package/src/mass/core/toMassSpectrum.ts +126 -0
  573. package/src/mass/core/traceIcon.ts +105 -0
  574. package/src/mass/core/writtenResolution.ts +81 -0
  575. package/src/mass/ui/MassAboutDialog.tsx +89 -0
  576. package/src/mass/ui/MassCanvas.tsx +170 -0
  577. package/src/mass/ui/MassChart.tsx +266 -0
  578. package/src/mass/ui/MassCommandProvider.tsx +34 -0
  579. package/src/mass/ui/MassCommandTooltip.tsx +36 -0
  580. package/src/mass/ui/MassDocumentationDialog.tsx +136 -0
  581. package/src/mass/ui/MassEditor.tsx +130 -0
  582. package/src/mass/ui/MassHeader.tsx +38 -0
  583. package/src/mass/ui/MassLogo.tsx +84 -0
  584. package/src/mass/ui/MassPointerTracker.tsx +72 -0
  585. package/src/mass/ui/MassShell.tsx +237 -0
  586. package/src/mass/ui/MassSidePanel.tsx +107 -0
  587. package/src/mass/ui/MassStateProvider.tsx +32 -0
  588. package/src/mass/ui/MassStatusBar.tsx +108 -0
  589. package/src/mass/ui/MassToolbar.tsx +120 -0
  590. package/src/mass/ui/MetadataPanel.tsx +201 -0
  591. package/src/mass/ui/MzDecimalsMenu.tsx +86 -0
  592. package/src/mass/ui/PeakLabels.tsx +242 -0
  593. package/src/mass/ui/PeakTable.tsx +199 -0
  594. package/src/mass/ui/PeaksPanel.tsx +182 -0
  595. package/src/mass/ui/SpectraPanel.tsx +153 -0
  596. package/src/mass/ui/SpectrumRow.tsx +246 -0
  597. package/src/mass/ui/SpectrumTrace.tsx +119 -0
  598. package/src/mass/ui/index.ts +69 -0
  599. package/src/mass/ui/massActions.ts +109 -0
  600. package/src/mass/ui/massChartProps.ts +130 -0
  601. package/src/mass/ui/massCommandContext.tsx +65 -0
  602. package/src/mass/ui/massHostPanels.ts +71 -0
  603. package/src/mass/ui/massStateContext.ts +48 -0
  604. package/src/mass/ui/useIntensityZoom.ts +55 -0
  605. package/src/mass/ui/useMassEditor.ts +156 -0
  606. package/src/mass/ui/useMassFiles.ts +91 -0
  607. package/src/mass/ui/useMassHandle.ts +58 -0
  608. package/src/mass/ui/useMassPointer.ts +120 -0
  609. package/src/mass/ui/useMassShortcuts.ts +85 -0
  610. package/src/mass/ui/useMassSide.ts +63 -0
  611. package/src/mass/ui/useMassZoom.ts +157 -0
  612. package/src/mass.ts +16 -0
  613. package/src/panel/ui/PanelRail.tsx +5 -1
  614. package/src/slides/ui/slideSanitizeSchema.ts +86 -2
  615. package/styles/chrome.css +7 -0
  616. package/styles/slides.css +47 -0
@@ -1,21 +1,19 @@
1
- import { useMemo } from 'react';
2
- import { Button, Toolbar } from 'react-science/ui';
3
-
4
1
  import {
5
2
  panelBodyStyle,
6
3
  panelEmptyStyle,
7
4
  panelHeaderCellStyle,
8
5
  panelStyle,
9
6
  panelTableStyle,
10
- panelToolbarStyle,
11
7
  } from '../../panel/core/panelStyles.ts';
8
+ import { removeBand } from '../core/handPicking.ts';
12
9
  import type { IrBand } from '../core/irBand.ts';
13
10
  import { sameIrBand } from '../core/irBand.ts';
14
11
  import { shortModeLabel } from '../core/irFormat.ts';
12
+ import type { IrSpectrum } from '../core/irSpectrum.ts';
15
13
  import { IR_TECHNIQUE_RULES } from '../core/irTechnique.ts';
16
14
 
17
15
  import { BandRow } from './BandRow.tsx';
18
- import { bandsToTsv } from './bandsTsv.ts';
16
+ import { BandsToolbar } from './BandsToolbar.tsx';
19
17
  import { useIrActions, useIrEditorState } from './irStateContext.ts';
20
18
 
21
19
  export interface BandsPanelProps {
@@ -45,6 +43,11 @@ export interface BandsPanelProps {
45
43
  * row, which is the whole reason the highlight is threaded through the shell
46
44
  * rather than held here: the two views are of one thing.
47
45
  *
46
+ * The list is the spectrum's own and can be edited: a band is taken away from
47
+ * its row, added by a click on the chart while picking by hand, and the whole
48
+ * list found automatically again. Once edited it is the spectrum's as picked
49
+ * by hand, and the threshold no longer moves it.
50
+ *
48
51
  * For a technique the correlation table does not cover — Raman — the column of
49
52
  * candidates and the button naming them are left out, and the table is the
50
53
  * bands themselves.
@@ -55,89 +58,25 @@ export function BandsPanel(props: BandsPanelProps) {
55
58
  const { highlight = null, onHighlight } = props;
56
59
  const { state, selectedSpectrum, assigned } = useIrEditorState();
57
60
  const actions = useIrActions();
58
- const { mode, pickBands, showAssignments, picking, technique } =
59
- state.settings;
61
+ const { mode, pickBands, technique } = state.settings;
60
62
  const { assignments } = IR_TECHNIQUE_RULES[technique];
63
+ const empty = emptyMessage(selectedSpectrum, pickBands, assigned.length);
61
64
 
62
- const rows = useMemo(() => assigned, [assigned]);
63
-
64
- const tsv = useMemo(
65
- () => bandsToTsv(rows, mode, assignments),
66
- [rows, mode, assignments],
67
- );
65
+ function remove(band: IrBand): void {
66
+ if (selectedSpectrum === null) return;
67
+ actions.setBands(
68
+ selectedSpectrum.id,
69
+ removeBand(selectedSpectrum.bands ?? [], band.wavenumber),
70
+ );
71
+ onHighlight?.(null);
72
+ }
68
73
 
69
74
  return (
70
75
  <div style={panelStyle}>
71
- <div style={panelToolbarStyle}>
72
- <Toolbar aria-label="Band actions">
73
- <Toolbar.Item
74
- icon="locate"
75
- active={pickBands}
76
- tooltip={pickBands ? 'Stop picking bands' : 'Pick the bands'}
77
- aria-label="Pick the bands"
78
- onClick={() => actions.setSettings({ pickBands: !pickBands })}
79
- />
80
- {assignments ? (
81
- <Toolbar.Item
82
- icon="label"
83
- active={showAssignments}
84
- tooltip="Name the assignments on the chart"
85
- aria-label="Name the assignments on the chart"
86
- disabled={!pickBands}
87
- onClick={() =>
88
- actions.setSettings({ showAssignments: !showAssignments })
89
- }
90
- />
91
- ) : null}
92
- </Toolbar>
93
-
94
- {/* The threshold is the one picking setting worth reaching for while
95
- reading: everything else about a band follows from the spectrum, and
96
- this is what decides whether a shoulder is a band at all. */}
97
- <label style={thresholdStyle}>
98
- <span style={{ opacity: 0.7 }}>threshold</span>
99
- <input
100
- type="range"
101
- min={0.005}
102
- max={0.3}
103
- step={0.005}
104
- value={picking.minRelativeHeight ?? 0.02}
105
- disabled={!pickBands}
106
- aria-label="How tall a band must be to be picked"
107
- onChange={(event) =>
108
- actions.setSettings({
109
- picking: { minRelativeHeight: event.target.valueAsNumber },
110
- })
111
- }
112
- />
113
- </label>
114
-
115
- <span style={{ flex: 1 }} />
116
-
117
- <Button
118
- variant="minimal"
119
- icon="clipboard"
120
- disabled={rows.length === 0}
121
- tooltipProps={{ content: 'Copy the table' }}
122
- aria-label="Copy the table"
123
- onClick={() => void navigator.clipboard?.writeText(tsv)}
124
- />
125
- </div>
76
+ <BandsToolbar />
126
77
 
127
78
  <div style={panelBodyStyle}>
128
- {selectedSpectrum === null ? (
129
- <p style={panelEmptyStyle}>No spectrum is selected.</p>
130
- ) : !pickBands ? (
131
- <p style={panelEmptyStyle}>
132
- The bands are not being picked. Press the locate button above to
133
- find them.
134
- </p>
135
- ) : rows.length === 0 ? (
136
- <p style={panelEmptyStyle}>
137
- No band was found above the threshold. Lower it to pick the weaker
138
- ones.
139
- </p>
140
- ) : (
79
+ {empty === null ? (
141
80
  <table style={panelTableStyle}>
142
81
  <thead>
143
82
  <tr>
@@ -149,10 +88,11 @@ export function BandsPanel(props: BandsPanelProps) {
149
88
  {assignments ? (
150
89
  <th style={panelHeaderCellStyle}>could be</th>
151
90
  ) : null}
91
+ <th style={panelHeaderCellStyle} />
152
92
  </tr>
153
93
  </thead>
154
94
  <tbody>
155
- {rows.map((entry) => (
95
+ {assigned.map((entry) => (
156
96
  <BandRow
157
97
  key={`${entry.band.spectrumId} ${entry.band.wavenumber}`}
158
98
  entry={entry}
@@ -160,19 +100,37 @@ export function BandsPanel(props: BandsPanelProps) {
160
100
  assignments={assignments}
161
101
  lit={sameIrBand(entry.band, highlight)}
162
102
  onHighlight={onHighlight}
103
+ onRemove={remove}
163
104
  />
164
105
  ))}
165
106
  </tbody>
166
107
  </table>
108
+ ) : (
109
+ <p style={panelEmptyStyle}>{empty}</p>
167
110
  )}
168
111
  </div>
169
112
  </div>
170
113
  );
171
114
  }
172
115
 
173
- const thresholdStyle = {
174
- display: 'inline-flex',
175
- alignItems: 'center',
176
- gap: 4,
177
- fontSize: 11,
178
- } as const;
116
+ /**
117
+ * What the panel says in place of the table, when it has no band to list.
118
+ * @param spectrum - The selected spectrum, `null` for none.
119
+ * @param picking - Whether the bands are picked at all.
120
+ * @param count - How many bands there are to list.
121
+ * @returns The sentence, or `null` when there is a table to show.
122
+ */
123
+ function emptyMessage(
124
+ spectrum: IrSpectrum | null,
125
+ picking: boolean,
126
+ count: number,
127
+ ): string | null {
128
+ if (spectrum === null) return 'No spectrum is selected.';
129
+ if (!picking) {
130
+ return 'The bands are not being picked. Press the locate button above to find them.';
131
+ }
132
+ if (count > 0) return null;
133
+ return spectrum.bandsByHand
134
+ ? 'No band is picked. Click the chart while picking by hand, or find them automatically again.'
135
+ : 'No band was found above the threshold. Lower it to pick the weaker ones.';
136
+ }
@@ -0,0 +1,152 @@
1
+ import { useMemo } from 'react';
2
+ import { Button, Toolbar } from 'react-science/ui';
3
+
4
+ import { panelToolbarStyle } from '../../panel/core/panelStyles.ts';
5
+ import { IR_TECHNIQUE_RULES } from '../core/irTechnique.ts';
6
+
7
+ import { bandsToTsv } from './bandsTsv.ts';
8
+ import { useIrCommandProps } from './irCommandContext.tsx';
9
+ import { useIrActions, useIrEditorState } from './irStateContext.ts';
10
+
11
+ /**
12
+ * The row at the top of the bands panel: the switches — picking at all,
13
+ * picking by hand, naming the assignments — then the threshold, then what
14
+ * acts at once, apart from them on the right: finding the bands automatically
15
+ * again, taking every band away, copying the table.
16
+ * @returns The row.
17
+ */
18
+ export function BandsToolbar() {
19
+ const { state, selectedSpectrum, assigned } = useIrEditorState();
20
+ const actions = useIrActions();
21
+ const command = useIrCommandProps();
22
+ const { tool } = state.view;
23
+ const { mode, pickBands, showAssignments, technique } = state.settings;
24
+ const { assignments } = IR_TECHNIQUE_RULES[technique];
25
+ const byHand = selectedSpectrum?.bandsByHand === true;
26
+
27
+ const tsv = useMemo(
28
+ () => bandsToTsv(assigned, mode, assignments),
29
+ [assigned, mode, assignments],
30
+ );
31
+
32
+ return (
33
+ <div style={panelToolbarStyle}>
34
+ <Toolbar aria-label="Band actions">
35
+ <Toolbar.Item
36
+ icon="locate"
37
+ active={pickBands}
38
+ tooltip={pickBands ? 'Stop picking bands' : 'Pick the bands'}
39
+ aria-label="Pick the bands"
40
+ onClick={() => actions.setSettings({ pickBands: !pickBands })}
41
+ />
42
+ <Toolbar.Item
43
+ icon="add-location"
44
+ active={tool === 'pick'}
45
+ {...command('pickTool')}
46
+ disabled={selectedSpectrum === null}
47
+ />
48
+ {assignments ? (
49
+ <Toolbar.Item
50
+ icon="label"
51
+ active={showAssignments}
52
+ tooltip="Name the assignments on the chart"
53
+ aria-label="Name the assignments on the chart"
54
+ disabled={!pickBands}
55
+ onClick={() =>
56
+ actions.setSettings({ showAssignments: !showAssignments })
57
+ }
58
+ />
59
+ ) : null}
60
+ </Toolbar>
61
+
62
+ <ThresholdSlider />
63
+
64
+ <span style={{ flex: 1 }} />
65
+
66
+ <Button
67
+ variant="minimal"
68
+ icon="refresh"
69
+ disabled={!pickBands || !byHand}
70
+ tooltipProps={{ content: 'Find the bands automatically again' }}
71
+ aria-label="Find the bands automatically again"
72
+ onClick={() => {
73
+ if (selectedSpectrum !== null) {
74
+ actions.resetBands(selectedSpectrum.id);
75
+ }
76
+ }}
77
+ />
78
+ <Button
79
+ variant="minimal"
80
+ icon="eraser"
81
+ disabled={!pickBands || assigned.length === 0}
82
+ tooltipProps={{ content: 'Take every band away, to pick them by hand' }}
83
+ aria-label="Take every band away"
84
+ onClick={() => {
85
+ if (selectedSpectrum !== null) {
86
+ actions.setBands(selectedSpectrum.id, []);
87
+ }
88
+ }}
89
+ />
90
+ <Button
91
+ variant="minimal"
92
+ icon="clipboard"
93
+ disabled={assigned.length === 0}
94
+ tooltipProps={{ content: 'Copy the table' }}
95
+ aria-label="Copy the table"
96
+ onClick={() => void navigator.clipboard?.writeText(tsv)}
97
+ />
98
+ </div>
99
+ );
100
+ }
101
+
102
+ /**
103
+ * The threshold, the one picking setting worth reaching for while reading:
104
+ * everything else about a band follows from the spectrum, and this is what
105
+ * decides whether a shoulder is a band at all. Bands picked by hand are not
106
+ * its to move.
107
+ * @returns The labelled slider.
108
+ */
109
+ function ThresholdSlider() {
110
+ const { state, selectedSpectrum } = useIrEditorState();
111
+ const actions = useIrActions();
112
+ const { pickBands, picking } = state.settings;
113
+ const byHand = selectedSpectrum?.bandsByHand === true;
114
+
115
+ return (
116
+ <label
117
+ style={thresholdStyle}
118
+ title={
119
+ byHand
120
+ ? 'The bands were picked by hand: find them automatically again to use the threshold.'
121
+ : undefined
122
+ }
123
+ >
124
+ <span style={{ opacity: 0.7 }}>threshold</span>
125
+ <input
126
+ type="range"
127
+ min={0.005}
128
+ max={0.3}
129
+ step={0.005}
130
+ style={sliderStyle}
131
+ value={picking.minRelativeHeight ?? 0.02}
132
+ disabled={!pickBands || byHand}
133
+ aria-label="How tall a band must be to be picked"
134
+ onChange={(event) =>
135
+ actions.setSettings({
136
+ picking: { minRelativeHeight: event.target.valueAsNumber },
137
+ })
138
+ }
139
+ />
140
+ </label>
141
+ );
142
+ }
143
+
144
+ const thresholdStyle = {
145
+ display: 'inline-flex',
146
+ alignItems: 'center',
147
+ gap: 4,
148
+ fontSize: 11,
149
+ } as const;
150
+
151
+ /** Narrower than the browser's own, so the row holds every control at 360 px. */
152
+ const sliderStyle = { width: 88 } as const;
@@ -1,5 +1,6 @@
1
1
  import { useCallback, useMemo } from 'react';
2
2
 
3
+ import { editBandsAt } from '../core/handPicking.ts';
3
4
  import type { IrBand } from '../core/irBand.ts';
4
5
  import type { IrPlotClick } from '../core/irEditorApi.ts';
5
6
  import type { IrDomain } from '../core/irSpectrum.ts';
@@ -35,7 +36,8 @@ export interface IrCanvasProps {
35
36
  chartId?: string;
36
37
  /**
37
38
  * Told of a click on the plot — a press let go without travelling, never the
38
- * end of a drag — with the spectrum selected at that moment.
39
+ * end of a drag — with the spectrum selected at that moment. Not told while
40
+ * bands are picked by hand, which is what a click is then.
39
41
  * @default undefined
40
42
  */
41
43
  onPlotClick?: (click: IrPlotClick) => void;
@@ -64,7 +66,8 @@ export function IrCanvas(props: IrCanvasProps) {
64
66
  chartId,
65
67
  onPlotClick,
66
68
  } = props;
67
- const { state, visibleSpectra, assigned } = useIrEditorState();
69
+ const { state, visibleSpectra, selectedSpectrum, assigned } =
70
+ useIrEditorState();
68
71
  const actions = useIrActions();
69
72
  const { domain, tool, selectedId } = state.view;
70
73
  const { technique, mode, showAssignments, labelLimit } = state.settings;
@@ -77,15 +80,23 @@ export function IrCanvas(props: IrCanvasProps) {
77
80
  );
78
81
 
79
82
  // Which spectrum was selected is the viewer's to say, not the chart's: the
80
- // chart only knows where the press landed.
81
- const onClickAt = useMemo(
82
- () =>
83
- onPlotClick === undefined
84
- ? undefined
85
- : (wavenumber: number) =>
86
- onPlotClick({ wavenumber, spectrumId: selectedId }),
87
- [onPlotClick, selectedId],
88
- );
83
+ // chart only knows where the press landed. While picking by hand a click is
84
+ // a band, and is the viewer's own rather than the host's.
85
+ const onClickAt = useMemo(() => {
86
+ if (tool === 'pick') {
87
+ if (selectedSpectrum === null) return undefined;
88
+ return (wavenumber: number, reach: number) => {
89
+ const bands = editBandsAt(selectedSpectrum, wavenumber, reach);
90
+ if (bands !== selectedSpectrum.bands) {
91
+ actions.setBands(selectedSpectrum.id, bands);
92
+ }
93
+ };
94
+ }
95
+ return onPlotClick === undefined
96
+ ? undefined
97
+ : (wavenumber: number) =>
98
+ onPlotClick({ wavenumber, spectrumId: selectedId });
99
+ }, [tool, selectedSpectrum, actions, onPlotClick, selectedId]);
89
100
 
90
101
  return (
91
102
  <div style={rootStyle}>
@@ -11,6 +11,7 @@ import { useChartSize } from '../../chart/ui/useChartSize.ts';
11
11
  import type { AssignedBand } from '../core/assignBands.ts';
12
12
  import type { IrBand } from '../core/irBand.ts';
13
13
  import { irModeFor } from '../core/irTechnique.ts';
14
+ import { BAND_HIT_RADIUS } from '../core/nearestBand.ts';
14
15
 
15
16
  import { BandMarks } from './BandMarks.tsx';
16
17
  import { IrPointerTracker } from './IrPointerTracker.tsx';
@@ -83,11 +84,15 @@ export function IrChart(props: IrChartProps): ReactElement {
83
84
  const frameWidth = plot.right + MARGIN.right;
84
85
  const frameHeight = plot.bottom + MARGIN.bottom;
85
86
 
87
+ // The scale a click is measured against comes out of the zoom the click is
88
+ // handed to, so the handler reads the latest one when the click happens.
89
+ const xFactor = useRef(0);
86
90
  const onClick = useMemo(
87
91
  () =>
88
92
  onPlotClick === undefined
89
93
  ? undefined
90
- : (point: ChartPoint) => onPlotClick(point.x),
94
+ : (point: ChartPoint) =>
95
+ onPlotClick(point.x, BAND_HIT_RADIUS / Math.abs(xFactor.current)),
91
96
  [onPlotClick],
92
97
  );
93
98
 
@@ -111,6 +116,10 @@ export function IrChart(props: IrChartProps): ReactElement {
111
116
  // was dragged over.
112
117
  const { domain: shown, xScale, yScale, selection, handlers } = zoom;
113
118
 
119
+ useLayoutEffect(() => {
120
+ xFactor.current = xScale.factor;
121
+ }, [xScale]);
122
+
114
123
  const reported = useRef(shown);
115
124
  // Before the browser paints, so a host that stores the window and hands it
116
125
  // back does so in the frame the gesture landed in rather than the one after.
@@ -111,6 +111,13 @@ function InfraredGuide() {
111
111
  a row marks the band on the chart, and hovering the chart lights the
112
112
  row.
113
113
  </p>
114
+ <p style={paragraphStyle}>
115
+ The bands are found automatically until you pick them by hand: with the
116
+ hand tool a click on the chart adds the band under it, at its top, and a
117
+ click on a mark takes it away, as does the cross at the end of its row.
118
+ From then on the threshold leaves the list alone, until it is found
119
+ automatically again.
120
+ </p>
114
121
  <p style={paragraphStyle}>
115
122
  A band is reported at the sampled point it peaked on, so on a 4 cm⁻¹
116
123
  grid a carbonyl centred at 1710 reads 1708 or 1712. Do not quote one as
@@ -18,7 +18,8 @@ export interface IrEditorProps {
18
18
  data?: IrSpectrum[];
19
19
  /**
20
20
  * Called whenever the spectra open change — one loaded, one closed, the chart
21
- * cleared — with the spectra now open.
21
+ * cleared, the bands of one picked — with the spectra now open, each carrying
22
+ * its bands.
22
23
  *
23
24
  * The document only. A zoom, a selection, a rename and a colour change what is
24
25
  * being looked at rather than what is loaded, and a host told about those would
@@ -50,7 +51,8 @@ export interface IrEditorProps {
50
51
  panels?: readonly IrHostPanel[];
51
52
  /**
52
53
  * The plot was clicked at this wavenumber (a press that did not travel, i.e.
53
- * not a zoom drag), with the spectrum selected at that moment.
54
+ * not a zoom drag), with the spectrum selected at that moment. Not called
55
+ * while bands are picked by hand: a click is a band then.
54
56
  * @default undefined
55
57
  */
56
58
  onPlotClick?: (click: IrPlotClick) => void;
@@ -92,6 +92,11 @@ export function IrShell(props: IrShellProps) {
92
92
  fullScreen: toggleFullScreen,
93
93
  readTool: () => actions.setTool('read'),
94
94
  boxTool: () => actions.setTool(tool === 'box' ? 'read' : 'box'),
95
+ // Picking by hand is done on the marks, so they are shown for it.
96
+ pickTool: () => {
97
+ actions.setTool(tool === 'pick' ? 'read' : 'pick');
98
+ if (!pickBands) actions.setSettings({ pickBands: true });
99
+ },
95
100
  zoomIn,
96
101
  zoomOut,
97
102
  resetZoom: () => actions.resetDomain(),
@@ -63,11 +63,14 @@ export function IrStatusBar() {
63
63
  {pickBands && assigned.length > 0 ? (
64
64
  <span style={itemStyle}>
65
65
  {countLabel(assigned.length, 'band', 'bands')}
66
+ {selectedSpectrum?.bandsByHand ? ' picked by hand' : null}
66
67
  {assignments ? `, ${countAssigned(assigned)} assigned` : null}
67
68
  </span>
68
69
  ) : null}
69
70
 
70
- {boxZoomOnly(mode) || tool === 'box' ? (
71
+ {tool === 'pick' ? (
72
+ <span style={mutedStyle}>click to add or remove a band</span>
73
+ ) : boxZoomOnly(mode) || tool === 'box' ? (
71
74
  <span style={mutedStyle}>square zoom: drag a rectangle</span>
72
75
  ) : null}
73
76
 
@@ -22,9 +22,10 @@ export interface IrToolbarProps {
22
22
  * The tools, down the left of the chart.
23
23
  *
24
24
  * Only what is done to the spectra: what is asked of the viewer itself — the
25
- * mark, help, full screen — is in the header. The two **tools** — read and
26
- * square zoom — come first and show which of the two a drag is currently
27
- * running, then the zoom commands that act at once, then what is being read: the
25
+ * mark, help, full screen — is in the header. The **tools** — read and square
26
+ * zoom, which say what a drag is running, and picking by hand, which says what
27
+ * a click is — come first, then the zoom commands that act at once, then what
28
+ * is being read: the
28
29
  * value axis, the picking, the assignments. Closing every spectrum is last and
29
30
  * alone, being the only one that throws something away.
30
31
  *
@@ -64,10 +65,12 @@ export function IrToolbar(props: IrToolbarProps) {
64
65
  disabled={isEmpty}
65
66
  />
66
67
  {/* The read tool drags along one axis, so it is drawn as that; the box
67
- tool sweeps a rectangle, which is what a marquee icon means. */}
68
+ tool sweeps a rectangle, which is what a marquee icon means. Picking
69
+ by hand is about a click, and a drag still reads while it is chosen,
70
+ so the two light together. */}
68
71
  <Toolbar.Item
69
72
  icon="arrows-horizontal"
70
- active={!settled && tool === 'read'}
73
+ active={!settled && tool !== 'box'}
71
74
  {...command('readTool')}
72
75
  disabled={isEmpty || settled}
73
76
  />
@@ -77,6 +80,12 @@ export function IrToolbar(props: IrToolbarProps) {
77
80
  {...command('boxTool')}
78
81
  disabled={isEmpty || settled}
79
82
  />
83
+ <Toolbar.Item
84
+ icon="add-location"
85
+ active={tool === 'pick'}
86
+ {...command('pickTool')}
87
+ disabled={selectedSpectrum === null}
88
+ />
80
89
 
81
90
  <Toolbar.Item icon="zoom-in" {...command('zoomIn')} disabled={isEmpty} />
82
91
  <Toolbar.Item
@@ -48,7 +48,8 @@ export interface VibrationalEditorProps {
48
48
  panels?: readonly IrHostPanel[];
49
49
  /**
50
50
  * The plot was clicked at this wavenumber (a press that did not travel, i.e.
51
- * not a zoom drag), with the spectrum selected at that moment.
51
+ * not a zoom drag), with the spectrum selected at that moment. Not called
52
+ * while bands are picked by hand.
52
53
  * @default undefined
53
54
  */
54
55
  onPlotClick?: (click: IrPlotClick) => void;
@@ -8,6 +8,7 @@
8
8
 
9
9
  import type { Dispatch } from 'react';
10
10
 
11
+ import type { IrBand } from '../core/irBand.ts';
11
12
  import type { IrAction } from '../core/irReducer.ts';
12
13
  import type { IrPanelId } from '../core/irSidePanels.ts';
13
14
  import type { IrDomain, IrSpectrum } from '../core/irSpectrum.ts';
@@ -27,6 +28,10 @@ export interface IrEditorActions {
27
28
  setSpectrumColor: (id: string, color: string) => void;
28
29
  /** Draw one, or stop drawing it. */
29
30
  setSpectrumVisible: (id: string, visible: boolean) => void;
31
+ /** Give one these bands, as picked by hand. */
32
+ setBands: (id: string, bands: IrBand[]) => void;
33
+ /** Have one's bands found automatically again, with the settings in force. */
34
+ resetBands: (id: string) => void;
30
35
  /** Point the panels at one, or at none. */
31
36
  selectSpectrum: (id: string | null) => void;
32
37
  /** Show this window. */
@@ -72,6 +77,12 @@ export function createIrActions(dispatch: Dispatch<IrAction>): IrEditorActions {
72
77
  setSpectrumVisible(id, visible) {
73
78
  dispatch({ type: 'setSpectrumVisible', id, visible });
74
79
  },
80
+ setBands(id, bands) {
81
+ dispatch({ type: 'setBands', id, bands });
82
+ },
83
+ resetBands(id) {
84
+ dispatch({ type: 'resetBands', id });
85
+ },
75
86
  selectSpectrum(id) {
76
87
  dispatch({ type: 'selectSpectrum', id });
77
88
  },
@@ -98,9 +98,12 @@ export interface IrChartProps {
98
98
  * Told the wavenumber a click on the plot landed at: a press let go over the
99
99
  * plot without travelling. The end of a drag is never one, nor is a press let
100
100
  * go over the axis labels, which inverts to a value the chart is not drawing.
101
+ *
102
+ * `reach` is how many cm⁻¹ a band's hit radius spans at the zoom the chart is
103
+ * at, so a band the click was aimed at can be told from one it was not.
101
104
  * @default undefined
102
105
  */
103
- onPlotClick?: (wavenumber: number) => void;
106
+ onPlotClick?: (wavenumber: number, reach: number) => void;
104
107
  /**
105
108
  * What a drag across the plot asks for: the wavenumber axis alone, or exactly
106
109
  * the rectangle it sweeps out. A viewer offering a square-zoom tool switches