react-cheminfo 0.65.0 → 0.67.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 (466) hide show
  1. package/README.md +33 -17
  2. package/lib/download/ui/FigureDownloadPanel.d.ts +7 -1
  3. package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
  4. package/lib/download/ui/FigureDownloadPanel.js +2 -2
  5. package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
  6. package/lib/ecosystem/core/sites.js +3 -3
  7. package/lib/ecosystem/core/sites.js.map +1 -1
  8. package/lib/ecosystem/core/types.d.ts +1 -1
  9. package/lib/ecosystem/core/types.d.ts.map +1 -1
  10. package/lib/ecosystem/ui/glyphs.js +1 -1
  11. package/lib/ecosystem/ui/glyphs.js.map +1 -1
  12. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  13. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  14. package/lib/i18n/core/messageCatalog.d.ts +2 -2
  15. package/lib/i18n/vite/localeCatalog.d.ts +1 -1
  16. package/lib/ir/core/analysisSpectra.d.ts +23 -6
  17. package/lib/ir/core/analysisSpectra.d.ts.map +1 -1
  18. package/lib/ir/core/analysisSpectra.js.map +1 -1
  19. package/lib/ir/core/bandLabelPlan.d.ts.map +1 -1
  20. package/lib/ir/core/bandLabelPlan.js +11 -6
  21. package/lib/ir/core/bandLabelPlan.js.map +1 -1
  22. package/lib/ir/core/index.d.ts +15 -11
  23. package/lib/ir/core/index.d.ts.map +1 -1
  24. package/lib/ir/core/index.js +9 -6
  25. package/lib/ir/core/index.js.map +1 -1
  26. package/lib/ir/core/irBand.d.ts +45 -14
  27. package/lib/ir/core/irBand.d.ts.map +1 -1
  28. package/lib/ir/core/irBand.js +28 -6
  29. package/lib/ir/core/irBand.js.map +1 -1
  30. package/lib/ir/core/irCommands.d.ts +11 -0
  31. package/lib/ir/core/irCommands.d.ts.map +1 -1
  32. package/lib/ir/core/irCommands.js +11 -1
  33. package/lib/ir/core/irCommands.js.map +1 -1
  34. package/lib/ir/core/irDomain.d.ts +4 -3
  35. package/lib/ir/core/irDomain.d.ts.map +1 -1
  36. package/lib/ir/core/irDomain.js +10 -7
  37. package/lib/ir/core/irDomain.js.map +1 -1
  38. package/lib/ir/core/irEditorApi.d.ts +12 -0
  39. package/lib/ir/core/irEditorApi.d.ts.map +1 -1
  40. package/lib/ir/core/irFormat.d.ts +14 -2
  41. package/lib/ir/core/irFormat.d.ts.map +1 -1
  42. package/lib/ir/core/irFormat.js +33 -4
  43. package/lib/ir/core/irFormat.js.map +1 -1
  44. package/lib/ir/core/irMode.d.ts +35 -8
  45. package/lib/ir/core/irMode.d.ts.map +1 -1
  46. package/lib/ir/core/irMode.js +38 -10
  47. package/lib/ir/core/irMode.js.map +1 -1
  48. package/lib/ir/core/irReducer.d.ts +2 -30
  49. package/lib/ir/core/irReducer.d.ts.map +1 -1
  50. package/lib/ir/core/irReducer.js +1 -24
  51. package/lib/ir/core/irReducer.js.map +1 -1
  52. package/lib/ir/core/irSidePanels.d.ts +7 -1
  53. package/lib/ir/core/irSidePanels.d.ts.map +1 -1
  54. package/lib/ir/core/irSpectrum.d.ts +52 -26
  55. package/lib/ir/core/irSpectrum.d.ts.map +1 -1
  56. package/lib/ir/core/irSpectrum.js +21 -15
  57. package/lib/ir/core/irSpectrum.js.map +1 -1
  58. package/lib/ir/core/irState.d.ts +46 -5
  59. package/lib/ir/core/irState.d.ts.map +1 -1
  60. package/lib/ir/core/irState.js +38 -1
  61. package/lib/ir/core/irState.js.map +1 -1
  62. package/lib/ir/core/irTechnique.d.ts +94 -0
  63. package/lib/ir/core/irTechnique.d.ts.map +1 -0
  64. package/lib/ir/core/irTechnique.js +87 -0
  65. package/lib/ir/core/irTechnique.js.map +1 -0
  66. package/lib/ir/core/irTechniqueCommands.d.ts +26 -0
  67. package/lib/ir/core/irTechniqueCommands.d.ts.map +1 -0
  68. package/lib/ir/core/irTechniqueCommands.js +68 -0
  69. package/lib/ir/core/irTechniqueCommands.js.map +1 -0
  70. package/lib/ir/core/pickBands.d.ts +6 -5
  71. package/lib/ir/core/pickBands.d.ts.map +1 -1
  72. package/lib/ir/core/pickBands.js +49 -26
  73. package/lib/ir/core/pickBands.js.map +1 -1
  74. package/lib/ir/core/ramanBands.d.ts +30 -0
  75. package/lib/ir/core/ramanBands.d.ts.map +1 -0
  76. package/lib/ir/core/ramanBands.js +83 -0
  77. package/lib/ir/core/ramanBands.js.map +1 -0
  78. package/lib/ir/core/spectrumJcamp.d.ts +10 -5
  79. package/lib/ir/core/spectrumJcamp.d.ts.map +1 -1
  80. package/lib/ir/core/spectrumJcamp.js +63 -15
  81. package/lib/ir/core/spectrumJcamp.js.map +1 -1
  82. package/lib/ir/core/toIrSpectrum.d.ts.map +1 -1
  83. package/lib/ir/core/toIrSpectrum.js +17 -2
  84. package/lib/ir/core/toIrSpectrum.js.map +1 -1
  85. package/lib/ir/ui/BandRow.d.ts +30 -0
  86. package/lib/ir/ui/BandRow.d.ts.map +1 -0
  87. package/lib/ir/ui/BandRow.js +42 -0
  88. package/lib/ir/ui/BandRow.js.map +1 -0
  89. package/lib/ir/ui/BandsPanel.d.ts +4 -0
  90. package/lib/ir/ui/BandsPanel.d.ts.map +1 -1
  91. package/lib/ir/ui/BandsPanel.js +14 -59
  92. package/lib/ir/ui/BandsPanel.js.map +1 -1
  93. package/lib/ir/ui/IrAboutDialog.d.ts +7 -0
  94. package/lib/ir/ui/IrAboutDialog.d.ts.map +1 -1
  95. package/lib/ir/ui/IrAboutDialog.js +16 -3
  96. package/lib/ir/ui/IrAboutDialog.js.map +1 -1
  97. package/lib/ir/ui/IrCanvas.d.ts +7 -0
  98. package/lib/ir/ui/IrCanvas.d.ts.map +1 -1
  99. package/lib/ir/ui/IrCanvas.js +9 -4
  100. package/lib/ir/ui/IrCanvas.js.map +1 -1
  101. package/lib/ir/ui/IrChart.d.ts +2 -1
  102. package/lib/ir/ui/IrChart.d.ts.map +1 -1
  103. package/lib/ir/ui/IrChart.js +22 -21
  104. package/lib/ir/ui/IrChart.js.map +1 -1
  105. package/lib/ir/ui/IrCommandProvider.d.ts +7 -0
  106. package/lib/ir/ui/IrCommandProvider.d.ts.map +1 -1
  107. package/lib/ir/ui/IrCommandProvider.js +2 -2
  108. package/lib/ir/ui/IrCommandProvider.js.map +1 -1
  109. package/lib/ir/ui/IrCommandTooltip.d.ts +7 -0
  110. package/lib/ir/ui/IrCommandTooltip.d.ts.map +1 -1
  111. package/lib/ir/ui/IrCommandTooltip.js +3 -2
  112. package/lib/ir/ui/IrCommandTooltip.js.map +1 -1
  113. package/lib/ir/ui/IrDocumentationDialog.d.ts +8 -1
  114. package/lib/ir/ui/IrDocumentationDialog.d.ts.map +1 -1
  115. package/lib/ir/ui/IrDocumentationDialog.js +30 -7
  116. package/lib/ir/ui/IrDocumentationDialog.js.map +1 -1
  117. package/lib/ir/ui/IrEditor.d.ts +25 -5
  118. package/lib/ir/ui/IrEditor.d.ts.map +1 -1
  119. package/lib/ir/ui/IrEditor.js +3 -20
  120. package/lib/ir/ui/IrEditor.js.map +1 -1
  121. package/lib/ir/ui/IrHeader.d.ts.map +1 -1
  122. package/lib/ir/ui/IrHeader.js +5 -1
  123. package/lib/ir/ui/IrHeader.js.map +1 -1
  124. package/lib/ir/ui/IrLogo.d.ts +11 -3
  125. package/lib/ir/ui/IrLogo.d.ts.map +1 -1
  126. package/lib/ir/ui/IrLogo.js +14 -5
  127. package/lib/ir/ui/IrLogo.js.map +1 -1
  128. package/lib/ir/ui/IrShell.d.ts +9 -1
  129. package/lib/ir/ui/IrShell.d.ts.map +1 -1
  130. package/lib/ir/ui/IrShell.js +26 -74
  131. package/lib/ir/ui/IrShell.js.map +1 -1
  132. package/lib/ir/ui/IrSidePanel.d.ts +11 -0
  133. package/lib/ir/ui/IrSidePanel.d.ts.map +1 -1
  134. package/lib/ir/ui/IrSidePanel.js +12 -3
  135. package/lib/ir/ui/IrSidePanel.js.map +1 -1
  136. package/lib/ir/ui/IrStatusBar.d.ts +3 -2
  137. package/lib/ir/ui/IrStatusBar.d.ts.map +1 -1
  138. package/lib/ir/ui/IrStatusBar.js +14 -9
  139. package/lib/ir/ui/IrStatusBar.js.map +1 -1
  140. package/lib/ir/ui/IrToolbar.d.ts +3 -0
  141. package/lib/ir/ui/IrToolbar.d.ts.map +1 -1
  142. package/lib/ir/ui/IrToolbar.js +10 -3
  143. package/lib/ir/ui/IrToolbar.js.map +1 -1
  144. package/lib/ir/ui/IrTraces.d.ts +4 -1
  145. package/lib/ir/ui/IrTraces.d.ts.map +1 -1
  146. package/lib/ir/ui/IrTraces.js +2 -0
  147. package/lib/ir/ui/IrTraces.js.map +1 -1
  148. package/lib/ir/ui/RamanEditor.d.ts +64 -0
  149. package/lib/ir/ui/RamanEditor.d.ts.map +1 -0
  150. package/lib/ir/ui/RamanEditor.js +17 -0
  151. package/lib/ir/ui/RamanEditor.js.map +1 -0
  152. package/lib/ir/ui/SpectraPanel.d.ts.map +1 -1
  153. package/lib/ir/ui/SpectraPanel.js +2 -2
  154. package/lib/ir/ui/SpectraPanel.js.map +1 -1
  155. package/lib/ir/ui/SpectrumRow.d.ts +7 -0
  156. package/lib/ir/ui/SpectrumRow.d.ts.map +1 -1
  157. package/lib/ir/ui/SpectrumRow.js +4 -5
  158. package/lib/ir/ui/SpectrumRow.js.map +1 -1
  159. package/lib/ir/ui/VibrationalEditor.d.ts +62 -0
  160. package/lib/ir/ui/VibrationalEditor.d.ts.map +1 -0
  161. package/lib/ir/ui/VibrationalEditor.js +33 -0
  162. package/lib/ir/ui/VibrationalEditor.js.map +1 -0
  163. package/lib/ir/ui/bandsTsv.d.ts +19 -0
  164. package/lib/ir/ui/bandsTsv.d.ts.map +1 -0
  165. package/lib/ir/ui/bandsTsv.js +38 -0
  166. package/lib/ir/ui/bandsTsv.js.map +1 -0
  167. package/lib/ir/ui/index.d.ts +1 -0
  168. package/lib/ir/ui/index.d.ts.map +1 -1
  169. package/lib/ir/ui/index.js.map +1 -1
  170. package/lib/ir/ui/irActions.d.ts +3 -3
  171. package/lib/ir/ui/irActions.d.ts.map +1 -1
  172. package/lib/ir/ui/irChartProps.d.ts +21 -4
  173. package/lib/ir/ui/irChartProps.d.ts.map +1 -1
  174. package/lib/ir/ui/irChartProps.js +3 -2
  175. package/lib/ir/ui/irChartProps.js.map +1 -1
  176. package/lib/ir/ui/irCommandContext.d.ts +8 -0
  177. package/lib/ir/ui/irCommandContext.d.ts.map +1 -1
  178. package/lib/ir/ui/irCommandContext.js +14 -3
  179. package/lib/ir/ui/irCommandContext.js.map +1 -1
  180. package/lib/ir/ui/irHostPanels.d.ts +53 -0
  181. package/lib/ir/ui/irHostPanels.d.ts.map +1 -0
  182. package/lib/ir/ui/irHostPanels.js +41 -0
  183. package/lib/ir/ui/irHostPanels.js.map +1 -0
  184. package/lib/ir/ui/useIrEditor.d.ts +3 -3
  185. package/lib/ir/ui/useIrEditor.d.ts.map +1 -1
  186. package/lib/ir/ui/useIrEditor.js +13 -4
  187. package/lib/ir/ui/useIrEditor.js.map +1 -1
  188. package/lib/ir/ui/useIrHandle.d.ts +14 -0
  189. package/lib/ir/ui/useIrHandle.d.ts.map +1 -0
  190. package/lib/ir/ui/useIrHandle.js +39 -0
  191. package/lib/ir/ui/useIrHandle.js.map +1 -0
  192. package/lib/ir/ui/useIrSide.d.ts +27 -0
  193. package/lib/ir/ui/useIrSide.d.ts.map +1 -0
  194. package/lib/ir/ui/useIrSide.js +42 -0
  195. package/lib/ir/ui/useIrSide.js.map +1 -0
  196. package/lib/ir/ui/useIrText.d.ts +40 -0
  197. package/lib/ir/ui/useIrText.d.ts.map +1 -0
  198. package/lib/ir/ui/useIrText.js +118 -0
  199. package/lib/ir/ui/useIrText.js.map +1 -0
  200. package/lib/ir/ui/useIrZoom.d.ts +15 -0
  201. package/lib/ir/ui/useIrZoom.d.ts.map +1 -1
  202. package/lib/ir/ui/useIrZoom.js +6 -4
  203. package/lib/ir/ui/useIrZoom.js.map +1 -1
  204. package/lib/ir/ui/useValueAxisZoom.d.ts +20 -0
  205. package/lib/ir/ui/useValueAxisZoom.d.ts.map +1 -0
  206. package/lib/ir/ui/useValueAxisZoom.js +54 -0
  207. package/lib/ir/ui/useValueAxisZoom.js.map +1 -0
  208. package/lib/ir.d.ts +3 -0
  209. package/lib/ir.d.ts.map +1 -1
  210. package/lib/ir.js +3 -0
  211. package/lib/ir.js.map +1 -1
  212. package/lib/locales/de.json +29 -2
  213. package/lib/locales/en.json +29 -2
  214. package/lib/locales/es.json +29 -2
  215. package/lib/locales/fr.json +29 -2
  216. package/lib/locales/it.json +29 -2
  217. package/lib/molecule3d/core/animatedPng.d.ts +25 -0
  218. package/lib/molecule3d/core/animatedPng.d.ts.map +1 -0
  219. package/lib/molecule3d/core/animatedPng.js +59 -0
  220. package/lib/molecule3d/core/animatedPng.js.map +1 -0
  221. package/lib/molecule3d/core/file.d.ts +24 -0
  222. package/lib/molecule3d/core/file.d.ts.map +1 -0
  223. package/lib/molecule3d/core/file.js +2 -0
  224. package/lib/molecule3d/core/file.js.map +1 -0
  225. package/lib/molecule3d/core/index.d.ts +4 -1
  226. package/lib/molecule3d/core/index.d.ts.map +1 -1
  227. package/lib/molecule3d/core/index.js +1 -0
  228. package/lib/molecule3d/core/index.js.map +1 -1
  229. package/lib/molecule3d/core/settings.d.ts +0 -7
  230. package/lib/molecule3d/core/settings.d.ts.map +1 -1
  231. package/lib/molecule3d/core/settings.js.map +1 -1
  232. package/lib/molecule3d/ui/Molecule3DExport.d.ts +10 -2
  233. package/lib/molecule3d/ui/Molecule3DExport.d.ts.map +1 -1
  234. package/lib/molecule3d/ui/Molecule3DExport.js +15 -2
  235. package/lib/molecule3d/ui/Molecule3DExport.js.map +1 -1
  236. package/lib/molecule3d/ui/Molecule3DToolbar.js +9 -2
  237. package/lib/molecule3d/ui/Molecule3DToolbar.js.map +1 -1
  238. package/lib/molecule3d/ui/MoleculeCanvas3D.d.ts.map +1 -1
  239. package/lib/molecule3d/ui/MoleculeCanvas3D.js +23 -41
  240. package/lib/molecule3d/ui/MoleculeCanvas3D.js.map +1 -1
  241. package/lib/molecule3d/ui/drawScene.d.ts +2 -1
  242. package/lib/molecule3d/ui/drawScene.d.ts.map +1 -1
  243. package/lib/molecule3d/ui/drawScene.js.map +1 -1
  244. package/lib/molecule3d/ui/exportMoleculeImage.d.ts +15 -1
  245. package/lib/molecule3d/ui/exportMoleculeImage.d.ts.map +1 -1
  246. package/lib/molecule3d/ui/exportMoleculeImage.js +14 -2
  247. package/lib/molecule3d/ui/exportMoleculeImage.js.map +1 -1
  248. package/lib/molecule3d/ui/moleculeFrames.d.ts +47 -0
  249. package/lib/molecule3d/ui/moleculeFrames.d.ts.map +1 -0
  250. package/lib/molecule3d/ui/moleculeFrames.js +65 -0
  251. package/lib/molecule3d/ui/moleculeFrames.js.map +1 -0
  252. package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts +14 -1
  253. package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts.map +1 -1
  254. package/lib/molecule3d/ui/renderMolecule.d.ts +3 -3
  255. package/lib/molecule3d/ui/renderMolecule.d.ts.map +1 -1
  256. package/lib/molecule3d/ui/renderMolecule.js +2 -1
  257. package/lib/molecule3d/ui/renderMolecule.js.map +1 -1
  258. package/lib/molecule3d/ui/sceneDrawer.d.ts +2 -1
  259. package/lib/molecule3d/ui/sceneDrawer.d.ts.map +1 -1
  260. package/lib/molecule3d/ui/sceneDrawer.js +9 -1
  261. package/lib/molecule3d/ui/sceneDrawer.js.map +1 -1
  262. package/lib/molecule3d/ui/useImageExport.d.ts +8 -3
  263. package/lib/molecule3d/ui/useImageExport.d.ts.map +1 -1
  264. package/lib/molecule3d/ui/useImageExport.js +13 -4
  265. package/lib/molecule3d/ui/useImageExport.js.map +1 -1
  266. package/lib/molecule3d/ui/useMoleculeScene.d.ts +2 -1
  267. package/lib/molecule3d/ui/useMoleculeScene.d.ts.map +1 -1
  268. package/lib/molecule3d/ui/useMoleculeScene.js.map +1 -1
  269. package/lib/molecule3d/ui/useMoleculeViewer.d.ts +16 -0
  270. package/lib/molecule3d/ui/useMoleculeViewer.d.ts.map +1 -0
  271. package/lib/molecule3d/ui/useMoleculeViewer.js +37 -0
  272. package/lib/molecule3d/ui/useMoleculeViewer.js.map +1 -0
  273. package/lib/molecule3d/ui/usePolarSurfaceArea.d.ts +3 -3
  274. package/lib/molecule3d/ui/usePolarSurfaceArea.d.ts.map +1 -1
  275. package/lib/molecule3d/ui/usePolarSurfaceArea.js +4 -3
  276. package/lib/molecule3d/ui/usePolarSurfaceArea.js.map +1 -1
  277. package/lib/molecule3d/ui/viewer.d.ts +4 -1
  278. package/lib/molecule3d/ui/viewer.d.ts.map +1 -1
  279. package/lib/molecule3d/ui/viewer.js +21 -19
  280. package/lib/molecule3d/ui/viewer.js.map +1 -1
  281. package/lib/molecule3d/ui/viewerTypes.d.ts +6 -0
  282. package/lib/molecule3d/ui/viewerTypes.d.ts.map +1 -1
  283. package/lib/molstar/core/captureScene.d.ts +19 -1
  284. package/lib/molstar/core/captureScene.d.ts.map +1 -1
  285. package/lib/molstar/core/captureScene.js +57 -2
  286. package/lib/molstar/core/captureScene.js.map +1 -1
  287. package/lib/molstar/core/index.d.ts +5 -2
  288. package/lib/molstar/core/index.d.ts.map +1 -1
  289. package/lib/molstar/core/index.js +4 -2
  290. package/lib/molstar/core/index.js.map +1 -1
  291. package/lib/molstar/core/trajectory.d.ts +56 -0
  292. package/lib/molstar/core/trajectory.d.ts.map +1 -0
  293. package/lib/molstar/core/trajectory.js +96 -0
  294. package/lib/molstar/core/trajectory.js.map +1 -0
  295. package/lib/panel/ui/PanelRail.d.ts.map +1 -1
  296. package/lib/panel/ui/PanelRail.js +1 -1
  297. package/lib/panel/ui/PanelRail.js.map +1 -1
  298. package/lib/raman.d.ts +17 -0
  299. package/lib/raman.d.ts.map +1 -0
  300. package/lib/raman.js +12 -0
  301. package/lib/raman.js.map +1 -0
  302. package/lib/router/core/basePath.d.ts +2 -2
  303. package/lib/router/core/basePath.js +2 -2
  304. package/lib/router/core/siteAddresses.d.ts +1 -1
  305. package/lib/router/core/siteAddresses.js +1 -1
  306. package/lib/seo/core/siteFiles.js +1 -1
  307. package/lib/seo/core/siteFiles.js.map +1 -1
  308. package/lib/server/answerAddresses.d.ts +3 -3
  309. package/lib/server/answerAddresses.js +3 -3
  310. package/lib/structure/core/index.d.ts +2 -0
  311. package/lib/structure/core/index.d.ts.map +1 -1
  312. package/lib/structure/core/index.js +1 -0
  313. package/lib/structure/core/index.js.map +1 -1
  314. package/lib/structure/core/structureTransfer.d.ts +29 -0
  315. package/lib/structure/core/structureTransfer.d.ts.map +1 -0
  316. package/lib/structure/core/structureTransfer.js +26 -0
  317. package/lib/structure/core/structureTransfer.js.map +1 -0
  318. package/lib/structure/ui/EditorImportButton.d.ts +20 -0
  319. package/lib/structure/ui/EditorImportButton.d.ts.map +1 -0
  320. package/lib/structure/ui/EditorImportButton.js +24 -0
  321. package/lib/structure/ui/EditorImportButton.js.map +1 -0
  322. package/lib/structure/ui/EditorImportProblem.d.ts +17 -0
  323. package/lib/structure/ui/EditorImportProblem.d.ts.map +1 -0
  324. package/lib/structure/ui/EditorImportProblem.js +32 -0
  325. package/lib/structure/ui/EditorImportProblem.js.map +1 -0
  326. package/lib/structure/ui/StructureDrop.d.ts +39 -0
  327. package/lib/structure/ui/StructureDrop.d.ts.map +1 -0
  328. package/lib/structure/ui/StructureDrop.js +19 -0
  329. package/lib/structure/ui/StructureDrop.js.map +1 -0
  330. package/lib/structure/ui/StructureDropOverlay.d.ts +16 -0
  331. package/lib/structure/ui/StructureDropOverlay.d.ts.map +1 -0
  332. package/lib/structure/ui/StructureDropOverlay.js +29 -0
  333. package/lib/structure/ui/StructureDropOverlay.js.map +1 -0
  334. package/lib/structure/ui/StructureEditor.d.ts +3 -80
  335. package/lib/structure/ui/StructureEditor.d.ts.map +1 -1
  336. package/lib/structure/ui/StructureEditor.js +21 -33
  337. package/lib/structure/ui/StructureEditor.js.map +1 -1
  338. package/lib/structure/ui/importedStructure.d.ts +25 -0
  339. package/lib/structure/ui/importedStructure.d.ts.map +1 -0
  340. package/lib/structure/ui/importedStructure.js +74 -0
  341. package/lib/structure/ui/importedStructure.js.map +1 -0
  342. package/lib/structure/ui/index.d.ts +2 -0
  343. package/lib/structure/ui/index.d.ts.map +1 -1
  344. package/lib/structure/ui/index.js +1 -0
  345. package/lib/structure/ui/index.js.map +1 -1
  346. package/lib/structure/ui/structureEditorProps.d.ts +98 -0
  347. package/lib/structure/ui/structureEditorProps.d.ts.map +1 -0
  348. package/lib/structure/ui/structureEditorProps.js +2 -0
  349. package/lib/structure/ui/structureEditorProps.js.map +1 -0
  350. package/lib/structure/ui/useDebouncedChange.d.ts +16 -0
  351. package/lib/structure/ui/useDebouncedChange.d.ts.map +1 -0
  352. package/lib/structure/ui/useDebouncedChange.js +30 -0
  353. package/lib/structure/ui/useDebouncedChange.js.map +1 -0
  354. package/lib/structure/ui/useStructureDrop.d.ts +30 -0
  355. package/lib/structure/ui/useStructureDrop.d.ts.map +1 -0
  356. package/lib/structure/ui/useStructureDrop.js +49 -0
  357. package/lib/structure/ui/useStructureDrop.js.map +1 -0
  358. package/lib/structure/ui/useStructureImport.d.ts +45 -0
  359. package/lib/structure/ui/useStructureImport.d.ts.map +1 -0
  360. package/lib/structure/ui/useStructureImport.js +62 -0
  361. package/lib/structure/ui/useStructureImport.js.map +1 -0
  362. package/package.json +5 -1
  363. package/src/download/ui/FigureDownloadPanel.tsx +9 -2
  364. package/src/ecosystem/core/sites.ts +3 -3
  365. package/src/ecosystem/core/types.ts +1 -1
  366. package/src/ecosystem/ui/glyphs.tsx +1 -1
  367. package/src/i18n/core/messageCatalog.ts +2 -2
  368. package/src/i18n/vite/localeCatalog.ts +1 -1
  369. package/src/ir/core/analysisSpectra.ts +26 -10
  370. package/src/ir/core/bandLabelPlan.ts +21 -10
  371. package/src/ir/core/index.ts +31 -7
  372. package/src/ir/core/irBand.ts +52 -14
  373. package/src/ir/core/irCommands.ts +15 -1
  374. package/src/ir/core/irDomain.ts +9 -7
  375. package/src/ir/core/irEditorApi.ts +13 -0
  376. package/src/ir/core/irFormat.ts +39 -6
  377. package/src/ir/core/irMode.ts +42 -10
  378. package/src/ir/core/irReducer.ts +3 -51
  379. package/src/ir/core/irSidePanels.ts +8 -1
  380. package/src/ir/core/irSpectrum.ts +59 -30
  381. package/src/ir/core/irState.ts +73 -5
  382. package/src/ir/core/irTechnique.ts +115 -0
  383. package/src/ir/core/irTechniqueCommands.ts +82 -0
  384. package/src/ir/core/pickBands.ts +63 -28
  385. package/src/ir/core/ramanBands.ts +105 -0
  386. package/src/ir/core/spectrumJcamp.ts +65 -16
  387. package/src/ir/core/toIrSpectrum.ts +20 -2
  388. package/src/ir/ui/BandRow.tsx +107 -0
  389. package/src/ir/ui/BandsPanel.tsx +32 -125
  390. package/src/ir/ui/IrAboutDialog.tsx +69 -28
  391. package/src/ir/ui/IrCanvas.tsx +29 -3
  392. package/src/ir/ui/IrChart.tsx +31 -24
  393. package/src/ir/ui/IrCommandProvider.tsx +10 -3
  394. package/src/ir/ui/IrCommandTooltip.tsx +11 -2
  395. package/src/ir/ui/IrDocumentationDialog.tsx +99 -55
  396. package/src/ir/ui/IrEditor.tsx +27 -40
  397. package/src/ir/ui/IrHeader.tsx +10 -3
  398. package/src/ir/ui/IrLogo.tsx +28 -9
  399. package/src/ir/ui/IrShell.tsx +47 -96
  400. package/src/ir/ui/IrSidePanel.tsx +36 -10
  401. package/src/ir/ui/IrStatusBar.tsx +17 -12
  402. package/src/ir/ui/IrToolbar.tsx +26 -15
  403. package/src/ir/ui/IrTraces.tsx +5 -1
  404. package/src/ir/ui/RamanEditor.tsx +71 -0
  405. package/src/ir/ui/SpectraPanel.tsx +2 -1
  406. package/src/ir/ui/SpectrumRow.tsx +14 -5
  407. package/src/ir/ui/VibrationalEditor.tsx +113 -0
  408. package/src/ir/ui/bandsTsv.ts +46 -0
  409. package/src/ir/ui/index.ts +1 -0
  410. package/src/ir/ui/irActions.ts +3 -3
  411. package/src/ir/ui/irChartProps.ts +21 -4
  412. package/src/ir/ui/irCommandContext.tsx +18 -3
  413. package/src/ir/ui/irHostPanels.ts +76 -0
  414. package/src/ir/ui/useIrEditor.ts +20 -8
  415. package/src/ir/ui/useIrHandle.ts +51 -0
  416. package/src/ir/ui/useIrSide.ts +60 -0
  417. package/src/ir/ui/useIrText.ts +170 -0
  418. package/src/ir/ui/useIrZoom.ts +22 -3
  419. package/src/ir/ui/useValueAxisZoom.ts +67 -0
  420. package/src/ir.ts +3 -0
  421. package/src/locales/de.json +29 -2
  422. package/src/locales/en.json +29 -2
  423. package/src/locales/es.json +29 -2
  424. package/src/locales/fr.json +29 -2
  425. package/src/locales/it.json +29 -2
  426. package/src/molecule3d/core/animatedPng.ts +79 -0
  427. package/src/molecule3d/core/file.ts +23 -0
  428. package/src/molecule3d/core/index.ts +3 -1
  429. package/src/molecule3d/core/settings.ts +0 -8
  430. package/src/molecule3d/ui/Molecule3DExport.tsx +43 -5
  431. package/src/molecule3d/ui/Molecule3DToolbar.tsx +9 -2
  432. package/src/molecule3d/ui/MoleculeCanvas3D.tsx +24 -38
  433. package/src/molecule3d/ui/drawScene.ts +2 -1
  434. package/src/molecule3d/ui/exportMoleculeImage.ts +28 -3
  435. package/src/molecule3d/ui/moleculeFrames.ts +88 -0
  436. package/src/molecule3d/ui/moleculeViewer3DProps.ts +14 -5
  437. package/src/molecule3d/ui/renderMolecule.ts +5 -3
  438. package/src/molecule3d/ui/sceneDrawer.ts +14 -2
  439. package/src/molecule3d/ui/useImageExport.ts +22 -5
  440. package/src/molecule3d/ui/useMoleculeScene.ts +2 -1
  441. package/src/molecule3d/ui/useMoleculeViewer.ts +46 -0
  442. package/src/molecule3d/ui/usePolarSurfaceArea.ts +6 -4
  443. package/src/molecule3d/ui/viewer.ts +34 -27
  444. package/src/molecule3d/ui/viewerTypes.ts +6 -0
  445. package/src/molstar/core/captureScene.ts +85 -2
  446. package/src/molstar/core/index.ts +13 -2
  447. package/src/molstar/core/trajectory.ts +117 -0
  448. package/src/panel/ui/PanelRail.tsx +3 -0
  449. package/src/raman.ts +20 -0
  450. package/src/router/core/basePath.ts +2 -2
  451. package/src/router/core/siteAddresses.ts +1 -1
  452. package/src/seo/core/siteFiles.ts +1 -1
  453. package/src/server/answerAddresses.ts +3 -3
  454. package/src/structure/core/index.ts +8 -0
  455. package/src/structure/core/structureTransfer.ts +37 -0
  456. package/src/structure/ui/EditorImportButton.tsx +59 -0
  457. package/src/structure/ui/EditorImportProblem.tsx +63 -0
  458. package/src/structure/ui/StructureDrop.tsx +66 -0
  459. package/src/structure/ui/StructureDropOverlay.tsx +50 -0
  460. package/src/structure/ui/StructureEditor.tsx +49 -134
  461. package/src/structure/ui/importedStructure.ts +83 -0
  462. package/src/structure/ui/index.ts +2 -0
  463. package/src/structure/ui/structureEditorProps.ts +103 -0
  464. package/src/structure/ui/useDebouncedChange.ts +41 -0
  465. package/src/structure/ui/useStructureDrop.ts +76 -0
  466. package/src/structure/ui/useStructureImport.ts +122 -0
@@ -1,24 +1,37 @@
1
+ import type { IrTechnique } from '../core/irTechnique.ts';
2
+
3
+ import { useIrText } from './useIrText.ts';
4
+
1
5
  export interface IrLogoProps {
2
6
  /**
3
7
  * How big to draw it, in pixels.
4
8
  * @default 16
5
9
  */
6
10
  size?: number;
11
+ /**
12
+ * What the spectra were measured with, which decides which way the bands
13
+ * point.
14
+ * @default 'infrared'
15
+ */
16
+ technique?: IrTechnique;
7
17
  }
8
18
 
9
19
  /**
10
- * The viewer's mark: three bands hanging from a baseline.
20
+ * The viewer's mark: three bands meeting a baseline.
11
21
  *
12
22
  * Drawn from the domain's own primitives rather than being a picture of a chart —
13
23
  * a transmittance baseline near the top with a strong band, a medium one and a
14
24
  * weak one dropping out of it, which is what an infrared spectrum looks like at a
15
- * glance and what nothing else looks like. Three elements, because that is what
16
- * survives 16 pixels.
25
+ * glance and what nothing else looks like. A Raman spectrum's bands stand up from
26
+ * a baseline near the foot instead, so its mark is the same three bands rising.
27
+ * Three elements, because that is what survives 16 pixels.
17
28
  * @param props - Component props.
18
29
  * @returns The mark, as SVG.
19
30
  */
20
31
  export function IrLogo(props: IrLogoProps) {
21
- const { size = 16 } = props;
32
+ const { size = 16, technique = 'infrared' } = props;
33
+ const { mark } = useIrText(technique);
34
+ const { baseline, bands } = MARKS[technique];
22
35
 
23
36
  return (
24
37
  <svg
@@ -26,19 +39,19 @@ export function IrLogo(props: IrLogoProps) {
26
39
  height={size}
27
40
  viewBox="0 0 16 16"
28
41
  role="img"
29
- aria-label="Infrared viewer"
42
+ aria-label={mark}
30
43
  >
31
- {/* The baseline, high up, where 100 % transmittance runs. */}
44
+ {/* The baseline: high up where 100 % transmittance runs, low for Raman. */}
32
45
  <path
33
- d="M1 3H15"
46
+ d={baseline}
34
47
  fill="none"
35
48
  stroke="#94a3b8"
36
49
  strokeWidth={1}
37
50
  strokeLinecap="round"
38
51
  />
39
- {/* Three bands dropping out of it, strong, medium, weak. */}
52
+ {/* Three bands meeting it, strong, medium, weak. */}
40
53
  <path
41
- d="M3 3V13M8 3V8.5M12.5 3V6"
54
+ d={bands}
42
55
  fill="none"
43
56
  stroke="#0072b2"
44
57
  strokeWidth={2}
@@ -47,3 +60,9 @@ export function IrLogo(props: IrLogoProps) {
47
60
  </svg>
48
61
  );
49
62
  }
63
+
64
+ /** The two strokes of each technique's mark. */
65
+ const MARKS: Record<IrTechnique, { baseline: string; bands: string }> = {
66
+ infrared: { baseline: 'M1 3H15', bands: 'M3 3V13M8 3V8.5M12.5 3V6' },
67
+ raman: { baseline: 'M1 13H15', bands: 'M3 13V3M8 13V7.5M12.5 13V10' },
68
+ };
@@ -1,11 +1,5 @@
1
1
  import type { Ref } from 'react';
2
- import {
3
- useCallback,
4
- useId,
5
- useImperativeHandle,
6
- useMemo,
7
- useState,
8
- } from 'react';
2
+ import { useId, useMemo, useState } from 'react';
9
3
  import { SplitPane, useFullscreen } from 'react-science/ui';
10
4
 
11
5
  import { sanitizeFileName } from '../../download/core/sanitizeFileName.ts';
@@ -13,12 +7,10 @@ import { useFigureDownload } from '../../download/ui/useFigureDownload.tsx';
13
7
  import { PanelRail } from '../../panel/ui/PanelRail.tsx';
14
8
  import type { IrBand } from '../core/irBand.ts';
15
9
  import type { IrCommandHandlers } from '../core/irCommands.ts';
16
- import { fullDomain } from '../core/irDomain.ts';
17
- import type { IrEditorHandle, ZoomToBandOptions } from '../core/irEditorApi.ts';
18
- import { otherIrMode, yAxisRules } from '../core/irMode.ts';
19
- import { irSidePanels } from '../core/irSidePanels.ts';
20
- import type { IrDomain, IrSpectrum } from '../core/irSpectrum.ts';
21
- import { DEFAULT_SIDE_PANEL } from '../core/irState.ts';
10
+ import type { IrEditorHandle, IrPlotClick } from '../core/irEditorApi.ts';
11
+ import { otherIrMode } from '../core/irMode.ts';
12
+ import type { IrSpectrum } from '../core/irSpectrum.ts';
13
+ import { irCommandOffered } from '../core/irTechniqueCommands.ts';
22
14
 
23
15
  import { IrAboutDialog } from './IrAboutDialog.tsx';
24
16
  import { IrCanvas } from './IrCanvas.tsx';
@@ -27,8 +19,12 @@ import { IrDocumentationDialog } from './IrDocumentationDialog.tsx';
27
19
  import { IrHeader } from './IrHeader.tsx';
28
20
  import { IrSidePanel } from './IrSidePanel.tsx';
29
21
  import { IrToolbar } from './IrToolbar.tsx';
22
+ import type { IrHostPanel } from './irHostPanels.ts';
30
23
  import { useIrActions, useIrEditorState } from './irStateContext.ts';
24
+ import { useIrHandle } from './useIrHandle.ts';
31
25
  import { useIrShortcuts } from './useIrShortcuts.ts';
26
+ import { useIrSide } from './useIrSide.ts';
27
+ import { useValueAxisZoom } from './useValueAxisZoom.ts';
32
28
 
33
29
  export interface IrShellProps {
34
30
  /**
@@ -36,6 +32,13 @@ export interface IrShellProps {
36
32
  * @default undefined
37
33
  */
38
34
  handle?: Ref<IrEditorHandle>;
35
+ /** The panels the host adds to the viewer's own, ahead of them. */
36
+ panels: readonly IrHostPanel[];
37
+ /**
38
+ * Told of a click on the plot, with the spectrum selected at that moment.
39
+ * @default undefined
40
+ */
41
+ onPlotClick?: (click: IrPlotClick) => void;
39
42
  }
40
43
 
41
44
  /**
@@ -53,13 +56,14 @@ export interface IrShellProps {
53
56
  * @returns The screen.
54
57
  */
55
58
  export function IrShell(props: IrShellProps) {
56
- const { handle } = props;
59
+ const { handle, panels, onPlotClick } = props;
57
60
 
58
61
  const { state, visibleSpectra, selectedSpectrum } = useIrEditorState();
59
62
  const actions = useIrActions();
60
63
  const { toggle: toggleFullScreen } = useFullscreen();
61
- const { openPanelIds, tool, domain } = state.view;
62
- const { mode, pickBands, showAssignments } = state.settings;
64
+ const { openPanelIds, tool } = state.view;
65
+ const side = useIrSide(panels);
66
+ const { mode, pickBands, showAssignments, technique } = state.settings;
63
67
 
64
68
  const [isAboutOpen, setIsAboutOpen] = useState(false);
65
69
  const [isDocumentationOpen, setIsDocumentationOpen] = useState(false);
@@ -79,27 +83,7 @@ export function IrShell(props: IrShellProps) {
79
83
  // times a second.
80
84
  const [highlight, setHighlight] = useState<IrBand | null>(null);
81
85
 
82
- /**
83
- * ChartScale the value axis by a factor, about the baseline the mode hangs from.
84
- * @param factor - Above one to zoom out.
85
- */
86
- const scaleValueAxis = useCallback(
87
- (factor: number) => {
88
- const shown = domain ?? fullDomain(visibleSpectra, mode);
89
- // Asked of the mode rather than written out again here: the baseline a
90
- // value axis is scaled about is `irMode`'s to know, and a second copy of
91
- // it is a second thing to get wrong.
92
- const { baseline = 0 } = yAxisRules(mode);
93
- actions.setDomain({
94
- x: shown.x,
95
- y: [
96
- baseline + (shown.y[0] - baseline) * factor,
97
- baseline + (shown.y[1] - baseline) * factor,
98
- ],
99
- });
100
- },
101
- [actions, domain, visibleSpectra, mode],
102
- );
86
+ const { zoomIn, zoomOut } = useValueAxisZoom();
103
87
 
104
88
  const commands = useMemo<IrCommandHandlers>(
105
89
  () => ({
@@ -108,13 +92,18 @@ export function IrShell(props: IrShellProps) {
108
92
  fullScreen: toggleFullScreen,
109
93
  readTool: () => actions.setTool('read'),
110
94
  boxTool: () => actions.setTool(tool === 'box' ? 'read' : 'box'),
111
- zoomIn: () => scaleValueAxis(1 / ZOOM_STEP),
112
- zoomOut: () => scaleValueAxis(ZOOM_STEP),
95
+ zoomIn,
96
+ zoomOut,
113
97
  resetZoom: () => actions.resetDomain(),
114
- toggleMode: () => actions.setSettings({ mode: otherIrMode(mode) }),
98
+ // A command the technique does not offer has no handler, so its key
99
+ // stays with the page.
100
+ toggleMode: irCommandOffered(technique, 'toggleMode')
101
+ ? () => actions.setSettings({ mode: otherIrMode(mode, technique) })
102
+ : undefined,
115
103
  togglePicking: () => actions.setSettings({ pickBands: !pickBands }),
116
- toggleAssignments: () =>
117
- actions.setSettings({ showAssignments: !showAssignments }),
104
+ toggleAssignments: irCommandOffered(technique, 'toggleAssignments')
105
+ ? () => actions.setSettings({ showAssignments: !showAssignments })
106
+ : undefined,
118
107
  exportImage: () => setFigureOpen(!isFigureOpen),
119
108
  clear: () => actions.clear(),
120
109
  }),
@@ -122,9 +111,11 @@ export function IrShell(props: IrShellProps) {
122
111
  actions,
123
112
  tool,
124
113
  mode,
114
+ technique,
125
115
  pickBands,
126
116
  showAssignments,
127
- scaleValueAxis,
117
+ zoomIn,
118
+ zoomOut,
128
119
  toggleFullScreen,
129
120
  isFigureOpen,
130
121
  setFigureOpen,
@@ -137,45 +128,10 @@ export function IrShell(props: IrShellProps) {
137
128
  // again.
138
129
  const [root, setRoot] = useState<HTMLElement | null>(null);
139
130
  useIrShortcuts(root, commands);
140
-
141
- useImperativeHandle(
142
- handle,
143
- (): IrEditorHandle => ({
144
- getSpectra: () => state.data.spectra,
145
- setSpectra: (spectra) => actions.setSpectra(spectra),
146
- addSpectra: (spectra) => actions.addSpectra(spectra),
147
- clear: () => actions.clear(),
148
- setDomain: (next) => actions.setDomain(next),
149
- resetDomain: () => actions.resetDomain(),
150
- zoomToWavenumber: (wavenumber, options: ZoomToBandOptions = {}) => {
151
- const { width = DEFAULT_FRAME_WIDTH } = options;
152
- const shown: IrDomain = domain ?? fullDomain(visibleSpectra, mode);
153
- actions.setDomain({
154
- x: [wavenumber - width / 2, wavenumber + width / 2],
155
- y: shown.y,
156
- });
157
- },
158
- selectSpectrum: (id) => actions.selectSpectrum(id),
159
- }),
160
- [state.data.spectra, actions, domain, visibleSpectra, mode],
161
- );
162
-
163
- /**
164
- * Open or close the side, as the splitter is dragged shut and back open.
165
- * @param open - Whether the side is now open.
166
- */
167
- function setSideOpen(open: boolean): void {
168
- if (!open) {
169
- for (const panelId of openPanelIds) actions.togglePanel(panelId);
170
- return;
171
- }
172
- // Dragging the splitter back open must land on something, or it opens on an
173
- // empty column and reads as broken.
174
- if (openPanelIds.length === 0) actions.togglePanel(DEFAULT_SIDE_PANEL);
175
- }
131
+ useIrHandle(handle);
176
132
 
177
133
  return (
178
- <IrCommandProvider handlers={commands}>
134
+ <IrCommandProvider handlers={commands} technique={technique}>
179
135
  {/* `tabIndex` so a click anywhere in the viewer makes this the target the
180
136
  shortcuts are heard on: keys are delivered to whatever holds the caret,
181
137
  and an SVG never does. */}
@@ -194,23 +150,28 @@ export function IrShell(props: IrShellProps) {
194
150
  direction="horizontal"
195
151
  controlledSide="end"
196
152
  defaultSize="360px"
197
- open={openPanelIds.length > 0}
198
- onOpenChange={setSideOpen}
153
+ open={side.isOpen}
154
+ onOpenChange={side.setOpen}
199
155
  >
200
156
  <IrCanvas
201
157
  highlight={highlight}
202
158
  onHighlight={setHighlight}
203
159
  chartId={chartId}
160
+ onPlotClick={onPlotClick}
204
161
  />
205
162
 
206
- <IrSidePanel highlight={highlight} onHighlight={setHighlight} />
163
+ <IrSidePanel
164
+ panels={panels}
165
+ highlight={highlight}
166
+ onHighlight={setHighlight}
167
+ />
207
168
  </SplitPane>
208
169
 
209
170
  {/* Outside the split, so the icons stay put against the right edge
210
171
  while the panel beside them is resized or closed. */}
211
172
  <div style={railStyle}>
212
173
  <PanelRail
213
- panels={irSidePanels}
174
+ panels={side.panels}
214
175
  openIds={openPanelIds}
215
176
  onToggle={actions.togglePanel}
216
177
  />
@@ -221,27 +182,17 @@ export function IrShell(props: IrShellProps) {
221
182
  <IrAboutDialog
222
183
  isOpen={isAboutOpen}
223
184
  onClose={() => setIsAboutOpen(false)}
185
+ technique={technique}
224
186
  />
225
187
  <IrDocumentationDialog
226
188
  isOpen={isDocumentationOpen}
227
189
  onClose={() => setIsDocumentationOpen(false)}
190
+ technique={technique}
228
191
  />
229
192
  </IrCommandProvider>
230
193
  );
231
194
  }
232
195
 
233
- /**
234
- * What one press of zoom in or out is worth.
235
- *
236
- * A fifth, which is about what one notch of a mouse wheel does — so the button
237
- * and the wheel feel like the same gesture at two speeds rather than two
238
- * different ones.
239
- */
240
- const ZOOM_STEP = 1.2;
241
-
242
- /** How wide a window a host gets when it asks to frame a band without saying. */
243
- const DEFAULT_FRAME_WIDTH = 200;
244
-
245
196
  /**
246
197
  * What a picture of the chart is called.
247
198
  *
@@ -1,14 +1,24 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { panelStyle } from '../../panel/core/panelStyles.ts';
1
4
  import { SidePanelStack } from '../../panel/ui/SidePanelStack.tsx';
2
5
  import type { IrBand } from '../core/irBand.ts';
3
6
  import type { IrSidePanelId } from '../core/irSidePanels.ts';
4
- import { irSidePanels } from '../core/irSidePanels.ts';
5
7
 
6
8
  import { BandsPanel } from './BandsPanel.tsx';
7
9
  import { MetadataPanel } from './MetadataPanel.tsx';
8
10
  import { SpectraPanel } from './SpectraPanel.tsx';
11
+ import type { IrHostPanel } from './irHostPanels.ts';
12
+ import { irStackPanels, isIrHostPanel } from './irHostPanels.ts';
9
13
  import { useIrActions, useIrEditorState } from './irStateContext.ts';
10
14
 
11
15
  export interface IrSidePanelProps {
16
+ /**
17
+ * The panels the host adds to the viewer's own, stacked above them in the
18
+ * order given.
19
+ * @default []
20
+ */
21
+ panels?: readonly IrHostPanel[];
12
22
  /**
13
23
  * The band the pointer is resting on.
14
24
  * @default null
@@ -29,28 +39,41 @@ export interface IrSidePanelProps {
29
39
  * bands are is one question asked of two panels. The header carries the close
30
40
  * button and nothing else — a panel's own actions are a toolbar inside its body,
31
41
  * so they travel with it.
42
+ *
43
+ * A host's panel is stacked like the viewer's own, and its body is laid out in
44
+ * the same column a built-in panel fills, so it takes its share of the height
45
+ * and scrolls within it rather than pushing the stack.
32
46
  * @param props - Component props.
33
47
  * @returns The panel stack.
34
48
  */
35
49
  export function IrSidePanel(props: IrSidePanelProps) {
36
- const { highlight = null, onHighlight } = props;
50
+ const {
51
+ panels: hostPanels = NO_PANELS,
52
+ highlight = null,
53
+ onHighlight,
54
+ } = props;
37
55
  const { state } = useIrEditorState();
38
56
  const actions = useIrActions();
39
57
  const { openPanelIds } = state.view;
58
+ const panels = useMemo(() => irStackPanels(hostPanels), [hostPanels]);
40
59
 
41
60
  return (
42
61
  <SidePanelStack
43
- panels={irSidePanels}
62
+ panels={panels}
44
63
  openPanelIds={openPanelIds}
45
64
  onClose={actions.togglePanel}
46
65
  >
47
- {(panel) => (
48
- <PanelBody
49
- panelId={panel.id}
50
- highlight={highlight}
51
- onHighlight={onHighlight}
52
- />
53
- )}
66
+ {(panel) =>
67
+ isIrHostPanel(panel) ? (
68
+ <div style={panelStyle}>{panel.content}</div>
69
+ ) : (
70
+ <PanelBody
71
+ panelId={panel.id}
72
+ highlight={highlight}
73
+ onHighlight={onHighlight}
74
+ />
75
+ )
76
+ }
54
77
  </SidePanelStack>
55
78
  );
56
79
  }
@@ -76,3 +99,6 @@ function PanelBody(props: PanelBodyProps) {
76
99
  if (panelId === 'metadata') return <MetadataPanel />;
77
100
  return <BandsPanel highlight={highlight} onHighlight={onHighlight} />;
78
101
  }
102
+
103
+ /** What a stack the host adds nothing to holds, kept stable for the memo. */
104
+ const NO_PANELS: readonly IrHostPanel[] = [];
@@ -8,18 +8,21 @@ import {
8
8
  statusSpacerStyle as spacerStyle,
9
9
  } from '../../panel/core/statusBar.ts';
10
10
  import { countAssigned } from '../core/assignBands.ts';
11
- import { formatWavenumber } from '../core/irFormat.ts';
12
- import { boxZoomOnly, yAxisTitle } from '../core/irMode.ts';
11
+ import { formatWavenumberRange } from '../core/irFormat.ts';
12
+ import { boxZoomOnly } from '../core/irMode.ts';
13
+ import { IR_TECHNIQUE_RULES } from '../core/irTechnique.ts';
13
14
 
14
15
  import { useIrEditorState } from './irStateContext.ts';
16
+ import { useIrText } from './useIrText.ts';
15
17
 
16
18
  /**
17
19
  * The one line under the chart: what is drawn, what was found, what went wrong.
18
20
  *
19
21
  * Everything in it is derived, so it is the cheapest place in the viewer to
20
22
  * answer "did that work" — how many spectra are drawn of those open, how many
21
- * bands the picking found and how many the table had something to say about, and
22
- * the range the selected spectrum covers.
23
+ * bands the picking found and how many the table had something to say about
24
+ * (where the table covers the technique), and the range the selected spectrum
25
+ * covers, in the order its axis is read.
23
26
  *
24
27
  * The refusal is last and is the only red in the shell, so the eye that has just
25
28
  * pressed something and seen nothing happen lands on the reason.
@@ -30,12 +33,14 @@ export function IrStatusBar() {
30
33
  useIrEditorState();
31
34
  const { spectra } = state.data;
32
35
  const { error, tool } = state.view;
33
- const { mode, pickBands } = state.settings;
36
+ const { mode, pickBands, technique } = state.settings;
37
+ const { reverseX, assignments } = IR_TECHNIQUE_RULES[technique];
38
+ const text = useIrText(technique);
34
39
 
35
40
  const range =
36
- selectedSpectrum === null || selectedSpectrum.wavenumber.length === 0
37
- ? null
38
- : `${formatWavenumber(selectedSpectrum.wavenumber.at(-1) as number)}–${formatWavenumber(selectedSpectrum.wavenumber[0] as number)} cm⁻¹`;
41
+ selectedSpectrum === null
42
+ ? ''
43
+ : formatWavenumberRange(selectedSpectrum.wavenumber, reverseX);
39
44
 
40
45
  return (
41
46
  <div style={barStyle}>
@@ -45,7 +50,7 @@ export function IrStatusBar() {
45
50
  : `${countLabel(visibleSpectra.length, 'spectrum', 'spectra')} drawn of ${spectra.length}`}
46
51
  </span>
47
52
 
48
- <span style={itemStyle}>{yAxisTitle(mode)}</span>
53
+ <span style={itemStyle}>{text.yTitle(mode)}</span>
49
54
 
50
55
  {selectedSpectrum === null ? null : (
51
56
  <span style={nameStyle} title={selectedSpectrum.name}>
@@ -53,12 +58,12 @@ export function IrStatusBar() {
53
58
  </span>
54
59
  )}
55
60
 
56
- {range === null ? null : <span style={mutedStyle}>{range}</span>}
61
+ {range === '' ? null : <span style={mutedStyle}>{range}</span>}
57
62
 
58
63
  {pickBands && assigned.length > 0 ? (
59
64
  <span style={itemStyle}>
60
- {countLabel(assigned.length, 'band', 'bands')},{' '}
61
- {countAssigned(assigned)} assigned
65
+ {countLabel(assigned.length, 'band', 'bands')}
66
+ {assignments ? `, ${countAssigned(assigned)} assigned` : null}
62
67
  </span>
63
68
  ) : null}
64
69
 
@@ -1,10 +1,13 @@
1
1
  import { Toolbar } from 'react-science/ui';
2
2
 
3
3
  import type { FigureDownloadState } from '../../download/ui/useFigureDownload.tsx';
4
- import { boxZoomOnly } from '../core/irMode.ts';
4
+ import { bandsPointDown, boxZoomOnly } from '../core/irMode.ts';
5
+ import { defaultIrMode } from '../core/irTechnique.ts';
6
+ import { irCommandOffered } from '../core/irTechniqueCommands.ts';
5
7
 
6
8
  import { useIrCommandProps } from './irCommandContext.tsx';
7
9
  import { useIrEditorState } from './irStateContext.ts';
10
+ import { useIrText } from './useIrText.ts';
8
11
 
9
12
  /** What {@link IrToolbar} needs. */
10
13
  export interface IrToolbarProps {
@@ -29,6 +32,9 @@ export interface IrToolbarProps {
29
32
  * drag on that axis is a rectangle, so both buttons go dead with the square zoom
30
33
  * lit. Showing `read` as available there would offer a gesture the chart does not
31
34
  * make, and showing it as *active* would name the wrong one.
35
+ *
36
+ * A button whose command the technique does not offer is not drawn: a Raman
37
+ * spectrum has a single value axis and no assignment to name.
32
38
  * @param props - Component props.
33
39
  * @returns The toolbar.
34
40
  */
@@ -38,7 +44,8 @@ export function IrToolbar(props: IrToolbarProps) {
38
44
  const command = useIrCommandProps();
39
45
  const { spectra } = state.data;
40
46
  const { domain, tool } = state.view;
41
- const { mode, pickBands, showAssignments } = state.settings;
47
+ const { mode, pickBands, showAssignments, technique } = state.settings;
48
+ const text = useIrText(technique);
42
49
 
43
50
  const isEmpty = spectra.length === 0;
44
51
  // The popover opens the panel itself, so the command's own click is left out.
@@ -49,7 +56,7 @@ export function IrToolbar(props: IrToolbarProps) {
49
56
  // `collapse`, not the default `wrap`: a wrapping vertical toolbar measures
50
57
  // itself and writes the result back as an inline width, so in a row short of
51
58
  // space it settles at half an icon and stays there.
52
- <Toolbar vertical overflow="collapse" aria-label="Infrared spectrum tools">
59
+ <Toolbar vertical overflow="collapse" aria-label={text.tools}>
53
60
  <Toolbar.Item
54
61
  icon="trash"
55
62
  intent="danger"
@@ -83,24 +90,28 @@ export function IrToolbar(props: IrToolbarProps) {
83
90
  disabled={domain === null}
84
91
  />
85
92
 
86
- <Toolbar.Item
87
- icon={mode === 'absorbance' ? 'arrow-up' : 'arrow-down'}
88
- active={mode === 'absorbance'}
89
- {...command('toggleMode')}
90
- disabled={isEmpty}
91
- />
93
+ {irCommandOffered(technique, 'toggleMode') ? (
94
+ <Toolbar.Item
95
+ icon={bandsPointDown(mode) ? 'arrow-down' : 'arrow-up'}
96
+ active={mode !== defaultIrMode(technique)}
97
+ {...command('toggleMode')}
98
+ disabled={isEmpty}
99
+ />
100
+ ) : null}
92
101
  <Toolbar.Item
93
102
  icon="locate"
94
103
  active={pickBands}
95
104
  {...command('togglePicking')}
96
105
  disabled={selectedSpectrum === null}
97
106
  />
98
- <Toolbar.Item
99
- icon="label"
100
- active={showAssignments}
101
- {...command('toggleAssignments')}
102
- disabled={!pickBands || selectedSpectrum === null}
103
- />
107
+ {irCommandOffered(technique, 'toggleAssignments') ? (
108
+ <Toolbar.Item
109
+ icon="label"
110
+ active={showAssignments}
111
+ {...command('toggleAssignments')}
112
+ disabled={!pickBands || selectedSpectrum === null}
113
+ />
114
+ ) : null}
104
115
 
105
116
  {/* What the chart looks like right now is what a figure is of — the
106
117
  window it was dragged to, the way up it is being read, the
@@ -26,7 +26,10 @@ export interface IrTracesProps {
26
26
  * the *high* end, the opposite of what every other chart's does.
27
27
  */
28
28
  xDomain: readonly [number, number];
29
- /** The wavenumber axis as it is currently zoomed, running right to left. */
29
+ /**
30
+ * The wavenumber axis as it is currently zoomed, running right to left for
31
+ * infrared.
32
+ */
30
33
  xScale: ChartScale;
31
34
  /** The value axis as it is currently zoomed. */
32
35
  yScale: ChartScale;
@@ -85,6 +88,7 @@ export function IrTraces(props: IrTracesProps): ReactElement {
85
88
  for (const spectrum of spectra) {
86
89
  if (!spectrum.visible) continue;
87
90
  const trace = traceOf(spectrum, mode);
91
+ if (trace === undefined) continue;
88
92
  const { x, y } = xyReduce(trace, { from, to, nbPoints: wanted });
89
93
  const d = profilePath(x, y, xScale, yScale);
90
94
  if (d !== '') drawn.push({ id: spectrum.id, color: spectrum.color, d });
@@ -0,0 +1,71 @@
1
+ import type { Ref } from 'react';
2
+
3
+ import type { IrEditorHandle, IrPlotClick } from '../core/irEditorApi.ts';
4
+ import type { IrPanelId } from '../core/irSidePanels.ts';
5
+ import type { IrSpectrum } from '../core/irSpectrum.ts';
6
+
7
+ import { VibrationalEditor } from './VibrationalEditor.tsx';
8
+ import type { IrHostPanel } from './irHostPanels.ts';
9
+
10
+ /** The handle a host drives a Raman viewer through: the infrared one's. */
11
+ export type RamanEditorHandle = IrEditorHandle;
12
+
13
+ export interface RamanEditorProps {
14
+ /**
15
+ * The spectra to open on, each carrying its `intensity`. Read when the viewer
16
+ * opens and never again: what is on the chart belongs to the viewer from then
17
+ * on. The `ref` handle is how spectra arrive afterwards.
18
+ * @default []
19
+ */
20
+ data?: IrSpectrum[];
21
+ /**
22
+ * Called whenever the spectra open change — one loaded, one closed, the chart
23
+ * cleared — with the spectra now open. Not called for a zoom, a selection, a
24
+ * rename or a colour.
25
+ * @default undefined
26
+ */
27
+ onChange?: (spectra: IrSpectrum[]) => void;
28
+ /**
29
+ * The side panels open to begin with: the viewer's own — `'spectra'`,
30
+ * `'bands'`, `'metadata'` — or the id of one of `panels`. An id no panel
31
+ * answers to is ignored.
32
+ * @default DEFAULT_SIDE_PANELS
33
+ */
34
+ defaultPanelIds?: readonly IrPanelId[];
35
+ /**
36
+ * Panels the host adds to the viewer's own. Their icons come first in the
37
+ * activity bar, in the order given, and each then behaves as a built-in panel
38
+ * does: toggled on its own, stacked in the same column with a share of its
39
+ * height, folded and closed from its header.
40
+ * @default []
41
+ */
42
+ panels?: readonly IrHostPanel[];
43
+ /**
44
+ * The plot was clicked at this Raman shift (a press that did not travel, i.e.
45
+ * not a zoom drag), with the spectrum selected at that moment. The shift is
46
+ * reported as `wavenumber`, the name both techniques share.
47
+ * @default undefined
48
+ */
49
+ onPlotClick?: (click: IrPlotClick) => void;
50
+ /**
51
+ * The handle a host drives the viewer through: take these spectra, frame this
52
+ * Raman shift, select that one.
53
+ * @default undefined
54
+ */
55
+ ref?: Ref<RamanEditorHandle>;
56
+ }
57
+
58
+ /**
59
+ * A Raman spectrum viewer: the infrared viewer's shell, panels, gestures and
60
+ * export, changed only where Raman is physically different.
61
+ *
62
+ * The spectra are read as intensity, their one value axis, so there is no mode
63
+ * to choose; the Raman shift runs from low at the left to high at the right;
64
+ * the bands are picked as maxima of intensity; and the infrared correlation
65
+ * table is not asked what a band might be.
66
+ * @param props - Component props.
67
+ * @returns The viewer.
68
+ */
69
+ export function RamanEditor(props: RamanEditorProps) {
70
+ return <VibrationalEditor technique="raman" {...props} />;
71
+ }
@@ -37,7 +37,7 @@ export function SpectraPanel() {
37
37
  const actions = useIrActions();
38
38
  const { spectra } = state.data;
39
39
  const { selectedId } = state.view;
40
- const { mode } = state.settings;
40
+ const { mode, technique } = state.settings;
41
41
 
42
42
  const selected = spectra.find((spectrum) => spectrum.id === selectedId);
43
43
  const allDrawn = spectra.every((spectrum) => spectrum.visible);
@@ -96,6 +96,7 @@ export function SpectraPanel() {
96
96
  <SpectrumRow
97
97
  key={spectrum.id}
98
98
  spectrum={spectrum}
99
+ technique={technique}
99
100
  selected={spectrum.id === selectedId}
100
101
  onSelect={() => actions.selectSpectrum(spectrum.id)}
101
102
  onToggle={() =>