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
@@ -5,6 +5,7 @@ import type { FigureNotice } from '../../download/core/copyFigure.ts';
5
5
  import { copyFigure } from '../../download/core/copyFigure.ts';
6
6
  import type { FigureFormat } from '../../download/core/downloadFigure.ts';
7
7
  import type { FigurePixels } from '../../download/core/figureScale.ts';
8
+ import { DEFAULT_FRAMES_PER_SECOND } from '../core/animatedPng.ts';
8
9
 
9
10
  import type { SceneCapture } from './exportMoleculeImage.ts';
10
11
  import {
@@ -16,8 +17,15 @@ import {
16
17
  export interface ImageExport {
17
18
  /** Size of the canvas on screen, or `null` before it is laid out. */
18
19
  canvasSize: () => FigurePixels | null;
19
- /** Render the scene at `scale` and download it as `format`. */
20
- exportImage: (format: FigureFormat, scale: number) => Promise<void>;
20
+ /**
21
+ * Render the scene at `scale` and download it as `format` — every frame of
22
+ * it, as an animated PNG, when `animated` is set and the format is PNG.
23
+ */
24
+ exportImage: (
25
+ format: FigureFormat,
26
+ scale: number,
27
+ animated?: boolean,
28
+ ) => Promise<void>;
21
29
  /**
22
30
  * Render the scene at `scale` and put it on the clipboard as a PNG. Call it
23
31
  * from the click itself: Safari only allows a write the click started.
@@ -30,12 +38,15 @@ export interface ImageExport {
30
38
  * @param container - The element molstar draws into.
31
39
  * @param viewerRef - The viewer, once created.
32
40
  * @param fileName - File name without its extension.
41
+ * @param framesPerSecond - How fast an animated PNG plays its frames.
42
+ * @default 25
33
43
  * @returns See {@link ImageExport}.
34
44
  */
35
45
  export function useImageExport(
36
46
  container: HTMLDivElement | null,
37
47
  viewerRef: RefObject<SceneCapture | null>,
38
48
  fileName: string,
49
+ framesPerSecond = DEFAULT_FRAMES_PER_SECOND,
39
50
  ): ImageExport {
40
51
  const canvasSize = useCallback((): FigurePixels | null => {
41
52
  if (container === null) return null;
@@ -45,15 +56,21 @@ export function useImageExport(
45
56
  }, [container]);
46
57
 
47
58
  const exportImage = useCallback(
48
- async (format: FigureFormat, scale: number) => {
59
+ async (format: FigureFormat, scale: number, animated = false) => {
49
60
  const viewer = viewerRef.current;
50
61
  const size = canvasSize();
51
62
  if (viewer === null || size === null) {
52
63
  throw new Error('There is no picture to export yet.');
53
64
  }
54
- await exportMoleculeImage(viewer, { format, scale, size, fileName });
65
+ await exportMoleculeImage(viewer, {
66
+ format,
67
+ scale,
68
+ size,
69
+ fileName,
70
+ framesPerSecond: animated ? framesPerSecond : undefined,
71
+ });
55
72
  },
56
- [canvasSize, viewerRef, fileName],
73
+ [canvasSize, viewerRef, fileName, framesPerSecond],
57
74
  );
58
75
 
59
76
  const copyImage = useCallback(
@@ -12,8 +12,9 @@
12
12
  import type { RefObject } from 'react';
13
13
  import { useCallback, useEffect, useRef } from 'react';
14
14
 
15
+ import type { Molecule3DFile } from '../core/file.ts';
15
16
  import type { Measurement } from '../core/measurement.ts';
16
- import type { Molecule3DFile, Molecule3DSettings } from '../core/settings.ts';
17
+ import type { Molecule3DSettings } from '../core/settings.ts';
17
18
 
18
19
  import type { MoleculeViewer3DProps } from './moleculeViewer3DProps.ts';
19
20
  import { SceneDrawer } from './sceneDrawer.ts';
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The molstar viewer of one canvas: created once its element exists, kept to
3
+ * the element's size, and disposed with it.
4
+ */
5
+
6
+ import type { RefObject } from 'react';
7
+ import { useEffect, useRef } from 'react';
8
+
9
+ import { createMolecule3DViewer } from './createViewer.ts';
10
+ import type { Molecule3DViewer } from './viewer.ts';
11
+ import type { Molecule3DViewerOptions } from './viewerTypes.ts';
12
+
13
+ /**
14
+ * Mount a viewer in `container` for as long as it exists.
15
+ * @param container - The element molstar draws in, or `null` before it exists.
16
+ * @param options - Read when the viewer is created; a later change is ignored,
17
+ * so a callback reads what it needs from a ref of its own.
18
+ * @returns The viewer, holding `null` while there is none.
19
+ */
20
+ export function useMoleculeViewer(
21
+ container: HTMLElement | null,
22
+ options: Molecule3DViewerOptions,
23
+ ): RefObject<Molecule3DViewer | null> {
24
+ const viewerRef = useRef<Molecule3DViewer | null>(null);
25
+ const latestOptions = useRef(options);
26
+ useEffect(() => {
27
+ latestOptions.current = options;
28
+ });
29
+
30
+ useEffect(() => {
31
+ if (container === null) return;
32
+ const viewer = createMolecule3DViewer(container, latestOptions.current);
33
+ viewerRef.current = viewer;
34
+ const observer = new ResizeObserver(() => {
35
+ viewer.handleResize();
36
+ });
37
+ observer.observe(container);
38
+ return () => {
39
+ observer.disconnect();
40
+ viewerRef.current = null;
41
+ viewer.dispose();
42
+ };
43
+ }, [container]);
44
+
45
+ return viewerRef;
46
+ }
@@ -1,14 +1,14 @@
1
1
  import { useEffect, useState } from 'react';
2
2
 
3
- import type { Molecule3DFile } from '../core/settings.ts';
3
+ import type { Molecule3DFile } from '../core/file.ts';
4
4
 
5
5
  /**
6
6
  * Ertl's topological polar surface area of the molecule, from openchemlib,
7
7
  * loaded only once a caller asks for it.
8
8
  * @param molfile - The molecule, or `null`.
9
9
  * @param enabled - Whether to compute it at all.
10
- * @returns The area in Ų, or `null` while unknown, disabled, or when
11
- * openchemlib is not installed or cannot read the molfile.
10
+ * @returns The area in Ų, or `null` while unknown, disabled, for an XYZ
11
+ * file, or when openchemlib is not installed or cannot read the molfile.
12
12
  */
13
13
  export function usePolarSurfaceArea(
14
14
  molfile: Molecule3DFile | null,
@@ -18,7 +18,9 @@ export function usePolarSurfaceArea(
18
18
  data: string;
19
19
  area: number | null;
20
20
  } | null>(null);
21
- const data = enabled ? (molfile?.data ?? null) : null;
21
+ // An XYZ file has no bonds for openchemlib to find the polar atoms by.
22
+ const data =
23
+ enabled && molfile?.format !== 'xyz' ? (molfile?.data ?? null) : null;
22
24
 
23
25
  useEffect(() => {
24
26
  if (data === null) return;
@@ -8,7 +8,6 @@
8
8
  * is the component's.
9
9
  */
10
10
 
11
- import type { PluginContext } from 'molstar/lib/mol-plugin/context.js';
12
11
  import { Color } from 'molstar/lib/mol-util/color/color.js';
13
12
 
14
13
  import {
@@ -24,11 +23,12 @@ import {
24
23
  } from '../../molstar/core/index.ts';
25
24
  import type { Molecule3DCamera } from '../core/camera.ts';
26
25
  import type { ImageSize } from '../core/exportImage.ts';
26
+ import type { Molecule3DFile } from '../core/file.ts';
27
27
  import type { Molecule3DHighlight } from '../core/highlight.ts';
28
28
  import type { Measurement, MeasurementKind } from '../core/measurement.ts';
29
- import type { Molecule3DFile } from '../core/settings.ts';
30
29
 
31
30
  import { applyCamera, resetCamera, watchCamera } from './camera.ts';
31
+ import { MoleculeFrames } from './moleculeFrames.ts';
32
32
  import {
33
33
  MODEL_REPRESENTATION_REF,
34
34
  clearMolecule,
@@ -54,16 +54,24 @@ export class Molecule3DViewer {
54
54
  /** Resolves once the canvas exists; every method awaits it internally. */
55
55
  readonly ready: Promise<void>;
56
56
 
57
+ /** The frames of the file on screen: playing them, and their pictures. */
58
+ readonly frames: MoleculeFrames;
59
+
57
60
  /**
58
61
  * Mount the canvas and start initialising the plugin.
59
62
  * @param container - A positioned element.
60
63
  * @param options - See {@link Molecule3DViewerOptions}.
61
64
  */
62
65
  constructor(container: HTMLElement, options: Molecule3DViewerOptions = {}) {
63
- const { background, onMeasure = ignore } = options;
66
+ const {
67
+ background,
68
+ onMeasure = ignore,
69
+ onFrameCountChange = ignore,
70
+ } = options;
64
71
  this.#plugin = new MolstarPlugin(container, { background });
65
72
  this.ready = this.#plugin.ready;
66
- // Registered before any `#run`, so the picker exists by the time one runs.
73
+ this.frames = new MoleculeFrames(this.#plugin, onFrameCountChange);
74
+ // Registered before any other `run`, so the picker exists by the time one runs.
67
75
  void this.#plugin
68
76
  .run((plugin) => {
69
77
  this.#picker = new MeasurementPicker(
@@ -84,10 +92,12 @@ export class Molecule3DViewer {
84
92
  * @throws {Error} When the file parses to zero atoms.
85
93
  */
86
94
  showMolecule(molfile: Molecule3DFile, style?: MoleculeStyle): Promise<void> {
87
- return this.#run(async (plugin) => {
88
- await clearMeasurements(plugin);
89
- await renderMolecule(plugin, molfile, style);
90
- });
95
+ return this.#plugin.run((plugin) =>
96
+ this.frames.redraw(plugin, async () => {
97
+ await clearMeasurements(plugin);
98
+ return renderMolecule(plugin, molfile, style);
99
+ }),
100
+ );
91
101
  }
92
102
 
93
103
  /**
@@ -95,10 +105,13 @@ export class Molecule3DViewer {
95
105
  * @returns Nothing; resolves once the scene is empty.
96
106
  */
97
107
  hideMolecule(): Promise<void> {
98
- return this.#run(async (plugin) => {
99
- await clearMeasurements(plugin);
100
- await clearMolecule(plugin);
101
- });
108
+ return this.#plugin.run((plugin) =>
109
+ this.frames.redraw(plugin, async () => {
110
+ await clearMeasurements(plugin);
111
+ await clearMolecule(plugin);
112
+ return 0;
113
+ }),
114
+ );
102
115
  }
103
116
 
104
117
  /**
@@ -107,7 +120,7 @@ export class Molecule3DViewer {
107
120
  * @returns Nothing; resolves once the surface is on screen.
108
121
  */
109
122
  showSurface(style?: SurfaceStyle): Promise<void> {
110
- return this.#run((plugin) => renderSurface(plugin, style));
123
+ return this.#plugin.run((plugin) => renderSurface(plugin, style));
111
124
  }
112
125
 
113
126
  /**
@@ -115,7 +128,7 @@ export class Molecule3DViewer {
115
128
  * @returns Nothing; resolves once the surface is gone.
116
129
  */
117
130
  hideSurface(): Promise<void> {
118
- return this.#run((plugin) => clearSurface(plugin));
131
+ return this.#plugin.run((plugin) => clearSurface(plugin));
119
132
  }
120
133
 
121
134
  /**
@@ -124,7 +137,7 @@ export class Molecule3DViewer {
124
137
  * @returns Nothing; resolves once the labels are on screen.
125
138
  */
126
139
  showMeasurements(measurements: readonly Measurement[]): Promise<void> {
127
- return this.#run((plugin) =>
140
+ return this.#plugin.run((plugin) =>
128
141
  renderMeasurements(plugin, measurements, moleculeStructure),
129
142
  );
130
143
  }
@@ -140,7 +153,7 @@ export class Molecule3DViewer {
140
153
  highlights: readonly Molecule3DHighlight[],
141
154
  color: string,
142
155
  ): Promise<void> {
143
- return this.#run(() => {
156
+ return this.#plugin.run(() => {
144
157
  this.#painter?.set(highlights, Color.fromHexStyle(color));
145
158
  });
146
159
  }
@@ -151,7 +164,7 @@ export class Molecule3DViewer {
151
164
  * @returns Nothing; resolves once the plugin has switched mode.
152
165
  */
153
166
  setMeasureKind(kind: MeasurementKind | null): Promise<void> {
154
- return this.#run(() => {
167
+ return this.#plugin.run(() => {
155
168
  this.#picker?.setKind(kind);
156
169
  });
157
170
  }
@@ -164,7 +177,7 @@ export class Molecule3DViewer {
164
177
  * @throws {Error} When the plugin has no screenshot helper.
165
178
  */
166
179
  captureImage(size: ImageSize): Promise<string | undefined> {
167
- return this.#run((plugin) => captureScene(plugin, size));
180
+ return this.#plugin.run((plugin) => captureScene(plugin, size));
168
181
  }
169
182
 
170
183
  /**
@@ -177,7 +190,7 @@ export class Molecule3DViewer {
177
190
  durationMilliseconds = DEFAULT_CAMERA_DURATION,
178
191
  fromFront = false,
179
192
  ): Promise<void> {
180
- return this.#run((plugin) => {
193
+ return this.#plugin.run((plugin) => {
181
194
  resetCamera(plugin, durationMilliseconds, fromFront);
182
195
  });
183
196
  }
@@ -189,7 +202,7 @@ export class Molecule3DViewer {
189
202
  * @returns Nothing; resolves once the move has been ordered.
190
203
  */
191
204
  setCamera(camera: Molecule3DCamera, durationMilliseconds = 0): Promise<void> {
192
- return this.#run((plugin) => {
205
+ return this.#plugin.run((plugin) => {
193
206
  applyCamera(plugin, camera, durationMilliseconds);
194
207
  });
195
208
  }
@@ -211,7 +224,7 @@ export class Molecule3DViewer {
211
224
  * @returns Nothing; resolves once the trackball has been reconfigured.
212
225
  */
213
226
  setSpin(spinning: boolean, speed = DEFAULT_SPIN_SPEED): Promise<void> {
214
- return this.#run((plugin) => {
227
+ return this.#plugin.run((plugin) => {
215
228
  setSpin(plugin, spinning, speed);
216
229
  });
217
230
  }
@@ -227,12 +240,6 @@ export class Molecule3DViewer {
227
240
  this.#painter?.dispose();
228
241
  this.#plugin.dispose();
229
242
  }
230
-
231
- #run<Result>(
232
- action: (plugin: PluginContext) => Result | Promise<Result>,
233
- ): Promise<Result | undefined> {
234
- return this.#plugin.run(action);
235
- }
236
243
  }
237
244
 
238
245
  function ignore(): void {
@@ -19,6 +19,12 @@ export interface Molecule3DViewerOptions {
19
19
  * @default undefined
20
20
  */
21
21
  onMeasure?: (measurement: Measurement) => void;
22
+ /**
23
+ * Called with how many frames the file on screen holds, each time a file is
24
+ * drawn, and with 0 once the scene is emptied.
25
+ * @default undefined
26
+ */
27
+ onFrameCountChange?: (frameCount: number) => void;
22
28
  }
23
29
 
24
30
  /** How to draw the model. */
@@ -1,11 +1,22 @@
1
1
  /**
2
- * A picture of the scene, rendered off screen at a size of its own.
2
+ * A picture of the scene, rendered off screen at a size of its own — one
3
+ * frame, or every frame of the trajectory on screen.
3
4
  */
4
5
 
5
6
  import type { PluginContext } from 'molstar/lib/mol-plugin/context.js';
7
+ import type { ViewportScreenshotHelper } from 'molstar/lib/mol-plugin/util/viewport-screenshot.js';
8
+ import { Task } from 'molstar/lib/mol-task/index.js';
6
9
 
7
10
  import type { ImageSize } from '../../molecule3d/core/exportImage.ts';
8
11
 
12
+ import {
13
+ setTrajectoryPlayback,
14
+ showTrajectoryFrame,
15
+ shownTrajectoryFrame,
16
+ stopTrajectory,
17
+ trajectoryFrameCount,
18
+ } from './trajectory.ts';
19
+
9
20
  /**
10
21
  * Render the scene without its selection highlights or its axes.
11
22
  * @param plugin - The molstar context.
@@ -17,6 +28,78 @@ export async function captureScene(
17
28
  plugin: PluginContext,
18
29
  size: ImageSize,
19
30
  ): Promise<string> {
31
+ return pictureHelper(plugin, size).getImageDataUri();
32
+ }
33
+
34
+ /** How a series of frames is played, so it can be resumed once captured. */
35
+ export interface FramePlayback {
36
+ playing: boolean;
37
+ framesPerSecond: number;
38
+ }
39
+
40
+ /**
41
+ * Render every frame of the trajectory on screen, in order, as the scene shows
42
+ * it: the model, its surface and the measurements over it, each at that frame.
43
+ * The animation is stopped while the frames are taken and resumed afterwards,
44
+ * and the scene is left on the frame it showed.
45
+ * @param plugin - The molstar context.
46
+ * @param size - Pixel size of each picture.
47
+ * @param playback - What to resume once the frames are taken.
48
+ * @returns One picture per frame; a scene of one model gives one.
49
+ * @throws {Error} When the plugin has no screenshot helper.
50
+ */
51
+ export async function captureFrames(
52
+ plugin: PluginContext,
53
+ size: ImageSize,
54
+ playback: FramePlayback,
55
+ ): Promise<ImageData[]> {
56
+ const pass = pictureHelper(plugin, size).imagePass;
57
+ const loop = plugin.animationLoop;
58
+ const shown = shownTrajectoryFrame(plugin);
59
+ const count = Math.max(1, trajectoryFrameCount(plugin));
60
+ await stopTrajectory(plugin);
61
+ loop.stop({ noDraw: true });
62
+ try {
63
+ await pass.updateBackground();
64
+ const frames: ImageData[] = [];
65
+ for (let index = 0; index < count; index++) {
66
+ // eslint-disable-next-line no-await-in-loop -- each frame is a commit of the state tree, and commits must not interleave
67
+ if (count > 1) await showTrajectoryFrame(plugin, index);
68
+ // The scene is otherwise committed on the next animation frame, after
69
+ // the picture has been taken of the previous one.
70
+ plugin.canvas3d?.commit(true);
71
+ // eslint-disable-next-line no-await-in-loop -- one render at a time on the one image pass
72
+ const image = await plugin.runTask(
73
+ Task.create('Render a frame', (runtime) =>
74
+ pass.getImageData(runtime, size.width, size.height),
75
+ ),
76
+ );
77
+ frames.push(image);
78
+ }
79
+ return frames;
80
+ } finally {
81
+ if (count > 1) await showTrajectoryFrame(plugin, shown);
82
+ loop.start({ immediate: true });
83
+ await setTrajectoryPlayback(
84
+ plugin,
85
+ playback.playing,
86
+ playback.framesPerSecond,
87
+ );
88
+ }
89
+ }
90
+
91
+ /**
92
+ * The screenshot helper, set to draw a picture of `size` with no axes and an
93
+ * opaque background.
94
+ * @param plugin - The molstar context.
95
+ * @param size - Pixel size of the picture.
96
+ * @returns The helper.
97
+ * @throws {Error} When the plugin has no screenshot helper.
98
+ */
99
+ function pictureHelper(
100
+ plugin: PluginContext,
101
+ size: ImageSize,
102
+ ): ViewportScreenshotHelper {
20
103
  const helper = plugin.helpers.viewportScreenshot;
21
104
  if (helper === undefined) {
22
105
  throw new Error('This viewer cannot take a picture of its scene.');
@@ -27,5 +110,5 @@ export async function captureScene(
27
110
  axes: { name: 'off', params: {} },
28
111
  transparent: false,
29
112
  });
30
- return helper.getImageDataUri();
113
+ return helper;
31
114
  }
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * The molstar layer under the 3D views: the plugin lifecycle, the camera, the
3
- * hover labels, the measurements, the highlights and the picture of a scene.
3
+ * hover labels, the measurements, the highlights, the frames of a trajectory
4
+ * and the picture of a scene.
4
5
  *
5
6
  * Three of our sites mount a headless molstar canvas — the molecule viewer
6
7
  * here, lcao's orbitals and symmetry's crystals — and each of them had its own
@@ -49,7 +50,8 @@ export {
49
50
  } from './hover.ts';
50
51
  export type { MolstarPluginOptions } from './plugin.ts';
51
52
  export { MolstarPlugin } from './plugin.ts';
52
- export { captureScene } from './captureScene.ts';
53
+ export type { FramePlayback } from './captureScene.ts';
54
+ export { captureFrames, captureScene } from './captureScene.ts';
53
55
  export type { MoleculeStructureSource } from './measurements.ts';
54
56
  export {
55
57
  MeasurementPicker,
@@ -57,3 +59,12 @@ export {
57
59
  clearMeasurements,
58
60
  renderMeasurements,
59
61
  } from './measurements.ts';
62
+ export {
63
+ PLAYBACK_FPS_RANGE,
64
+ clampFramesPerSecond,
65
+ setTrajectoryPlayback,
66
+ showTrajectoryFrame,
67
+ shownTrajectoryFrame,
68
+ stopTrajectory,
69
+ trajectoryFrameCount,
70
+ } from './trajectory.ts';
@@ -0,0 +1,117 @@
1
+ /**
2
+ * The frames of a trajectory: how many there are, which one is shown, and
3
+ * playing them in a loop.
4
+ *
5
+ * molstar keeps a trajectory as one data node and shows one of its frames
6
+ * through a `ModelFromTrajectory` node whose `modelIndex` says which. Playing
7
+ * is molstar's own model-index animation, which steps that index; showing one
8
+ * frame sets it.
9
+ */
10
+
11
+ import type { PluginContext } from 'molstar/lib/mol-plugin/context.js';
12
+ import { AnimateModelIndex } from 'molstar/lib/mol-plugin-state/animation/built-in/model-index.js';
13
+ import { PluginStateObject } from 'molstar/lib/mol-plugin-state/objects.js';
14
+ import { ModelFromTrajectory } from 'molstar/lib/mol-plugin-state/transforms/model.js';
15
+ import { StateSelection } from 'molstar/lib/mol-state/index.js';
16
+
17
+ /** How fast molstar's model-index animation can step, frames per second. */
18
+ export const PLAYBACK_FPS_RANGE = { minimum: 5, maximum: 60 } as const;
19
+
20
+ /**
21
+ * How many frames the trajectory on screen holds.
22
+ * @param plugin - The molstar context.
23
+ * @returns The most frames of any trajectory shown; 0 when none is.
24
+ */
25
+ export function trajectoryFrameCount(plugin: PluginContext): number {
26
+ const state = plugin.state.data;
27
+ let count = 0;
28
+ for (const model of modelCells(plugin)) {
29
+ const trajectory = StateSelection.findAncestorOfType(
30
+ state.tree,
31
+ state.cells,
32
+ model.transform.ref,
33
+ PluginStateObject.Molecule.Trajectory,
34
+ );
35
+ count = Math.max(count, trajectory?.obj?.data.frameCount ?? 0);
36
+ }
37
+ return count;
38
+ }
39
+
40
+ /**
41
+ * Show one frame of every trajectory on screen, and everything built on it:
42
+ * the drawn model, its surface and the measurements over it.
43
+ * @param plugin - The molstar context.
44
+ * @param index - The frame, from 0.
45
+ * @returns Nothing; resolves once the state tree is updated.
46
+ */
47
+ export async function showTrajectoryFrame(
48
+ plugin: PluginContext,
49
+ index: number,
50
+ ): Promise<void> {
51
+ const update = plugin.build();
52
+ for (const model of modelCells(plugin)) {
53
+ update.to(model).update({ modelIndex: index });
54
+ }
55
+ await update.commit();
56
+ }
57
+
58
+ /**
59
+ * The frame on screen.
60
+ * @param plugin - The molstar context.
61
+ * @returns The index of the frame the first trajectory shows; 0 when none is.
62
+ */
63
+ export function shownTrajectoryFrame(plugin: PluginContext): number {
64
+ return modelCells(plugin)[0]?.transform.params?.modelIndex ?? 0;
65
+ }
66
+
67
+ /**
68
+ * Play the frames in a loop, or stop them where they stand.
69
+ * @param plugin - The molstar context.
70
+ * @param playing - Whether to play. A trajectory of one frame never plays.
71
+ * @param framesPerSecond - How fast, clamped into {@link PLAYBACK_FPS_RANGE}.
72
+ * @returns Nothing; resolves once the animation is started or stopped.
73
+ */
74
+ export async function setTrajectoryPlayback(
75
+ plugin: PluginContext,
76
+ playing: boolean,
77
+ framesPerSecond: number,
78
+ ): Promise<void> {
79
+ if (!playing || trajectoryFrameCount(plugin) < 2) {
80
+ await stopTrajectory(plugin);
81
+ return;
82
+ }
83
+ await plugin.managers.animation.play(AnimateModelIndex, {
84
+ mode: { name: 'loop', params: { direction: 'forward' } },
85
+ duration: {
86
+ name: 'sequential',
87
+ params: { maxFps: clampFramesPerSecond(framesPerSecond) },
88
+ },
89
+ });
90
+ }
91
+
92
+ /**
93
+ * Stop the frames where they stand.
94
+ * @param plugin - The molstar context.
95
+ * @returns Nothing; resolves once the animation is stopped.
96
+ */
97
+ export async function stopTrajectory(plugin: PluginContext): Promise<void> {
98
+ const animation = plugin.managers.animation;
99
+ if (animation.isAnimating) await animation.stop();
100
+ }
101
+
102
+ /**
103
+ * A frame rate molstar's model-index animation accepts.
104
+ * @param framesPerSecond - Any rate.
105
+ * @returns The rate, rounded and clamped into {@link PLAYBACK_FPS_RANGE}.
106
+ */
107
+ export function clampFramesPerSecond(framesPerSecond: number): number {
108
+ const { minimum, maximum } = PLAYBACK_FPS_RANGE;
109
+ if (!Number.isFinite(framesPerSecond)) return minimum;
110
+ return Math.min(maximum, Math.max(minimum, Math.round(framesPerSecond)));
111
+ }
112
+
113
+ function modelCells(plugin: PluginContext) {
114
+ return plugin.state.data.select(
115
+ StateSelection.Generators.ofTransformer(ModelFromTrajectory),
116
+ );
117
+ }
@@ -55,6 +55,9 @@ export function PanelRail<TId extends string>(
55
55
  id={panel.id}
56
56
  icon={panel.icon}
57
57
  tooltip={panel.title}
58
+ // A tooltip is not an accessible name: without this every toggle is
59
+ // an icon-only button with no name at all.
60
+ aria-label={panel.title}
58
61
  active={openIds.includes(panel.id)}
59
62
  onClick={() => onToggle(panel.id)}
60
63
  />
package/src/raman.ts ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Displaying Raman spectra: the infrared viewer, read for Raman.
3
+ *
4
+ * A door of its own so a page showing Raman spectra imports a Raman viewer by
5
+ * name. What it opens is the same code as `react-cheminfo/ir` — one shell, one
6
+ * set of panels — and the same spectrum model, which a host fills with an
7
+ * `intensity` array where an infrared spectrum carries absorbance and
8
+ * transmittance.
9
+ */
10
+
11
+ export type { LoadedIrSpectrum } from './ir/core/analysisSpectra.ts';
12
+ export type { IrEditorHandle, IrPlotClick } from './ir/core/irEditorApi.ts';
13
+ export type { IrSpectrum } from './ir/core/irSpectrum.ts';
14
+ export { toIrSpectra } from './ir/core/toIrSpectrum.ts';
15
+ export type { IrHostPanel } from './ir/ui/irHostPanels.ts';
16
+ export type {
17
+ RamanEditorHandle,
18
+ RamanEditorProps,
19
+ } from './ir/ui/RamanEditor.tsx';
20
+ export { RamanEditor } from './ir/ui/RamanEditor.tsx';
@@ -4,8 +4,8 @@ import { trimTrailingSlash } from './address.ts';
4
4
  * Where a site is mounted, read off the page rather than off the build.
5
5
  *
6
6
  * The build is mount-agnostic — vite is given a relative base, so the same
7
- * `dist` serves `https://surge.cheminfo.org/` and
8
- * `https://www.cheminfo.org/surge/`. What tells the two apart is the `<base>`
7
+ * `dist` serves `https://isomers.cheminfo.org/` and
8
+ * `https://www.cheminfo.org/isomers/`. What tells the two apart is the `<base>`
9
9
  * the deployment stamps into the page it hands out, and `document.baseURI`
10
10
  * resolves it against the address actually opened. So this answers correctly
11
11
  * whether or not a slash closes the address, and on an address the SPA
@@ -16,7 +16,7 @@ import {
16
16
  *
17
17
  * The mount is read off the page, not off the build: the build carries no
18
18
  * mount, and the `<base>` a deployment stamps into its pages is what tells
19
- * `https://surge.cheminfo.org/` from `https://www.cheminfo.org/surge/`. Under
19
+ * `https://isomers.cheminfo.org/` from `https://www.cheminfo.org/isomers/`. Under
20
20
  * Node there is no page, and the mount is the root.
21
21
  * @param siteId - The site, as `ECOSYSTEM_SITES` names it.
22
22
  * @param options - A mount path to use instead of the one read off the page.
@@ -130,7 +130,7 @@ export function originOf(options: SiteOrigin): string {
130
130
  const origin = options.origin ?? `https://${resolveSite(options.site).host}`;
131
131
  if (!HTTP_ORIGIN.test(origin) || !URL.canParse(origin)) {
132
132
  throw new Error(
133
- `an origin is an absolute address, e.g. https://surge.cheminfo.org: ${JSON.stringify(origin)}`,
133
+ `an origin is an absolute address, e.g. https://isomers.cheminfo.org: ${JSON.stringify(origin)}`,
134
134
  );
135
135
  }
136
136
  return trimTrailingSlash(origin);