react-cheminfo 0.76.0 → 0.78.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 (389) hide show
  1. package/README.md +141 -31
  2. package/lib/card/core/cardAddress.d.ts +19 -2
  3. package/lib/card/core/cardAddress.d.ts.map +1 -1
  4. package/lib/card/core/cardAddress.js +35 -2
  5. package/lib/card/core/cardAddress.js.map +1 -1
  6. package/lib/card/core/cardPageUrl.d.ts +7 -1
  7. package/lib/card/core/cardPageUrl.d.ts.map +1 -1
  8. package/lib/card/core/cardPageUrl.js +4 -2
  9. package/lib/card/core/cardPageUrl.js.map +1 -1
  10. package/lib/card/core/index.d.ts +1 -1
  11. package/lib/card/core/index.d.ts.map +1 -1
  12. package/lib/card/core/index.js +1 -1
  13. package/lib/card/core/index.js.map +1 -1
  14. package/lib/credits/core/credits.d.ts +30 -0
  15. package/lib/credits/core/credits.d.ts.map +1 -1
  16. package/lib/credits/core/credits.js +35 -0
  17. package/lib/credits/core/credits.js.map +1 -1
  18. package/lib/download/core/downloadFigure.d.ts +12 -1
  19. package/lib/download/core/downloadFigure.d.ts.map +1 -1
  20. package/lib/download/core/downloadFigure.js +21 -0
  21. package/lib/download/core/downloadFigure.js.map +1 -1
  22. package/lib/download/core/figureDpi.d.ts +59 -0
  23. package/lib/download/core/figureDpi.d.ts.map +1 -0
  24. package/lib/download/core/figureDpi.js +75 -0
  25. package/lib/download/core/figureDpi.js.map +1 -0
  26. package/lib/download/core/figurePng.d.ts +4 -1
  27. package/lib/download/core/figurePng.d.ts.map +1 -1
  28. package/lib/download/core/figurePng.js +11 -2
  29. package/lib/download/core/figurePng.js.map +1 -1
  30. package/lib/download/core/index.d.ts +4 -1
  31. package/lib/download/core/index.d.ts.map +1 -1
  32. package/lib/download/core/index.js +3 -1
  33. package/lib/download/core/index.js.map +1 -1
  34. package/lib/download/core/pngDpi.d.ts +22 -0
  35. package/lib/download/core/pngDpi.d.ts.map +1 -0
  36. package/lib/download/core/pngDpi.js +79 -0
  37. package/lib/download/core/pngDpi.js.map +1 -0
  38. package/lib/download/ui/FigureDownloadPanel.d.ts +13 -0
  39. package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
  40. package/lib/download/ui/FigureDownloadPanel.js +18 -34
  41. package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
  42. package/lib/download/ui/figureDownloadHint.d.ts +5 -0
  43. package/lib/download/ui/figureDownloadHint.d.ts.map +1 -1
  44. package/lib/download/ui/figureDownloadHint.js +8 -0
  45. package/lib/download/ui/figureDownloadHint.js.map +1 -1
  46. package/lib/download/ui/figureDownloadOptions.d.ts +84 -0
  47. package/lib/download/ui/figureDownloadOptions.d.ts.map +1 -0
  48. package/lib/download/ui/figureDownloadOptions.js +2 -0
  49. package/lib/download/ui/figureDownloadOptions.js.map +1 -0
  50. package/lib/download/ui/resolutionChoices.d.ts +27 -0
  51. package/lib/download/ui/resolutionChoices.d.ts.map +1 -0
  52. package/lib/download/ui/resolutionChoices.js +48 -0
  53. package/lib/download/ui/resolutionChoices.js.map +1 -0
  54. package/lib/download/ui/useFigureActions.d.ts +4 -1
  55. package/lib/download/ui/useFigureActions.d.ts.map +1 -1
  56. package/lib/download/ui/useFigureActions.js +17 -8
  57. package/lib/download/ui/useFigureActions.js.map +1 -1
  58. package/lib/download/ui/useFigureDownload.d.ts +2 -55
  59. package/lib/download/ui/useFigureDownload.d.ts.map +1 -1
  60. package/lib/download/ui/useFigureDownload.js +45 -13
  61. package/lib/download/ui/useFigureDownload.js.map +1 -1
  62. package/lib/ecosystem/core/sites.d.ts.map +1 -1
  63. package/lib/ecosystem/core/sites.js +14 -0
  64. package/lib/ecosystem/core/sites.js.map +1 -1
  65. package/lib/ecosystem/core/types.d.ts +1 -1
  66. package/lib/ecosystem/core/types.d.ts.map +1 -1
  67. package/lib/ecosystem/ui/glyphs.d.ts.map +1 -1
  68. package/lib/ecosystem/ui/glyphs.js +3 -0
  69. package/lib/ecosystem/ui/glyphs.js.map +1 -1
  70. package/lib/host/core/connectHost.js +1 -1
  71. package/lib/host/core/connectHost.js.map +1 -1
  72. package/lib/host/core/connectTool.d.ts +103 -0
  73. package/lib/host/core/connectTool.d.ts.map +1 -0
  74. package/lib/host/core/connectTool.js +169 -0
  75. package/lib/host/core/connectTool.js.map +1 -0
  76. package/lib/host/core/hostOutputs.d.ts +16 -3
  77. package/lib/host/core/hostOutputs.d.ts.map +1 -1
  78. package/lib/host/core/hostOutputs.js +38 -4
  79. package/lib/host/core/hostOutputs.js.map +1 -1
  80. package/lib/host/core/index.d.ts +8 -2
  81. package/lib/host/core/index.d.ts.map +1 -1
  82. package/lib/host/core/index.js +4 -1
  83. package/lib/host/core/index.js.map +1 -1
  84. package/lib/host/core/kinds.d.ts +31 -3
  85. package/lib/host/core/kinds.d.ts.map +1 -1
  86. package/lib/host/core/kinds.js +35 -4
  87. package/lib/host/core/kinds.js.map +1 -1
  88. package/lib/host/core/messageValues.d.ts +29 -0
  89. package/lib/host/core/messageValues.d.ts.map +1 -0
  90. package/lib/host/core/messageValues.js +57 -0
  91. package/lib/host/core/messageValues.js.map +1 -0
  92. package/lib/host/core/protocol.d.ts +2 -5
  93. package/lib/host/core/protocol.d.ts.map +1 -1
  94. package/lib/host/core/protocol.js +3 -37
  95. package/lib/host/core/protocol.js.map +1 -1
  96. package/lib/host/core/resultKinds.d.ts +74 -0
  97. package/lib/host/core/resultKinds.d.ts.map +1 -0
  98. package/lib/host/core/resultKinds.js +40 -0
  99. package/lib/host/core/resultKinds.js.map +1 -0
  100. package/lib/host/core/toolMessages.d.ts +24 -0
  101. package/lib/host/core/toolMessages.d.ts.map +1 -0
  102. package/lib/host/core/toolMessages.js +136 -0
  103. package/lib/host/core/toolMessages.js.map +1 -0
  104. package/lib/host/ui/index.d.ts +2 -0
  105. package/lib/host/ui/index.d.ts.map +1 -1
  106. package/lib/host/ui/index.js +1 -0
  107. package/lib/host/ui/index.js.map +1 -1
  108. package/lib/host/ui/useFramedTool.d.ts +74 -0
  109. package/lib/host/ui/useFramedTool.d.ts.map +1 -0
  110. package/lib/host/ui/useFramedTool.js +125 -0
  111. package/lib/host/ui/useFramedTool.js.map +1 -0
  112. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  113. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  114. package/lib/locales/de.json +30 -1
  115. package/lib/locales/en.json +30 -1
  116. package/lib/locales/es.json +30 -1
  117. package/lib/locales/fr.json +30 -1
  118. package/lib/locales/it.json +30 -1
  119. package/lib/molecule3d/ui/Molecule3DStage.d.ts +4 -33
  120. package/lib/molecule3d/ui/Molecule3DStage.d.ts.map +1 -1
  121. package/lib/molecule3d/ui/Molecule3DStage.js +3 -37
  122. package/lib/molecule3d/ui/Molecule3DStage.js.map +1 -1
  123. package/lib/molecule3d/ui/MoleculeCanvas3D.d.ts.map +1 -1
  124. package/lib/molecule3d/ui/MoleculeCanvas3D.js +10 -2
  125. package/lib/molecule3d/ui/MoleculeCanvas3D.js.map +1 -1
  126. package/lib/molecule3d/ui/exportMoleculeImage.d.ts +10 -0
  127. package/lib/molecule3d/ui/exportMoleculeImage.d.ts.map +1 -1
  128. package/lib/molecule3d/ui/exportMoleculeImage.js +17 -0
  129. package/lib/molecule3d/ui/exportMoleculeImage.js.map +1 -1
  130. package/lib/molecule3d/ui/index.d.ts +1 -1
  131. package/lib/molecule3d/ui/index.d.ts.map +1 -1
  132. package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts +23 -0
  133. package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts.map +1 -1
  134. package/lib/molecule3d/ui/useImageExport.d.ts +3 -0
  135. package/lib/molecule3d/ui/useImageExport.d.ts.map +1 -1
  136. package/lib/molecule3d/ui/useImageExport.js +21 -3
  137. package/lib/molecule3d/ui/useImageExport.js.map +1 -1
  138. package/lib/osiris/core/barGeometry.d.ts +42 -0
  139. package/lib/osiris/core/barGeometry.d.ts.map +1 -0
  140. package/lib/osiris/core/barGeometry.js +46 -0
  141. package/lib/osiris/core/barGeometry.js.map +1 -0
  142. package/lib/osiris/core/computeProperties.d.ts +42 -0
  143. package/lib/osiris/core/computeProperties.d.ts.map +1 -0
  144. package/lib/osiris/core/computeProperties.js +115 -0
  145. package/lib/osiris/core/computeProperties.js.map +1 -0
  146. package/lib/osiris/core/constants.d.ts +70 -0
  147. package/lib/osiris/core/constants.d.ts.map +1 -0
  148. package/lib/osiris/core/constants.js +99 -0
  149. package/lib/osiris/core/constants.js.map +1 -0
  150. package/lib/osiris/core/fitness.d.ts +32 -0
  151. package/lib/osiris/core/fitness.d.ts.map +1 -0
  152. package/lib/osiris/core/fitness.js +48 -0
  153. package/lib/osiris/core/fitness.js.map +1 -0
  154. package/lib/osiris/core/index.d.ts +29 -0
  155. package/lib/osiris/core/index.d.ts.map +1 -0
  156. package/lib/osiris/core/index.js +19 -0
  157. package/lib/osiris/core/index.js.map +1 -0
  158. package/lib/osiris/core/poolSize.d.ts +17 -0
  159. package/lib/osiris/core/poolSize.d.ts.map +1 -0
  160. package/lib/osiris/core/poolSize.js +22 -0
  161. package/lib/osiris/core/poolSize.js.map +1 -0
  162. package/lib/osiris/core/poolTypes.d.ts +140 -0
  163. package/lib/osiris/core/poolTypes.d.ts.map +1 -0
  164. package/lib/osiris/core/poolTypes.js +12 -0
  165. package/lib/osiris/core/poolTypes.js.map +1 -0
  166. package/lib/osiris/core/predictIdCode.d.ts +39 -0
  167. package/lib/osiris/core/predictIdCode.d.ts.map +1 -0
  168. package/lib/osiris/core/predictIdCode.js +54 -0
  169. package/lib/osiris/core/predictIdCode.js.map +1 -0
  170. package/lib/osiris/core/predictProtocol.d.ts +67 -0
  171. package/lib/osiris/core/predictProtocol.d.ts.map +1 -0
  172. package/lib/osiris/core/predictProtocol.js +29 -0
  173. package/lib/osiris/core/predictProtocol.js.map +1 -0
  174. package/lib/osiris/core/predictionPool.d.ts +23 -0
  175. package/lib/osiris/core/predictionPool.d.ts.map +1 -0
  176. package/lib/osiris/core/predictionPool.js +186 -0
  177. package/lib/osiris/core/predictionPool.js.map +1 -0
  178. package/lib/osiris/core/predictionQueue.d.ts +46 -0
  179. package/lib/osiris/core/predictionQueue.d.ts.map +1 -0
  180. package/lib/osiris/core/predictionQueue.js +57 -0
  181. package/lib/osiris/core/predictionQueue.js.map +1 -0
  182. package/lib/osiris/core/predictors.d.ts +62 -0
  183. package/lib/osiris/core/predictors.d.ts.map +1 -0
  184. package/lib/osiris/core/predictors.js +100 -0
  185. package/lib/osiris/core/predictors.js.map +1 -0
  186. package/lib/osiris/core/propertyKeys.d.ts +32 -0
  187. package/lib/osiris/core/propertyKeys.d.ts.map +1 -0
  188. package/lib/osiris/core/propertyKeys.js +44 -0
  189. package/lib/osiris/core/propertyKeys.js.map +1 -0
  190. package/lib/osiris/core/riskAppearance.d.ts +60 -0
  191. package/lib/osiris/core/riskAppearance.d.ts.map +1 -0
  192. package/lib/osiris/core/riskAppearance.js +59 -0
  193. package/lib/osiris/core/riskAppearance.js.map +1 -0
  194. package/lib/osiris/core/riskDetail.d.ts +22 -0
  195. package/lib/osiris/core/riskDetail.d.ts.map +1 -0
  196. package/lib/osiris/core/riskDetail.js +86 -0
  197. package/lib/osiris/core/riskDetail.js.map +1 -0
  198. package/lib/osiris/core/riskDetailRequest.d.ts +31 -0
  199. package/lib/osiris/core/riskDetailRequest.d.ts.map +1 -0
  200. package/lib/osiris/core/riskDetailRequest.js +49 -0
  201. package/lib/osiris/core/riskDetailRequest.js.map +1 -0
  202. package/lib/osiris/core/riskFindings.d.ts +26 -0
  203. package/lib/osiris/core/riskFindings.d.ts.map +1 -0
  204. package/lib/osiris/core/riskFindings.js +79 -0
  205. package/lib/osiris/core/riskFindings.js.map +1 -0
  206. package/lib/osiris/core/runPredictionJob.d.ts +20 -0
  207. package/lib/osiris/core/runPredictionJob.d.ts.map +1 -0
  208. package/lib/osiris/core/runPredictionJob.js +43 -0
  209. package/lib/osiris/core/runPredictionJob.js.map +1 -0
  210. package/lib/osiris/core/scales.d.ts +70 -0
  211. package/lib/osiris/core/scales.d.ts.map +1 -0
  212. package/lib/osiris/core/scales.js +185 -0
  213. package/lib/osiris/core/scales.js.map +1 -0
  214. package/lib/osiris/core/types.d.ts +91 -0
  215. package/lib/osiris/core/types.d.ts.map +1 -0
  216. package/lib/osiris/core/types.js +19 -0
  217. package/lib/osiris/core/types.js.map +1 -0
  218. package/lib/osiris/core/valuation.d.ts +28 -0
  219. package/lib/osiris/core/valuation.d.ts.map +1 -0
  220. package/lib/osiris/core/valuation.js +39 -0
  221. package/lib/osiris/core/valuation.js.map +1 -0
  222. package/lib/osiris/ui/PropertyBar.d.ts +27 -0
  223. package/lib/osiris/ui/PropertyBar.d.ts.map +1 -0
  224. package/lib/osiris/ui/PropertyBar.js +27 -0
  225. package/lib/osiris/ui/PropertyBar.js.map +1 -0
  226. package/lib/osiris/ui/PropertyPanel.d.ts +91 -0
  227. package/lib/osiris/ui/PropertyPanel.d.ts.map +1 -0
  228. package/lib/osiris/ui/PropertyPanel.js +77 -0
  229. package/lib/osiris/ui/PropertyPanel.js.map +1 -0
  230. package/lib/osiris/ui/PropertyRows.d.ts +40 -0
  231. package/lib/osiris/ui/PropertyRows.d.ts.map +1 -0
  232. package/lib/osiris/ui/PropertyRows.js +23 -0
  233. package/lib/osiris/ui/PropertyRows.js.map +1 -0
  234. package/lib/osiris/ui/RiskFindings.d.ts +43 -0
  235. package/lib/osiris/ui/RiskFindings.d.ts.map +1 -0
  236. package/lib/osiris/ui/RiskFindings.js +51 -0
  237. package/lib/osiris/ui/RiskFindings.js.map +1 -0
  238. package/lib/osiris/ui/RiskPanel.d.ts +46 -0
  239. package/lib/osiris/ui/RiskPanel.d.ts.map +1 -0
  240. package/lib/osiris/ui/RiskPanel.js +32 -0
  241. package/lib/osiris/ui/RiskPanel.js.map +1 -0
  242. package/lib/osiris/ui/RiskSquare.d.ts +51 -0
  243. package/lib/osiris/ui/RiskSquare.d.ts.map +1 -0
  244. package/lib/osiris/ui/RiskSquare.js +23 -0
  245. package/lib/osiris/ui/RiskSquare.js.map +1 -0
  246. package/lib/osiris/ui/index.d.ts +15 -0
  247. package/lib/osiris/ui/index.d.ts.map +1 -0
  248. package/lib/osiris/ui/index.js +8 -0
  249. package/lib/osiris/ui/index.js.map +1 -0
  250. package/lib/osiris/ui/usePredictions.d.ts +81 -0
  251. package/lib/osiris/ui/usePredictions.d.ts.map +1 -0
  252. package/lib/osiris/ui/usePredictions.js +102 -0
  253. package/lib/osiris/ui/usePredictions.js.map +1 -0
  254. package/lib/osiris-ui.d.ts +11 -0
  255. package/lib/osiris-ui.d.ts.map +1 -0
  256. package/lib/osiris-ui.js +11 -0
  257. package/lib/osiris-ui.js.map +1 -0
  258. package/lib/osiris.d.ts +17 -0
  259. package/lib/osiris.d.ts.map +1 -0
  260. package/lib/osiris.js +17 -0
  261. package/lib/osiris.js.map +1 -0
  262. package/lib/panel/ui/FilterInput.d.ts.map +1 -1
  263. package/lib/panel/ui/FilterInput.js +3 -1
  264. package/lib/panel/ui/FilterInput.js.map +1 -1
  265. package/lib/panel/ui/SidePanelItem.d.ts +39 -0
  266. package/lib/panel/ui/SidePanelItem.d.ts.map +1 -0
  267. package/lib/panel/ui/SidePanelItem.js +63 -0
  268. package/lib/panel/ui/SidePanelItem.js.map +1 -0
  269. package/lib/panel/ui/SidePanelStack.d.ts +11 -10
  270. package/lib/panel/ui/SidePanelStack.d.ts.map +1 -1
  271. package/lib/panel/ui/SidePanelStack.js +22 -15
  272. package/lib/panel/ui/SidePanelStack.js.map +1 -1
  273. package/lib/panel/ui/SpectrumColorSwatch.d.ts.map +1 -1
  274. package/lib/panel/ui/SpectrumColorSwatch.js +4 -2
  275. package/lib/panel/ui/SpectrumColorSwatch.js.map +1 -1
  276. package/lib/panel/ui/usePanelFolds.d.ts +35 -0
  277. package/lib/panel/ui/usePanelFolds.d.ts.map +1 -0
  278. package/lib/panel/ui/usePanelFolds.js +73 -0
  279. package/lib/panel/ui/usePanelFolds.js.map +1 -0
  280. package/lib/shared/ui/FullscreenStage.d.ts +43 -0
  281. package/lib/shared/ui/FullscreenStage.d.ts.map +1 -0
  282. package/lib/shared/ui/FullscreenStage.js +38 -0
  283. package/lib/shared/ui/FullscreenStage.js.map +1 -0
  284. package/lib/shared/ui/canFillScreen.d.ts +7 -0
  285. package/lib/shared/ui/canFillScreen.d.ts.map +1 -0
  286. package/lib/shared/ui/canFillScreen.js +9 -0
  287. package/lib/shared/ui/canFillScreen.js.map +1 -0
  288. package/lib/shared/ui/index.d.ts +3 -0
  289. package/lib/shared/ui/index.d.ts.map +1 -1
  290. package/lib/shared/ui/index.js +2 -0
  291. package/lib/shared/ui/index.js.map +1 -1
  292. package/lib/split/ui/splitPanes.d.ts +3 -3
  293. package/lib/split/ui/splitPanes.js +1 -1
  294. package/lib/structure/core/structureNotations.d.ts +8 -1
  295. package/lib/structure/core/structureNotations.d.ts.map +1 -1
  296. package/lib/structure/core/structureNotations.js +14 -8
  297. package/lib/structure/core/structureNotations.js.map +1 -1
  298. package/lib/structure/ui/StructureExportPanel.d.ts +8 -0
  299. package/lib/structure/ui/StructureExportPanel.d.ts.map +1 -1
  300. package/lib/structure/ui/StructureExportPanel.js +9 -4
  301. package/lib/structure/ui/StructureExportPanel.js.map +1 -1
  302. package/lib/structure/ui/index.d.ts +1 -0
  303. package/lib/structure/ui/index.d.ts.map +1 -1
  304. package/lib/structure/ui/index.js.map +1 -1
  305. package/package.json +4 -1
  306. package/src/card/core/cardAddress.ts +39 -3
  307. package/src/card/core/cardPageUrl.ts +10 -3
  308. package/src/card/core/index.ts +7 -1
  309. package/src/credits/core/credits.ts +40 -0
  310. package/src/download/core/downloadFigure.ts +26 -1
  311. package/src/download/core/figureDpi.ts +94 -0
  312. package/src/download/core/figurePng.ts +11 -2
  313. package/src/download/core/index.ts +13 -1
  314. package/src/download/core/pngDpi.ts +84 -0
  315. package/src/download/ui/FigureDownloadPanel.tsx +41 -51
  316. package/src/download/ui/figureDownloadHint.ts +13 -0
  317. package/src/download/ui/figureDownloadOptions.ts +85 -0
  318. package/src/download/ui/resolutionChoices.ts +67 -0
  319. package/src/download/ui/useFigureActions.ts +24 -9
  320. package/src/download/ui/useFigureDownload.tsx +57 -71
  321. package/src/ecosystem/core/sites.ts +14 -0
  322. package/src/ecosystem/core/types.ts +2 -1
  323. package/src/ecosystem/ui/glyphs.tsx +20 -0
  324. package/src/host/core/connectHost.ts +1 -1
  325. package/src/host/core/connectTool.ts +285 -0
  326. package/src/host/core/hostOutputs.ts +47 -5
  327. package/src/host/core/index.ts +20 -1
  328. package/src/host/core/kinds.ts +53 -8
  329. package/src/host/core/messageValues.ts +58 -0
  330. package/src/host/core/protocol.ts +5 -37
  331. package/src/host/core/resultKinds.ts +65 -0
  332. package/src/host/core/toolMessages.ts +160 -0
  333. package/src/host/ui/index.ts +6 -0
  334. package/src/host/ui/useFramedTool.ts +213 -0
  335. package/src/locales/de.json +30 -1
  336. package/src/locales/en.json +30 -1
  337. package/src/locales/es.json +30 -1
  338. package/src/locales/fr.json +30 -1
  339. package/src/locales/it.json +30 -1
  340. package/src/molecule3d/ui/Molecule3DStage.tsx +4 -88
  341. package/src/molecule3d/ui/MoleculeCanvas3D.tsx +10 -1
  342. package/src/molecule3d/ui/exportMoleculeImage.ts +22 -0
  343. package/src/molecule3d/ui/index.ts +4 -1
  344. package/src/molecule3d/ui/moleculeViewer3DProps.ts +24 -0
  345. package/src/molecule3d/ui/useImageExport.ts +28 -2
  346. package/src/osiris/core/barGeometry.ts +74 -0
  347. package/src/osiris/core/computeProperties.ts +175 -0
  348. package/src/osiris/core/constants.ts +110 -0
  349. package/src/osiris/core/fitness.ts +59 -0
  350. package/src/osiris/core/index.ts +78 -0
  351. package/src/osiris/core/poolSize.ts +24 -0
  352. package/src/osiris/core/poolTypes.ts +140 -0
  353. package/src/osiris/core/predictIdCode.ts +69 -0
  354. package/src/osiris/core/predictProtocol.ts +78 -0
  355. package/src/osiris/core/predictionPool.ts +237 -0
  356. package/src/osiris/core/predictionQueue.ts +89 -0
  357. package/src/osiris/core/predictors.ts +142 -0
  358. package/src/osiris/core/propertyKeys.ts +54 -0
  359. package/src/osiris/core/riskAppearance.ts +86 -0
  360. package/src/osiris/core/riskDetail.ts +120 -0
  361. package/src/osiris/core/riskDetailRequest.ts +64 -0
  362. package/src/osiris/core/riskFindings.ts +92 -0
  363. package/src/osiris/core/runPredictionJob.ts +49 -0
  364. package/src/osiris/core/scales.ts +236 -0
  365. package/src/osiris/core/types.ts +103 -0
  366. package/src/osiris/core/valuation.ts +44 -0
  367. package/src/osiris/ui/PropertyBar.tsx +77 -0
  368. package/src/osiris/ui/PropertyPanel.tsx +227 -0
  369. package/src/osiris/ui/PropertyRows.tsx +92 -0
  370. package/src/osiris/ui/RiskFindings.tsx +137 -0
  371. package/src/osiris/ui/RiskPanel.tsx +81 -0
  372. package/src/osiris/ui/RiskSquare.tsx +108 -0
  373. package/src/osiris/ui/index.ts +17 -0
  374. package/src/osiris/ui/usePredictions.ts +194 -0
  375. package/src/osiris-ui.ts +11 -0
  376. package/src/osiris.ts +17 -0
  377. package/src/panel/ui/FilterInput.tsx +4 -1
  378. package/src/panel/ui/SidePanelItem.tsx +162 -0
  379. package/src/panel/ui/SidePanelStack.tsx +29 -36
  380. package/src/panel/ui/SpectrumColorSwatch.tsx +5 -3
  381. package/src/panel/ui/usePanelFolds.ts +103 -0
  382. package/src/shared/ui/FullscreenStage.tsx +96 -0
  383. package/src/shared/ui/canFillScreen.ts +8 -0
  384. package/src/shared/ui/index.ts +6 -0
  385. package/src/split/ui/splitPanes.tsx +4 -4
  386. package/src/structure/core/structureNotations.ts +25 -8
  387. package/src/structure/ui/StructureExportPanel.tsx +23 -4
  388. package/src/structure/ui/index.ts +4 -0
  389. package/styles/osiris.css +339 -0
@@ -0,0 +1,96 @@
1
+ /**
2
+ * A box that can fill the screen: the 3D canvas and its toolbars, a side panel.
3
+ *
4
+ * A box filling the screen hides everything outside it, and the popovers and
5
+ * tooltips of what it holds are portalled to `document.body`: while the box
6
+ * fills the screen they are portalled into it instead, the way react-science's
7
+ * `RootLayout` keeps its own menus visible. Otherwise the portal options of the
8
+ * page around the box are passed through untouched.
9
+ */
10
+
11
+ import { PortalContext, PortalProvider } from '@blueprintjs/core';
12
+ import type { CSSProperties, ReactElement, ReactNode } from 'react';
13
+ import { useCallback, useContext, useState } from 'react';
14
+ import { FullScreenProvider, useFullscreen } from 'react-science/ui';
15
+
16
+ import { canFillScreen } from './canFillScreen.ts';
17
+
18
+ /** Whether a box fills the screen, and how to change that. */
19
+ export interface StageFullscreen {
20
+ /** Whether the box fills the screen. */
21
+ active: boolean;
22
+ /** Fill the screen, or leave it. */
23
+ toggle: () => void;
24
+ }
25
+
26
+ /** Props of {@link FullscreenStage}. */
27
+ export interface FullscreenStageProps {
28
+ /**
29
+ * Style of the box, or a function handed whether the box fills the screen,
30
+ * for a box shaped differently while it does.
31
+ */
32
+ style: CSSProperties | ((fillsScreen: boolean) => CSSProperties);
33
+ /**
34
+ * Called with the box once it is mounted, and with `null` once it is gone.
35
+ * It must keep its identity across renders.
36
+ * @default undefined
37
+ */
38
+ onStage?: (element: HTMLDivElement | null) => void;
39
+ /**
40
+ * What is drawn in the box, handed whether it fills the screen and the
41
+ * toggle, or `undefined` where the browser cannot fill the screen.
42
+ */
43
+ children: (fullscreen: StageFullscreen | undefined) => ReactNode;
44
+ }
45
+
46
+ /**
47
+ * The box, able to fill the screen.
48
+ * @param props - See {@link FullscreenStageProps}.
49
+ * @returns The box.
50
+ */
51
+ export function FullscreenStage(props: FullscreenStageProps): ReactElement {
52
+ return (
53
+ <FullScreenProvider>
54
+ {(fullscreenRef) => <Stage {...props} fullscreenRef={fullscreenRef} />}
55
+ </FullScreenProvider>
56
+ );
57
+ }
58
+
59
+ interface StageProps extends FullscreenStageProps {
60
+ /** Where `FullScreenProvider` expects the element that fills the screen. */
61
+ fullscreenRef: { current: HTMLDivElement | null };
62
+ }
63
+
64
+ function Stage(props: StageProps): ReactElement {
65
+ const { style, onStage, children, fullscreenRef } = props;
66
+ const { isFullScreen, toggle } = useFullscreen();
67
+ const portal = useContext(PortalContext);
68
+ const [canFill] = useState(canFillScreen);
69
+ const [stage, setStage] = useState<HTMLDivElement | null>(null);
70
+ const stageRef = useCallback(
71
+ (element: HTMLDivElement | null) => {
72
+ fullscreenRef.current = element;
73
+ setStage(element);
74
+ onStage?.(element);
75
+ },
76
+ [fullscreenRef, onStage],
77
+ );
78
+
79
+ // The provider is always there, so entering full screen changes a value
80
+ // rather than the tree, and what the box holds is never mounted again.
81
+ return (
82
+ <div
83
+ ref={stageRef}
84
+ style={typeof style === 'function' ? style(isFullScreen) : style}
85
+ >
86
+ <PortalProvider
87
+ portalClassName={portal.portalClassName}
88
+ portalContainer={
89
+ isFullScreen && stage !== null ? stage : portal.portalContainer
90
+ }
91
+ >
92
+ {children(canFill ? { active: isFullScreen, toggle } : undefined)}
93
+ </PortalProvider>
94
+ </div>
95
+ );
96
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Whether this browser lets a page fill the screen: neither an iPhone nor a
3
+ * frame without `allowfullscreen` does.
4
+ * @returns Whether `requestFullscreen` can succeed.
5
+ */
6
+ export function canFillScreen(): boolean {
7
+ return typeof document !== 'undefined' && document.fullscreenEnabled;
8
+ }
@@ -7,3 +7,9 @@ export type {
7
7
  ActionTooltipTarget,
8
8
  } from './useActionTooltip.ts';
9
9
  export { ACTION_TOOLTIP_DELAY, useActionTooltip } from './useActionTooltip.ts';
10
+ export { canFillScreen } from './canFillScreen.ts';
11
+ export type {
12
+ FullscreenStageProps,
13
+ StageFullscreen,
14
+ } from './FullscreenStage.tsx';
15
+ export { FullscreenStage } from './FullscreenStage.tsx';
@@ -65,9 +65,9 @@ export interface SplitPanesProps extends SplitRange {
65
65
  */
66
66
  stackBelow?: number;
67
67
  /**
68
- * The gutter each pane keeps beside the splitter, in pixels, so neither
69
- * figure is read against its edge.
70
- * @default 6
68
+ * The gutter each pane keeps beside the splitter, in pixels. The bar is
69
+ * already the separation, so a gutter only widens it into a band of page.
70
+ * @default 0
71
71
  */
72
72
  gutter?: number;
73
73
  /**
@@ -234,7 +234,7 @@ const STACK_ACROSS = 860;
234
234
  const STACK_DOWN = 420;
235
235
 
236
236
  /** The gutter a pane keeps beside the splitter, in pixels. */
237
- const GUTTER = 6;
237
+ const GUTTER = 0;
238
238
 
239
239
  /** The gap between the panes once they have stacked, in pixels. */
240
240
  const STACKED_GAP = 16;
@@ -56,6 +56,13 @@ export interface StructureNotation {
56
56
  block: boolean;
57
57
  }
58
58
 
59
+ /**
60
+ * Notations the caller has already written, shown instead of the ones
61
+ * OpenChemLib would write. A drawing program's molfile keeps its
62
+ * abbreviations as superatoms, which a round trip through OpenChemLib drops.
63
+ */
64
+ export type SuppliedNotations = Partial<Record<StructureNotationKind, string>>;
65
+
59
66
  /** What a molfile is, for the application that opens one. */
60
67
  const MOLFILE_TYPE = 'chemical/x-mdl-molfile';
61
68
 
@@ -66,35 +73,45 @@ const MOLFILE_TYPE = 'chemical/x-mdl-molfile';
66
73
  * tautomer cannot always be canonized — comes back empty rather than taking
67
74
  * the rest of the list down with it.
68
75
  * @param molecule - The structure, as the editor handed it over. Not modified.
76
+ * @param supplied - Notations the caller wrote itself, used as they are.
69
77
  * @returns One entry per notation, in the order they are shown.
70
78
  */
71
- export function structureNotations(molecule: Molecule): StructureNotation[] {
72
- const idCode = written(() => molecule.getIDCode());
79
+ export function structureNotations(
80
+ molecule: Molecule,
81
+ supplied: SuppliedNotations = {},
82
+ ): StructureNotation[] {
83
+ const value = (kind: StructureNotationKind, write: () => string) =>
84
+ supplied[kind] ?? written(write);
73
85
  return [
74
86
  {
75
87
  kind: 'smiles',
76
- value: written(() => molecule.toIsomericSmiles()),
88
+ value: value('smiles', () => molecule.toIsomericSmiles()),
77
89
  canonical: false,
78
90
  block: false,
79
91
  },
80
92
  {
81
93
  kind: 'molfileV3000',
82
- value: written(() => molecule.toMolfileV3()),
94
+ value: value('molfileV3000', () => molecule.toMolfileV3()),
83
95
  canonical: false,
84
96
  file: { suffix: '-v3000', extension: 'mol', mimeType: MOLFILE_TYPE },
85
97
  block: true,
86
98
  },
87
99
  {
88
100
  kind: 'molfileV2000',
89
- value: written(() => molecule.toMolfile()),
101
+ value: value('molfileV2000', () => molecule.toMolfile()),
90
102
  canonical: false,
91
103
  file: { suffix: '-v2000', extension: 'mol', mimeType: MOLFILE_TYPE },
92
104
  block: true,
93
105
  },
94
- { kind: 'idCode', value: idCode, canonical: true, block: false },
106
+ {
107
+ kind: 'idCode',
108
+ value: value('idCode', () => molecule.getIDCode()),
109
+ canonical: true,
110
+ block: false,
111
+ },
95
112
  {
96
113
  kind: 'noStereoIdCode',
97
- value: written(() =>
114
+ value: value('noStereoIdCode', () =>
98
115
  CanonizerUtil.getIDCode(molecule, CanonizerUtil.NOSTEREO),
99
116
  ),
100
117
  canonical: true,
@@ -102,7 +119,7 @@ export function structureNotations(molecule: Molecule): StructureNotation[] {
102
119
  },
103
120
  {
104
121
  kind: 'noStereoTautomerIdCode',
105
- value: written(() =>
122
+ value: value('noStereoTautomerIdCode', () =>
106
123
  CanonizerUtil.getIDCode(molecule, CanonizerUtil.NOSTEREO_TAUTOMER),
107
124
  ),
108
125
  canonical: true,
@@ -15,6 +15,7 @@ import { useChromeT } from '../../i18n/ui/useT.ts';
15
15
  import { TOKEN } from '../../tokens/core/familyTokens.ts';
16
16
  import { sourceMolecule } from '../core/sourceMolecule.ts';
17
17
  import { structureError } from '../core/structureError.ts';
18
+ import type { SuppliedNotations } from '../core/structureNotations.ts';
18
19
  import { structureNotations } from '../core/structureNotations.ts';
19
20
  import type { StructureSourceInput } from '../core/structureSource.ts';
20
21
  import { structureSource } from '../core/structureSource.ts';
@@ -36,6 +37,13 @@ export interface StructureExportPanelProps extends StructureSourceInput {
36
37
  * @default false
37
38
  */
38
39
  fragment?: boolean;
40
+ /**
41
+ * Notations the caller wrote itself, shown and saved as they are instead of
42
+ * the ones OpenChemLib would write from the structure — a drawing program
43
+ * whose molfile keeps superatoms that a round trip would drop.
44
+ * @default {}
45
+ */
46
+ notations?: SuppliedNotations;
39
47
  }
40
48
 
41
49
  /**
@@ -53,12 +61,17 @@ export function StructureExportPanel(
53
61
  props: StructureExportPanelProps,
54
62
  ): ReactElement {
55
63
  const { idCode, coordinates, molfile, smiles } = props;
56
- const { name = 'structure', fragment = false } = props;
64
+ const { name = 'structure', fragment = false, notations: supplied } = props;
57
65
  const t = useChromeT();
58
66
 
59
67
  const read = useMemo(
60
- () => readStructure({ idCode, coordinates, molfile, smiles }, fragment),
61
- [idCode, coordinates, molfile, smiles, fragment],
68
+ () =>
69
+ readStructure(
70
+ { idCode, coordinates, molfile, smiles },
71
+ fragment,
72
+ supplied,
73
+ ),
74
+ [idCode, coordinates, molfile, smiles, fragment, supplied],
62
75
  );
63
76
 
64
77
  if (read.kind !== 'read') {
@@ -120,11 +133,13 @@ type ReadStructure =
120
133
  * Read the notation the caller handed over, and write every other one from it.
121
134
  * @param input - Whatever notations the caller has.
122
135
  * @param fragment - Whether the structure is a query fragment.
136
+ * @param supplied - Notations the caller wrote itself.
123
137
  * @returns The molecule and its notations, or why there are none.
124
138
  */
125
139
  function readStructure(
126
140
  input: StructureSourceInput,
127
141
  fragment: boolean,
142
+ supplied: SuppliedNotations | undefined,
128
143
  ): ReadStructure {
129
144
  const source = structureSource(input);
130
145
  if (source.kind === 'empty') return { kind: 'empty' };
@@ -135,7 +150,11 @@ function readStructure(
135
150
  // structure from the one that was drawn.
136
151
  if (fragment) molecule.setFragment(true);
137
152
  if (molecule.getAllAtoms() === 0) return { kind: 'empty' };
138
- return { kind: 'read', molecule, notations: structureNotations(molecule) };
153
+ return {
154
+ kind: 'read',
155
+ molecule,
156
+ notations: structureNotations(molecule, supplied),
157
+ };
139
158
  } catch (error) {
140
159
  return { kind: 'error', message: structureError(error).message };
141
160
  }
@@ -36,6 +36,10 @@ export { StructureExportButton } from './StructureExportButton.tsx';
36
36
  export type { CardStructureProps } from './CardStructure.tsx';
37
37
  export { CardStructure } from './CardStructure.tsx';
38
38
  export type { StructureExportPanelProps } from './StructureExportPanel.tsx';
39
+ export type {
40
+ StructureNotationKind,
41
+ SuppliedNotations,
42
+ } from '../core/structureNotations.ts';
39
43
  export type { ToolbarFloorOptions } from './useToolbarFloor.ts';
40
44
  export { useToolbarFloor } from './useToolbarFloor.ts';
41
45
  export type { StructureDraft } from './useStructureDraft.ts';
@@ -0,0 +1,339 @@
1
+ /*
2
+ * The OSIRIS property panel of `react-cheminfo/osiris-ui`: the four risk
3
+ * squares, the ten bars, and the explanation a square opens. Imported once by
4
+ * the page that draws the panel, after `chrome.css`, whose tokens it reads.
5
+ *
6
+ * Every colour is a token. The neutrals and the geometry are the family's, the
7
+ * accent is the site's own, and the three status colours below are the shared
8
+ * semantic ones — the same values on every site, never retuned. They are
9
+ * declared here because `chrome.css` does not declare them; a page that loads
10
+ * both reads the same three values either way.
11
+ */
12
+
13
+ :root {
14
+ --danger: #dc2626;
15
+ --success: #16a34a;
16
+ --warning: #d97706;
17
+ }
18
+
19
+ /* ── The panel ──────────────────────────────────────────────────────────── */
20
+
21
+ .property-panel {
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: 12px;
25
+ }
26
+
27
+ .property-panel__head {
28
+ display: flex;
29
+ align-items: baseline;
30
+ flex-wrap: wrap;
31
+ gap: 4px 10px;
32
+ font-size: 1.0625rem;
33
+ font-weight: 600;
34
+ }
35
+
36
+ /* A name from an SD field, or the molecule's own SMILES when it carried none:
37
+ either can be long, and neither is worth pushing the numbers off the card. */
38
+ .property-panel__label {
39
+ overflow: hidden;
40
+ max-width: 100%;
41
+ color: var(--text-muted);
42
+ font-size: 0.8125rem;
43
+ font-weight: 400;
44
+ text-overflow: ellipsis;
45
+ white-space: nowrap;
46
+ }
47
+
48
+ .osiris-note {
49
+ margin: 0;
50
+ color: var(--text-muted);
51
+ font-size: 0.8125rem;
52
+ }
53
+
54
+ /* The spinner while an explanation is fetched, on the line it explains. */
55
+ .osiris-note--working {
56
+ display: flex;
57
+ align-items: center;
58
+ gap: 6px;
59
+ }
60
+
61
+ .risk-panel,
62
+ .property-section {
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: 8px;
66
+ }
67
+
68
+ .risk-panel h5,
69
+ .property-section h5 {
70
+ margin: 0;
71
+ }
72
+
73
+ /* ── The four risks ─────────────────────────────────────────────────────── */
74
+
75
+ /* Two columns at the least: in a side panel too narrow for two 11rem squares,
76
+ the names wrap rather than stacking the four risks one under another. */
77
+ .risk-grid {
78
+ display: grid;
79
+ gap: 6px;
80
+ grid-template-columns: repeat(
81
+ auto-fit,
82
+ minmax(min(11rem, calc(50% - 3px)), 1fr)
83
+ );
84
+ }
85
+
86
+ .risk-square {
87
+ display: flex;
88
+ align-items: center;
89
+ padding: 6px 8px;
90
+ border: 1px solid var(--border);
91
+ border-radius: var(--radius);
92
+ margin: 0;
93
+ background: var(--surface);
94
+ color: inherit;
95
+ font: inherit;
96
+ gap: 8px;
97
+ text-align: left;
98
+ }
99
+
100
+ button.risk-square {
101
+ cursor: pointer;
102
+ }
103
+
104
+ button.risk-square:hover {
105
+ border-color: var(--border-strong);
106
+ background: var(--surface-sunken);
107
+ }
108
+
109
+ button.risk-square[aria-pressed='true'] {
110
+ border-color: var(--accent);
111
+ background: color-mix(in oklab, var(--accent) 10%, white);
112
+ }
113
+
114
+ /* A cell of the comparison table: the square alone, centred in its column. */
115
+ .risk-square--compact {
116
+ justify-content: center;
117
+ padding: 2px;
118
+ border: 0;
119
+ background: none;
120
+ }
121
+
122
+ .risk-square__swatch {
123
+ width: 14px;
124
+ height: 14px;
125
+ flex: none;
126
+ border-radius: 3px;
127
+ background: var(--text-faint);
128
+ }
129
+
130
+ /* The three levels are the three the drug score multiplies by — ×1, ×0.8, ×0.6
131
+ — so the colour says what the score already counted. `unknown` is the
132
+ library's own "the tables did not load", which is never green. */
133
+ .risk-square__swatch[data-level='none'] {
134
+ background: var(--success);
135
+ }
136
+
137
+ .risk-square__swatch[data-level='low'] {
138
+ background: var(--warning);
139
+ }
140
+
141
+ .risk-square__swatch[data-level='high'] {
142
+ background: var(--danger);
143
+ }
144
+
145
+ .risk-square__swatch[data-level='unknown'] {
146
+ background: var(--text-faint);
147
+ }
148
+
149
+ .risk-square__swatch[data-level='pending'] {
150
+ background: repeating-linear-gradient(
151
+ 45deg,
152
+ var(--border),
153
+ var(--border) 3px,
154
+ var(--surface) 3px,
155
+ var(--surface) 6px
156
+ );
157
+ }
158
+
159
+ .risk-square__text {
160
+ display: flex;
161
+ min-width: 0;
162
+ flex-direction: column;
163
+ }
164
+
165
+ .risk-square__name {
166
+ font-size: 0.8125rem;
167
+ font-weight: 600;
168
+ }
169
+
170
+ .risk-square__level {
171
+ color: var(--text-muted);
172
+ font-size: 0.75rem;
173
+ }
174
+
175
+ /* ── Why a risk came back as it did ─────────────────────────────────────── */
176
+
177
+ .risk-findings {
178
+ display: flex;
179
+ flex-direction: column;
180
+ padding: 8px 10px;
181
+ border: 1px solid var(--border);
182
+ border-radius: var(--radius);
183
+ background: var(--surface-sunken);
184
+ gap: 10px;
185
+ }
186
+
187
+ .risk-finding__heading {
188
+ margin: 0;
189
+ font-size: 0.8125rem;
190
+ font-weight: 600;
191
+ }
192
+
193
+ .risk-finding__drawings {
194
+ display: flex;
195
+ flex-wrap: wrap;
196
+ gap: 10px;
197
+ }
198
+
199
+ .risk-finding__figure {
200
+ margin: 0;
201
+ }
202
+
203
+ .risk-finding__figure > figcaption {
204
+ color: var(--text-muted);
205
+ font-size: 0.75rem;
206
+ }
207
+
208
+ /* ── The ten numbers ────────────────────────────────────────────────────
209
+
210
+ A name, a bar and a value on one line each. The bar's colour is the only
211
+ thing here that is not a neutral, and it is mixed from the three status
212
+ tokens — there is no hex code in this part and none in the component that
213
+ sets the fill's length. */
214
+
215
+ .property-rows {
216
+ display: flex;
217
+ flex-direction: column;
218
+ gap: 10px;
219
+ }
220
+
221
+ .property-row {
222
+ display: grid;
223
+ align-items: center;
224
+ gap: 0 10px;
225
+ grid-template-columns: minmax(6rem, 8.5rem) minmax(4rem, 1fr) minmax(
226
+ 3.5rem,
227
+ auto
228
+ );
229
+ }
230
+
231
+ .property-row__label {
232
+ font-size: 0.8125rem;
233
+ }
234
+
235
+ .property-row__unit {
236
+ color: var(--text-faint);
237
+ font-size: 0.6875rem;
238
+ }
239
+
240
+ .property-row__unit::before {
241
+ content: ' ';
242
+ }
243
+
244
+ .property-row__value {
245
+ font-size: 0.8125rem;
246
+ font-variant-numeric: tabular-nums;
247
+ text-align: right;
248
+ }
249
+
250
+ /* The bar carries its threshold label under it, so the row keeps room for one
251
+ whether or not that property has a published rule of thumb. */
252
+ .property-bar {
253
+ position: relative;
254
+ padding-bottom: 0.875rem;
255
+ }
256
+
257
+ .property-bar__track {
258
+ position: relative;
259
+ height: 8px;
260
+ border-radius: 999px;
261
+ background: var(--surface-sunken);
262
+ box-shadow: inset 0 0 0 1px var(--border);
263
+ }
264
+
265
+ .property-bar__fill {
266
+ position: absolute;
267
+ top: 0;
268
+ bottom: 0;
269
+ min-width: 2px;
270
+ border-radius: inherit;
271
+
272
+ /* The green-to-red ramp, mixed from the three shared status colours rather
273
+ than computed in JavaScript, which would put a hex code in a component.
274
+ `color-mix` clamps a percentage into 0–100%, so the first mix is pure amber
275
+ from the middle of the scale up and the second is pure amber down to it:
276
+ red → amber → green, with no muddy midpoint. */
277
+ --ramp-low: color-mix(
278
+ in oklab,
279
+ var(--warning) calc(var(--fitness, 1) * 200%),
280
+ var(--danger)
281
+ );
282
+
283
+ background: color-mix(
284
+ in oklab,
285
+ var(--success) calc((var(--fitness, 1) - 0.5) * 200%),
286
+ var(--ramp-low)
287
+ );
288
+ }
289
+
290
+ /* Where a diverging bar grows from. A fill that starts a quarter of the way
291
+ along says nothing without it. */
292
+ .property-bar__origin {
293
+ position: absolute;
294
+ top: -1px;
295
+ bottom: -1px;
296
+ width: 1px;
297
+ background: var(--border-strong);
298
+ }
299
+
300
+ /* The published rule of thumb: cLogP ≤ 5, logS > −4, molweight < 450,
301
+ drug-likeness > 0. */
302
+ .property-bar__mark {
303
+ position: absolute;
304
+ top: -3px;
305
+ bottom: -3px;
306
+ width: 2px;
307
+ border-radius: 1px;
308
+ background: var(--text-faint);
309
+ }
310
+
311
+ .property-bar__threshold {
312
+ position: absolute;
313
+ bottom: 0;
314
+ color: var(--text-faint);
315
+ font-size: 0.6875rem;
316
+ line-height: 1;
317
+ transform: translateX(-50%);
318
+ white-space: nowrap;
319
+ }
320
+
321
+ /* A narrow card has no width to spend on a bar: the name and the number are
322
+ what a phone reads, and the bar takes the line under them. */
323
+ @media (max-width: 480px) {
324
+ .property-row {
325
+ grid-template-columns: minmax(0, 1fr) minmax(3.5rem, auto);
326
+ }
327
+
328
+ .property-row__bar {
329
+ grid-column: 1 / -1;
330
+ grid-row: 2;
331
+ }
332
+ }
333
+
334
+ /* The panel is worth printing beside the structure. */
335
+ @media print {
336
+ .risk-findings {
337
+ break-inside: avoid;
338
+ }
339
+ }