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
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Reading the files a chemist drops on the chart or picks from a dialog.
3
+ *
4
+ * Every file is read on its own, and one that cannot be read is said rather
5
+ * than stopping the others: a drop of eleven files with one infrared JCAMP among
6
+ * them draws the ten mass spectra and names the eleventh in the status bar.
7
+ */
8
+
9
+ import { useCallback, useMemo } from 'react';
10
+
11
+ import { errorMessage } from '../../error/core/index.ts';
12
+ import type { LoadMassSpectraResult } from '../core/loadMassSpectra.ts';
13
+ import { loadMassSpectra } from '../core/loadMassSpectra.ts';
14
+ import type { MassSpectrum } from '../core/massSpectrum.ts';
15
+ import { toMassSpectra } from '../core/toMassSpectrum.ts';
16
+
17
+ import { useMassActions, useMassEditorState } from './massStateContext.ts';
18
+
19
+ /** How files reach the viewer. */
20
+ export interface MassFiles {
21
+ /**
22
+ * Read these files and add what they hold.
23
+ * @param files - What was dropped or chosen.
24
+ * @returns Once every file has been read.
25
+ */
26
+ readFiles: (files: readonly File[]) => Promise<void>;
27
+ }
28
+
29
+ /**
30
+ * Read files into the viewer this is called inside.
31
+ * @returns How to read them.
32
+ */
33
+ export function useMassFiles(): MassFiles {
34
+ const { state } = useMassEditorState();
35
+ const actions = useMassActions();
36
+ const { spectra: open } = state.data;
37
+
38
+ const readFiles = useCallback(
39
+ async (files: readonly File[]) => {
40
+ // Read together, since each read is the browser's work rather than ours,
41
+ // and then dressed in the order the files were given, so the colours are
42
+ // handed out in that order too.
43
+ const results = await Promise.all(files.map(readFile));
44
+ const colors = open.map((spectrum) => spectrum.color);
45
+ const read: MassSpectrum[] = [];
46
+ const problems: string[] = [];
47
+ for (const [index, result] of results.entries()) {
48
+ const name = files[index]?.name ?? 'A file';
49
+ if (typeof result === 'string') {
50
+ problems.push(result);
51
+ continue;
52
+ }
53
+ try {
54
+ const spectra = toMassSpectra(result.spectra, { taken: colors });
55
+ for (const spectrum of spectra) colors.push(spectrum.color);
56
+ read.push(...spectra);
57
+ } catch (error) {
58
+ problems.push(
59
+ `${name} could not be peak picked — ${errorMessage(error)}`,
60
+ );
61
+ continue;
62
+ }
63
+ if (result.dropped > 0) {
64
+ problems.push(
65
+ `${name} holds ${result.spectra.length + result.dropped} spectra and only the first ${result.spectra.length} were read.`,
66
+ );
67
+ }
68
+ }
69
+ if (read.length > 0) actions.addSpectra(read);
70
+ // After the spectra, which clear any error standing from before.
71
+ if (problems.length > 0) actions.setError(problems.join(' '));
72
+ },
73
+ [actions, open],
74
+ );
75
+
76
+ return useMemo(() => ({ readFiles }), [readFiles]);
77
+ }
78
+
79
+ /**
80
+ * Read one file, saying why when it cannot be.
81
+ * @param file - The file.
82
+ * @returns What it held, or the sentence its refusal came with.
83
+ */
84
+ async function readFile(file: File): Promise<LoadMassSpectraResult | string> {
85
+ try {
86
+ const bytes = new Uint8Array(await file.arrayBuffer());
87
+ return await loadMassSpectra(bytes, { fileName: file.name });
88
+ } catch (error) {
89
+ return errorMessage(error);
90
+ }
91
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The handle a host drives the viewer through, filled in from its state.
3
+ *
4
+ * A hook of its own beside the shell, because every gesture on the handle reads
5
+ * the state the shell already reads — and the shell is long enough without it.
6
+ */
7
+
8
+ import type { Ref } from 'react';
9
+ import { useImperativeHandle } from 'react';
10
+
11
+ import { mzFrame } from '../core/massDomain.ts';
12
+ import type {
13
+ MassEditorHandle,
14
+ ZoomToMzOptions,
15
+ } from '../core/massEditorApi.ts';
16
+
17
+ import { useMassActions, useMassEditorState } from './massStateContext.ts';
18
+
19
+ /**
20
+ * Fill in a host's handle on the viewer this is called inside.
21
+ * @param handle - The handle to fill in, if the host asked for one.
22
+ * @param readFiles - How a file is read into the viewer, as a drop reads it.
23
+ */
24
+ export function useMassHandle(
25
+ handle: Ref<MassEditorHandle> | undefined,
26
+ readFiles: (files: readonly File[]) => Promise<void>,
27
+ ): void {
28
+ const { state, visibleSpectra } = useMassEditorState();
29
+ const actions = useMassActions();
30
+ const { domain } = state.view;
31
+
32
+ useImperativeHandle(
33
+ handle,
34
+ (): MassEditorHandle => ({
35
+ getSpectra: () => state.data.spectra,
36
+ setSpectra: (spectra) => actions.setSpectra(spectra),
37
+ addSpectra: (spectra) => actions.addSpectra(spectra),
38
+ openFiles: (files) => readFiles(files),
39
+ clear: () => actions.clear(),
40
+ setDomain: (next) => actions.setDomain(next),
41
+ resetDomain: () => actions.resetDomain(),
42
+ zoomToMz: (mz, options: ZoomToMzOptions = {}) => {
43
+ actions.setDomain(
44
+ mzFrame(
45
+ mz,
46
+ visibleSpectra,
47
+ domain,
48
+ options.halfWidth === undefined
49
+ ? {}
50
+ : { halfWidth: options.halfWidth },
51
+ ),
52
+ );
53
+ },
54
+ selectSpectrum: (id) => actions.selectSpectrum(id),
55
+ }),
56
+ [state.data.spectra, actions, readFiles, domain, visibleSpectra],
57
+ );
58
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * What a mass chart reads under the pointer, and which peak it is asking about.
3
+ *
4
+ * Following the pointer at all is `useChartPointer` in the shared chart:
5
+ * placing it in user units, refusing the margins, and reporting only when the
6
+ * answer changed. What it *reads* there is the part that is about mass, and is
7
+ * the whole of this file — the m/z, the intensity, and the peak within reach.
8
+ */
9
+
10
+ import type { RefObject } from 'react';
11
+ import { useCallback, useMemo } from 'react';
12
+
13
+ import type { PlotRect } from '../../chart/core/chartGeometry.ts';
14
+ import type { ChartScale } from '../../chart/core/chartScale.ts';
15
+ import { chartValue } from '../../chart/core/chartScale.ts';
16
+ import type { ChartPoint } from '../../chart/core/svgPoint.ts';
17
+ import type { ChartPointer } from '../../chart/ui/useChartPointer.ts';
18
+ import { useChartPointer } from '../../chart/ui/useChartPointer.ts';
19
+ import type { MassSpectrum } from '../core/massSpectrum.ts';
20
+ import type { NearestPeak } from '../core/nearestPeak.ts';
21
+ import { nearestPeakMz, sameNearestPeak } from '../core/nearestPeak.ts';
22
+
23
+ /** What the axes say under the pointer, which is what a readout prints. */
24
+ export interface MassReadout {
25
+ /** What the m/z axis reads there. */
26
+ mz: number;
27
+ /** What the intensity axis reads there. */
28
+ intensity: number;
29
+ /** The peak within reach of the pointer, `null` when none is. */
30
+ peak: NearestPeak | null;
31
+ }
32
+
33
+ export interface MassPointerOptions {
34
+ /** The SVG the chart is drawn on, as it was handed to its `ref`. */
35
+ svgRef: RefObject<SVGSVGElement | null>;
36
+ /** Where the plot sits inside that SVG. */
37
+ plot: PlotRect;
38
+ /** The m/z axis as it is currently zoomed. */
39
+ xScale: ChartScale;
40
+ /** The intensity axis as it is currently zoomed. */
41
+ yScale: ChartScale;
42
+ /** What the chart draws, for the peak under the pointer to be found. */
43
+ spectra: readonly MassSpectrum[];
44
+ /**
45
+ * Told which peak the pointer has come to rest on, and told `null` when it
46
+ * leaves one — called only when the answer changes, so it is safe to hang a
47
+ * highlight that redraws half the page on it.
48
+ * @default undefined
49
+ */
50
+ onPeak?: (peak: NearestPeak | null) => void;
51
+ /**
52
+ * Told when the pointer leaves the plot, and only then.
53
+ *
54
+ * `onPeak` says `null` for the gap between two sticks as well, so it cannot
55
+ * be read as the reading being over — which is the one thing a host drawing a
56
+ * picture of whatever is crossed has to know.
57
+ * @default undefined
58
+ */
59
+ onAway?: () => void;
60
+ }
61
+
62
+ /**
63
+ * Follow the pointer over a mass chart.
64
+ * @param options - The chart, its axes and what it holds.
65
+ * @returns Where the pointer is and what it reads, both `null` while it is
66
+ * anywhere but over the plot.
67
+ */
68
+ export function useMassPointer(
69
+ options: MassPointerOptions,
70
+ ): ChartPointer<MassReadout> {
71
+ const { svgRef, plot, xScale, yScale, spectra, onPeak, onAway } = options;
72
+
73
+ const read = useCallback(
74
+ (point: ChartPoint): MassReadout => ({
75
+ mz: chartValue(xScale, point.x),
76
+ intensity: chartValue(yScale, point.y),
77
+ peak: nearestPeakMz(spectra, xScale, point.x),
78
+ }),
79
+ [xScale, yScale, spectra],
80
+ );
81
+
82
+ const onReadout = useMemo(
83
+ () =>
84
+ onPeak === undefined && onAway === undefined
85
+ ? undefined
86
+ : (readout: MassReadout | null) => {
87
+ onPeak?.(readout?.peak ?? null);
88
+ // Only the whole reading is absent off the plot: inside it there is
89
+ // always an m/z and an intensity, whether or not a stick is within
90
+ // reach. So this is the leave, and the `null` peak above is not.
91
+ if (readout === null) onAway?.();
92
+ },
93
+ [onPeak, onAway],
94
+ );
95
+
96
+ return useChartPointer({
97
+ svgRef,
98
+ plot,
99
+ read,
100
+ sameReadout: sameMassReadout,
101
+ onReadout,
102
+ });
103
+ }
104
+
105
+ /**
106
+ * Whether two readings are about the same peak.
107
+ *
108
+ * The peak alone, and never the m/z under the crosshair: that fractional value
109
+ * changes on every pixel the pointer moves, and comparing it would report a new
110
+ * answer for every tremor of a hand resting on one stick.
111
+ * @param current - What was last read.
112
+ * @param next - What has just been read.
113
+ * @returns Whether both are about the same peak.
114
+ */
115
+ export function sameMassReadout(
116
+ current: MassReadout,
117
+ next: MassReadout,
118
+ ): boolean {
119
+ return sameNearestPeak(current.peak, next.peak);
120
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * The keys, heard on the viewer's own root rather than on the document.
3
+ *
4
+ * Two viewers on one page must not both answer `f`, and a page that holds this
5
+ * beside an infrared viewer must not have its own keys eaten. So the viewer
6
+ * hears a key only while it holds the caret — the root carries `tabIndex={-1}`
7
+ * so a click anywhere in it does — and a key it acted on goes no further.
8
+ */
9
+
10
+ import { useEffect, useLayoutEffect, useRef } from 'react';
11
+
12
+ import { isEditingField } from '../../panel/core/isEditingField.ts';
13
+ import type {
14
+ MassCommand,
15
+ MassCommandHandlers,
16
+ MassCommandId,
17
+ } from '../core/massCommands.ts';
18
+ import { massCommands } from '../core/massCommands.ts';
19
+
20
+ /**
21
+ * Fire the viewer's commands from the keyboard.
22
+ *
23
+ * The handlers are read live through a ref rather than closed over, so the
24
+ * listener is attached once for the life of the viewer instead of being torn
25
+ * down and rebuilt on every render — and the chart re-renders on every move of
26
+ * the pointer across it.
27
+ * @param root - The viewer's root, `null` until it is mounted.
28
+ * @param handlers - What each command does.
29
+ */
30
+ export function useMassShortcuts(
31
+ root: HTMLElement | null,
32
+ handlers: MassCommandHandlers,
33
+ ): void {
34
+ const latest = useRef(handlers);
35
+
36
+ useLayoutEffect(() => {
37
+ latest.current = handlers;
38
+ });
39
+
40
+ useEffect(() => {
41
+ if (root === null) return;
42
+
43
+ /**
44
+ * Run the command a key names, if it names one.
45
+ * @param event - The key that arrived.
46
+ */
47
+ function onKeyDown(event: KeyboardEvent): void {
48
+ // A key pressed with a modifier belongs to the browser or to the page:
49
+ // Ctrl+F is a search, and a viewer that swallowed it to fit its chart
50
+ // would be a viewer people stop typing in.
51
+ if (event.ctrlKey || event.metaKey || event.altKey) return;
52
+ // Never while a name is being typed into the spectra panel.
53
+ if (isEditingField(event.target)) return;
54
+
55
+ const id = KEYS.get(event.key.toLowerCase());
56
+ if (id === undefined) return;
57
+ const handler = latest.current[id];
58
+ if (handler === undefined) return;
59
+
60
+ event.preventDefault();
61
+ // So the same key does not also reach a viewer mounted beside this one.
62
+ event.stopPropagation();
63
+ handler();
64
+ }
65
+
66
+ root.addEventListener('keydown', onKeyDown);
67
+ return () => {
68
+ root.removeEventListener('keydown', onKeyDown);
69
+ };
70
+ }, [root]);
71
+ }
72
+
73
+ /**
74
+ * Every key the viewer answers to, against the command it runs — built once
75
+ * from the command table, lower-cased so a capital arriving from a held shift
76
+ * still reaches the command a lowercase key names.
77
+ */
78
+ const KEYS = new Map<string, MassCommandId>(
79
+ Object.entries(massCommands as Record<string, MassCommand>).flatMap(
80
+ ([id, command]) =>
81
+ (command.shortcut?.keys ?? []).map(
82
+ (key) => [key.toLowerCase(), id as MassCommandId] as const,
83
+ ),
84
+ ),
85
+ );
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The side of the viewer: the panels it offers, whether any of them is open,
3
+ * and what dragging the splitter shut and back open does to them.
4
+ *
5
+ * A hook of its own beside the shell, because the shell lays the side out and
6
+ * this decides what is on it.
7
+ */
8
+
9
+ import { useMemo } from 'react';
10
+
11
+ import { DEFAULT_SIDE_PANEL } from '../core/massState.ts';
12
+
13
+ import type { MassHostPanel, MassStackPanel } from './massHostPanels.ts';
14
+ import { massStackPanels } from './massHostPanels.ts';
15
+ import { useMassActions, useMassEditorState } from './massStateContext.ts';
16
+
17
+ /** The side, as the shell lays it out. */
18
+ export interface MassSide {
19
+ /** Every panel on offer, in the order their icons are stacked. */
20
+ panels: readonly MassStackPanel[];
21
+ /** Whether a panel on offer is open, which is whether the side is. */
22
+ isOpen: boolean;
23
+ /**
24
+ * Open or close the side, as the splitter is dragged shut and back open.
25
+ * @param open - Whether the side is now open.
26
+ */
27
+ setOpen: (open: boolean) => void;
28
+ }
29
+
30
+ /**
31
+ * The side of the viewer this is called inside.
32
+ * @param hostPanels - The panels the host adds to the viewer's own.
33
+ * @returns The panels on offer, whether the side is open, and how to open it.
34
+ */
35
+ export function useMassSide(hostPanels: readonly MassHostPanel[]): MassSide {
36
+ const { state } = useMassEditorState();
37
+ const actions = useMassActions();
38
+ const { openPanelIds } = state.view;
39
+
40
+ const panels = useMemo(() => massStackPanels(hostPanels), [hostPanels]);
41
+ // Read off the panels on offer rather than off the ids: an id no panel
42
+ // answers to opens nothing, and a side open on it alone is an empty column.
43
+ const isOpen = useMemo(() => {
44
+ const open = new Set<string>(openPanelIds);
45
+ return panels.some((panel) => open.has(panel.id));
46
+ }, [panels, openPanelIds]);
47
+
48
+ /**
49
+ * Open or close the side.
50
+ * @param open - Whether the side is now open.
51
+ */
52
+ function setOpen(open: boolean): void {
53
+ if (!open) {
54
+ for (const panelId of openPanelIds) actions.togglePanel(panelId);
55
+ return;
56
+ }
57
+ // Dragging the splitter back open must land on something, or it opens on an
58
+ // empty column and reads as broken.
59
+ if (!isOpen) actions.togglePanel(DEFAULT_SIDE_PANEL);
60
+ }
61
+
62
+ return { panels, isOpen, setOpen };
63
+ }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * The generic zoom, told what a mass spectrum's window is fitted to.
3
+ *
4
+ * Every gesture — the drag, the wheel, the double click — is `useChartZoom` in
5
+ * the shared chart and is not written here, because none of it is about mass.
6
+ * What *is* about mass is the fit: a spectrum carries two traces where only one
7
+ * is drawn, and a previewed pattern is left out of the extents. That arithmetic
8
+ * is `massDomain.ts`, and this hook is what joins the two.
9
+ *
10
+ * One gesture is about mass in the same way. A click on a mass chart is a peak
11
+ * or it is nothing at all, and only the axis the gesture was measured against
12
+ * can say which of the two it was — so the hook that owns that axis answers it,
13
+ * and the chart above is handed the peak rather than a place on the plot.
14
+ */
15
+
16
+ import type { RefObject } from 'react';
17
+ import { useCallback, useLayoutEffect, useMemo, useRef } from 'react';
18
+
19
+ import type { ZoomDragMode } from '../../chart/core/chartDomain.ts';
20
+ import type { PlotRect } from '../../chart/core/chartGeometry.ts';
21
+ import type { ChartScale } from '../../chart/core/chartScale.ts';
22
+ import type { ChartPoint } from '../../chart/core/svgPoint.ts';
23
+ import type { ChartClickModifiers } from '../../chart/ui/chartGestures.ts';
24
+ import type { ChartZoom } from '../../chart/ui/useChartZoom.ts';
25
+ import { useChartZoom } from '../../chart/ui/useChartZoom.ts';
26
+ import { fittedTo, fullDomain } from '../core/massDomain.ts';
27
+ import type { MassDomain, MassSpectrum } from '../core/massSpectrum.ts';
28
+ import type { NearestPeak } from '../core/nearestPeak.ts';
29
+ import { peakAtMz } from '../core/nearestPeak.ts';
30
+
31
+ /** A click on the plot, with everything needed to say what it was on. */
32
+ export interface MassZoomClick {
33
+ /** Where it landed on the m/z axis. */
34
+ mz: number;
35
+ /** The picked peak within reach of it, `null` when it landed on none. */
36
+ peak: NearestPeak | null;
37
+ /**
38
+ * The m/z axis the click was measured against, for a host testing marks of
39
+ * its own — a ring on a fragmented peak — before the sticks.
40
+ */
41
+ xScale: ChartScale;
42
+ /** The modifier keys held as the button came up. */
43
+ modifiers: ChartClickModifiers;
44
+ }
45
+
46
+ export interface MassZoomOptions {
47
+ /** What the chart draws. */
48
+ spectra: readonly MassSpectrum[];
49
+ /**
50
+ * What the window is fitted to instead, when that is not what the chart
51
+ * draws — every pane of a stack is fitted to the union, so a faint spectrum
52
+ * and a bright one are not drawn alike.
53
+ * @default the spectra the chart draws
54
+ */
55
+ fitTo?: readonly MassSpectrum[];
56
+ /**
57
+ * Whether one spectrum is drawn below the axis, which fits the window about
58
+ * zero.
59
+ * @default false
60
+ */
61
+ mirror?: boolean;
62
+ /** The SVG the gestures are made on, as it was handed to its `ref`. */
63
+ svgRef: RefObject<SVGSVGElement | null>;
64
+ /** Where the plot sits inside that SVG, which the axes are laid over. */
65
+ plot: PlotRect;
66
+ /**
67
+ * The window a host is imposing, `null` while it imposes none. Handed straight
68
+ * through; `useChartZoom` documents what imposing one does.
69
+ * @default null
70
+ */
71
+ domain?: MassDomain | null;
72
+ /**
73
+ * What a drag asks for: the m/z axis alone, or the rectangle swept out.
74
+ * @default 'xAxis'
75
+ */
76
+ drag?: ZoomDragMode;
77
+ /**
78
+ * Whether the chart answers `f` with the fit itself. A viewer running its own
79
+ * keys through a command table, where the key is documented, turns it off.
80
+ * @default true
81
+ */
82
+ keys?: boolean;
83
+ /**
84
+ * Told where a click on the plot landed — a press let go over it without
85
+ * travelling, never the end of a drag — and the peak within reach of it.
86
+ * @default undefined
87
+ */
88
+ onClick?: (click: MassZoomClick) => void;
89
+ }
90
+
91
+ /**
92
+ * Zoom a mass chart by dragging it, by the wheel and by double clicking it.
93
+ *
94
+ * The y axis keeps its default rules, which are a stick spectrum's: zero is the
95
+ * baseline the wheel scales about, and it stays inside the window however the
96
+ * chart is zoomed, because a window starting at a tenth of the base peak would
97
+ * cut every stick off at the ankles.
98
+ * @param options - The chart and what it holds.
99
+ * @returns The window and the gestures that move it.
100
+ */
101
+ export function useMassZoom(options: MassZoomOptions): ChartZoom {
102
+ const {
103
+ spectra,
104
+ fitTo,
105
+ mirror = false,
106
+ svgRef,
107
+ plot,
108
+ domain = null,
109
+ drag = 'xAxis',
110
+ keys = true,
111
+ onClick,
112
+ } = options;
113
+
114
+ const measured = fitTo ?? spectra;
115
+ const fitted = useMemo(
116
+ () => fullDomain(measured, mirror),
117
+ [measured, mirror],
118
+ );
119
+ const fitKey = useMemo(() => fittedTo(measured, mirror), [measured, mirror]);
120
+ const gestures = useMemo(() => ({ drag, wheel: true, keys }), [drag, keys]);
121
+
122
+ // The axis a click is measured against is the one the zoom arrived at, and
123
+ // the click comes back out of that same hook: it therefore reaches the
124
+ // handler through a ref, read as the button comes up rather than closed over
125
+ // when the gesture layer was built.
126
+ const axis = useRef<ChartScale | null>(null);
127
+
128
+ const onPress = useCallback(
129
+ (point: ChartPoint, modifiers: ChartClickModifiers) => {
130
+ const xScale = axis.current;
131
+ if (xScale === null || onClick === undefined) return;
132
+ onClick({
133
+ mz: point.x,
134
+ peak: peakAtMz(spectra, xScale, point.x),
135
+ xScale,
136
+ modifiers,
137
+ });
138
+ },
139
+ [spectra, onClick],
140
+ );
141
+
142
+ const zoom = useChartZoom({
143
+ fitted,
144
+ fitKey,
145
+ svgRef,
146
+ plot,
147
+ domain,
148
+ gestures,
149
+ ...(onClick === undefined ? {} : { onClick: onPress }),
150
+ });
151
+
152
+ useLayoutEffect(() => {
153
+ axis.current = zoom.xScale;
154
+ });
155
+
156
+ return zoom;
157
+ }
package/src/mass.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Displaying mass spectra: the chart, the peak table and the whole editor.
3
+ *
4
+ * A door of its own, and not part of `react-cheminfo/core` or
5
+ * `react-cheminfo/ui`, because reading a spectrum drags the formats it may
6
+ * arrive in — `jcampconverter` and `xy-parser` for the files, `ms-spectrum` and
7
+ * `ml-gsd` for the peak picking, `convert-to-jcamp` for writing them back out.
8
+ * A site with no spectra to look at installs none of it.
9
+ *
10
+ * The infrared viewer, `react-cheminfo/ir`, is its sibling: the same shell, the
11
+ * same three buckets of state, the same chart underneath. Neither imports the
12
+ * other.
13
+ */
14
+
15
+ export * from './mass/core/index.ts';
16
+ export * from './mass/ui/index.ts';
@@ -51,8 +51,12 @@ export function PanelRail<TId extends string>(
51
51
  <ActivityBar>
52
52
  {panels.map((panel) => (
53
53
  <ActivityBar.Item
54
+ // The panel id goes on a data attribute rather than on `id`: it is
55
+ // unique within one rail, not on the page, and a page can hold two —
56
+ // AGA2S hands the mass viewer the glycan editor's own panels, so both
57
+ // rails carry `fragments`.
58
+ data-panel-id={panel.id}
54
59
  key={panel.id}
55
- id={panel.id}
56
60
  icon={panel.icon}
57
61
  tooltip={panel.title}
58
62
  // A tooltip is not an accessible name: without this every toggle is