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
@@ -2,6 +2,8 @@ import type { ChromeKey } from '../../i18n/core/chromeCatalog.ts';
2
2
  import type { Translate } from '../../i18n/ui/useT.ts';
3
3
  import type { FigureNotice } from '../core/copyFigure.ts';
4
4
  import type { FigureFormat } from '../core/downloadFigure.ts';
5
+ import type { FigureResolutionUnit } from '../core/figureDpi.ts';
6
+ import { formatFigureCentimetres } from '../core/figureDpi.ts';
5
7
  import type { FigurePixels } from '../core/figureScale.ts';
6
8
  import { figurePixels, formatFigurePixels } from '../core/figureScale.ts';
7
9
 
@@ -19,6 +21,10 @@ export interface HintState {
19
21
  notice: FigureNotice | null;
20
22
  /** Whether the SVG embeds a rendered picture. */
21
23
  rasterSvg: boolean;
24
+ /** How the resolution is offered; in dpi, the printed size is written out. */
25
+ unit: FigureResolutionUnit;
26
+ /** The language of the page, which the printed size is written in. */
27
+ language: string;
22
28
  }
23
29
 
24
30
  /**
@@ -31,6 +37,7 @@ export interface HintState {
31
37
  */
32
38
  export function hintOf(state: HintState, t: Translate<ChromeKey>): string {
33
39
  const { format, size, scale, failure, notice, rasterSvg } = state;
40
+ const { unit, language } = state;
34
41
  if (failure !== null) return failure;
35
42
  if (size === null) return t('download.noFigure');
36
43
  if (notice === 'copyUnsupported') return t('download.copyUnsupported');
@@ -45,6 +52,12 @@ export function hintOf(state: HintState, t: Translate<ChromeKey>): string {
45
52
  });
46
53
  }
47
54
  const pixels = formatFigurePixels(figurePixels(size, scale));
55
+ if (unit === 'dpi') {
56
+ const printed = formatFigureCentimetres(size, language);
57
+ return format === 'svg'
58
+ ? t('download.hintSvgDpi', printed)
59
+ : t('download.hintPngDpi', { pixels, ...printed });
60
+ }
48
61
  return format === 'svg'
49
62
  ? t('download.hintSvg', { pixels })
50
63
  : t('download.hintPng', { pixels });
@@ -0,0 +1,85 @@
1
+ import type { FigureFormat } from '../core/downloadFigure.ts';
2
+ import type { FigureResolutionUnit } from '../core/figureDpi.ts';
3
+ import type { FigureSvg } from '../core/figureSvg.ts';
4
+
5
+ import type { FigureRenderer } from './useFigureRedraw.tsx';
6
+
7
+ /** What the "Save figure" panel is set up with. */
8
+ export interface FigureDownloadOptions {
9
+ /**
10
+ * The `id` of the box the figure is mounted in. Everything drawn inside it
11
+ * is saved — sixteen charts of a pair grid as readily as one scatter plot —
12
+ * and the controls floating over it are left behind. Give this or
13
+ * `writeFigure`.
14
+ * @default undefined
15
+ */
16
+ targetId?: string;
17
+ /**
18
+ * Writes the figure as an SVG document, in place of reading it off the
19
+ * page: for a drawing whose file carries more than its picture, such as the
20
+ * chemistry behind a structure. It is called when the panel opens, to
21
+ * measure the figure, and again for every save and copy. The SVG is saved as
22
+ * written, at the size it states; the resolution paints the PNG alone.
23
+ * @default undefined
24
+ */
25
+ writeFigure?: () => Promise<FigureSvg>;
26
+ /**
27
+ * What the saved file is called, without its extension. Name it after the
28
+ * data rather than after the tool: a reader with four of these in a
29
+ * downloads folder cannot tell four `figure.png` apart.
30
+ * @default 'figure'
31
+ */
32
+ fileName?: string;
33
+ /**
34
+ * The format it opens on.
35
+ * @default 'png'
36
+ */
37
+ defaultFormat?: FigureFormat;
38
+ /**
39
+ * How the resolution is offered: as multiples of the figure on screen, or —
40
+ * for a figure drawn to the size it prints at — in dots per inch. In dots
41
+ * per inch an SVG keeps the size it states, and 1× is 96 dpi.
42
+ * @default 'multiple'
43
+ */
44
+ unit?: FigureResolutionUnit;
45
+ /**
46
+ * The resolution a PNG opens on, as a multiple of the figure on screen:
47
+ * `dpiScale(600)` opens on 600 dpi. An SVG opens at 1×, the size it has on
48
+ * screen, and each format keeps the multiple the reader last picked for it.
49
+ * @default 2, or 300 dpi
50
+ */
51
+ defaultScale?: number;
52
+ /**
53
+ * The resolutions offered, as multiples of the figure on screen.
54
+ * @default [1, 2, 3, 4], or 150, 300, 600 and 1200 dpi
55
+ */
56
+ scales?: readonly number[];
57
+ /**
58
+ * Called with the multiple a PNG is set to, for a page that keeps the
59
+ * reader's choice — to paint its own PNGs at it, or to open on it next time.
60
+ * @default undefined
61
+ */
62
+ onScaleChange?: (scale: number) => void;
63
+ /**
64
+ * What is painted under the figure. `transparent` leaves it unpainted, for a
65
+ * figure going onto a coloured slide. A written figure paints its own.
66
+ * @default the surface the figure is drawn on
67
+ */
68
+ background?: string;
69
+ /**
70
+ * What the panel is called.
71
+ * @default the chrome's own line, in the language of the page
72
+ */
73
+ title?: string;
74
+ /**
75
+ * Draws the figure at a size, for a file. When it is given the panel offers
76
+ * a size — as shown, 4:3, 16:9, a journal column, or typed — and a figure
77
+ * saved at a size other than its own is drawn again at that size, off the
78
+ * page, so its axes and labels are laid out for the new shape rather than
79
+ * stretched into it. Draw exactly what is on screen, with the same data,
80
+ * zoom and colours; only the box changes. A written figure has the size it
81
+ * states, and is offered none.
82
+ * @default undefined — the figure is saved at the size it has on screen
83
+ */
84
+ renderFigure?: FigureRenderer;
85
+ }
@@ -0,0 +1,67 @@
1
+ import type { HelpContent } from '../../help/ui/HelpBody.tsx';
2
+ import type { ChromeKey } from '../../i18n/core/chromeCatalog.ts';
3
+ import type { Translate } from '../../i18n/ui/useT.ts';
4
+ import type { OverlayOption } from '../../overlay/ui/OverlayRow.tsx';
5
+ import type { FigureResolutionUnit } from '../core/figureDpi.ts';
6
+ import { figureResolutionLabel } from '../core/figureDpi.ts';
7
+ import type { FigurePixels } from '../core/figureScale.ts';
8
+ import {
9
+ figurePixels,
10
+ figureScaleFits,
11
+ formatFigurePixels,
12
+ } from '../core/figureScale.ts';
13
+
14
+ /**
15
+ * The resolutions offered, each saying what it would actually produce.
16
+ *
17
+ * One too large for the browser to paint is greyed rather than dropped, so the
18
+ * reader learns the ceiling exists before they meet it as a blank file. An SVG
19
+ * is not painted, so it has no such ceiling.
20
+ * @param scales - The multiples the caller offers.
21
+ * @param size - How big the figure is drawn for the file.
22
+ * @param painted - Whether the file is painted into pixels.
23
+ * @param unit - How the resolution reads.
24
+ * @returns The choices, in the order offered.
25
+ */
26
+ export function scaleChoices(
27
+ scales: readonly number[],
28
+ size: FigurePixels | null,
29
+ painted: boolean,
30
+ unit: FigureResolutionUnit,
31
+ ): readonly OverlayOption[] {
32
+ const choices: OverlayOption[] = [];
33
+ for (const scale of scales) {
34
+ const pixels = size === null ? null : figurePixels(size, scale);
35
+ choices.push({
36
+ value: String(scale),
37
+ label: figureResolutionLabel(scale, unit),
38
+ title: pixels === null ? undefined : formatFigurePixels(pixels),
39
+ disabled: painted && size !== null && !figureScaleFits(size, scale),
40
+ });
41
+ }
42
+ return choices;
43
+ }
44
+
45
+ /**
46
+ * What the resolution means, in the unit it is offered in.
47
+ * @param unit - How the resolution reads.
48
+ * @param t - The chrome's formatter.
49
+ * @returns The help of the row.
50
+ */
51
+ export function resolutionHelp(
52
+ unit: FigureResolutionUnit,
53
+ t: Translate<ChromeKey>,
54
+ ): HelpContent {
55
+ const title = t('download.resolution');
56
+ return unit === 'dpi'
57
+ ? {
58
+ title,
59
+ body: t('download.resolutionDpiHelp'),
60
+ example: { code: '300 dpi', note: t('download.resolutionDpiExample') },
61
+ }
62
+ : {
63
+ title,
64
+ body: t('download.resolutionHelp'),
65
+ example: { code: '2×', note: t('download.resolutionExample') },
66
+ };
67
+ }
@@ -1,8 +1,9 @@
1
1
  import { copyFigure } from '../core/copyFigure.ts';
2
2
  import type { FigureFormat } from '../core/downloadFigure.ts';
3
- import { downloadFigure } from '../core/downloadFigure.ts';
3
+ import { downloadFigure, downloadFigureSvg } from '../core/downloadFigure.ts';
4
4
  import { figurePng } from '../core/figurePng.ts';
5
5
  import type { FigurePixels } from '../core/figureScale.ts';
6
+ import type { FigureSvg } from '../core/figureSvg.ts';
6
7
  import { figureSvg } from '../core/figureSvg.ts';
7
8
 
8
9
  import type { FigureRedraw } from './useFigureRedraw.tsx';
@@ -12,7 +13,9 @@ import { useFigureTask } from './useFigureTask.ts';
12
13
  /** What {@link useFigureActions} works from. */
13
14
  export interface FigureActionsOptions {
14
15
  /** The `id` of the box the figure is mounted in. */
15
- targetId: string;
16
+ targetId?: string;
17
+ /** Writes the figure, in place of reading it off the page. */
18
+ writeFigure?: () => Promise<FigureSvg>;
16
19
  /** Which file save writes. */
17
20
  format: FigureFormat;
18
21
  /** The multiple of the figure on screen it is painted at. */
@@ -47,17 +50,26 @@ export interface FigureActions extends Omit<FigureTask, 'run'> {
47
50
  * @returns See {@link FigureActions}.
48
51
  */
49
52
  export function useFigureActions(options: FigureActionsOptions): FigureActions {
50
- const { targetId, format, scale, fileName, background } = options;
53
+ const { targetId, writeFigure, format, scale, fileName, background } =
54
+ options;
51
55
  const { redrawAt, redraw } = options;
52
56
  const { run, busy, failure, notice, clear } = useFigureTask();
53
57
 
54
- function withFigure(write: (box: string | Element) => Promise<void>) {
58
+ async function withFigure(write: (box: string | Element) => Promise<void>) {
59
+ if (targetId === undefined) throw new Error('There is no figure to save.');
55
60
  return redrawAt === null
56
61
  ? write(targetId)
57
62
  : redraw(targetId, redrawAt, write);
58
63
  }
59
64
 
60
65
  function save(): void {
66
+ if (writeFigure !== undefined) {
67
+ const written = writeFigure().then((figure) =>
68
+ downloadFigureSvg(figure, { format, scale, fileName }),
69
+ );
70
+ run(written.then(() => null));
71
+ return;
72
+ }
61
73
  const options = { format, scale, fileName, background };
62
74
  run(withFigure((box) => downloadFigure(box, options)).then(() => null));
63
75
  }
@@ -65,11 +77,14 @@ export function useFigureActions(options: FigureActionsOptions): FigureActions {
65
77
  function copy(): void {
66
78
  // The clipboard is written before anything is awaited, with the picture
67
79
  // still being painted: Safari only allows a write the click itself started.
68
- const png = new Promise<Blob>((resolve, reject) => {
69
- withFigure(async (box) => {
70
- resolve(await figurePng(figureSvg(box, { background }), scale));
71
- }).catch(reject);
72
- });
80
+ const png =
81
+ writeFigure === undefined
82
+ ? new Promise<Blob>((resolve, reject) => {
83
+ withFigure(async (box) => {
84
+ resolve(await figurePng(figureSvg(box, { background }), scale));
85
+ }).catch(reject);
86
+ })
87
+ : writeFigure().then((figure) => figurePng(figure, scale));
73
88
  run(copyFigure(png));
74
89
  }
75
90
 
@@ -1,8 +1,13 @@
1
1
  import type { ReactElement, ReactNode } from 'react';
2
- import { useCallback, useState } from 'react';
2
+ import { useCallback, useRef, useState } from 'react';
3
3
 
4
4
  import { useChromeT } from '../../i18n/ui/useT.ts';
5
5
  import type { FigureFormat } from '../core/downloadFigure.ts';
6
+ import {
7
+ DEFAULT_FIGURE_DPI,
8
+ FIGURE_DPIS,
9
+ dpiScale,
10
+ } from '../core/figureDpi.ts';
6
11
  import type { FigureLayout } from '../core/figureLayout.ts';
7
12
  import { figureLayoutRedraws, figureLayoutSize } from '../core/figureLayout.ts';
8
13
  import type { FigurePixels } from '../core/figureScale.ts';
@@ -14,64 +19,11 @@ import {
14
19
  import { figureSize } from '../core/figureTarget.ts';
15
20
 
16
21
  import { FigureDownloadPanel } from './FigureDownloadPanel.tsx';
22
+ import type { FigureDownloadOptions } from './figureDownloadOptions.ts';
17
23
  import { useFigureActions } from './useFigureActions.ts';
18
- import type { FigureRenderer } from './useFigureRedraw.tsx';
19
24
  import { useFigureRedraw } from './useFigureRedraw.tsx';
20
25
 
21
- /** What the "Save figure" panel is set up with. */
22
- export interface FigureDownloadOptions {
23
- /**
24
- * The `id` of the box the figure is mounted in. Everything drawn inside it
25
- * is saved — sixteen charts of a pair grid as readily as one scatter plot —
26
- * and the controls floating over it are left behind.
27
- */
28
- targetId: string;
29
- /**
30
- * What the saved file is called, without its extension. Name it after the
31
- * data rather than after the tool: a reader with four of these in a
32
- * downloads folder cannot tell four `figure.png` apart.
33
- * @default 'figure'
34
- */
35
- fileName?: string;
36
- /**
37
- * The format it opens on.
38
- * @default 'png'
39
- */
40
- defaultFormat?: FigureFormat;
41
- /**
42
- * The resolution a PNG opens on, as a multiple of the figure on screen. An
43
- * SVG opens at 1×, the size it has on screen, and each format keeps the
44
- * multiple the reader last picked for it.
45
- * @default 2
46
- */
47
- defaultScale?: number;
48
- /**
49
- * The resolutions offered.
50
- * @default [1, 2, 3, 4]
51
- */
52
- scales?: readonly number[];
53
- /**
54
- * What is painted under the figure. `transparent` leaves it unpainted, for a
55
- * figure going onto a coloured slide.
56
- * @default the surface the figure is drawn on
57
- */
58
- background?: string;
59
- /**
60
- * What the panel is called.
61
- * @default the chrome's own line, in the language of the page
62
- */
63
- title?: string;
64
- /**
65
- * Draws the figure at a size, for a file. When it is given the panel offers
66
- * a size — as shown, 4:3, 16:9, a journal column, or typed — and a figure
67
- * saved at a size other than its own is drawn again at that size, off the
68
- * page, so its axes and labels are laid out for the new shape rather than
69
- * stretched into it. Draw exactly what is on screen, with the same data,
70
- * zoom and colours; only the box changes.
71
- * @default undefined — the figure is saved at the size it has on screen
72
- */
73
- renderFigure?: FigureRenderer;
74
- }
26
+ export type { FigureDownloadOptions } from './figureDownloadOptions.ts';
75
27
 
76
28
  /** What {@link useFigureDownload} hands back. */
77
29
  export interface FigureDownloadState {
@@ -93,6 +45,9 @@ export interface FigureDownloadState {
93
45
  portal: ReactNode;
94
46
  }
95
47
 
48
+ /** The dots per inch offered, as the multiples the figure is painted at. */
49
+ const DPI_SCALES = FIGURE_DPIS.map(dpiScale);
50
+
96
51
  /**
97
52
  * The "Save figure" panel — save as PNG or SVG, or copy as PNG — for a caller
98
53
  * that brings its own trigger, such as a button in an editor's toolbar.
@@ -103,10 +58,18 @@ export interface FigureDownloadState {
103
58
  export function useFigureDownload(
104
59
  options: FigureDownloadOptions,
105
60
  ): FigureDownloadState {
106
- const { targetId, fileName, background, scales = FIGURE_SCALES } = options;
107
- const { defaultFormat = 'png', defaultScale = DEFAULT_FIGURE_SCALE } =
108
- options;
109
- const { title, renderFigure } = options;
61
+ const { targetId, writeFigure, fileName, background } = options;
62
+ const { unit = 'multiple', defaultFormat = 'png' } = options;
63
+ const { title, renderFigure, onScaleChange } = options;
64
+ const dpi = unit === 'dpi';
65
+ const scales = options.scales ?? (dpi ? DPI_SCALES : FIGURE_SCALES);
66
+ const defaultScale =
67
+ options.defaultScale ??
68
+ (dpi ? dpiScale(DEFAULT_FIGURE_DPI) : DEFAULT_FIGURE_SCALE);
69
+ // A figure with a printed size, or one its page wrote, keeps the size its
70
+ // SVG states: the resolution is then the PNG's alone.
71
+ const svgAtOwnSize = dpi || writeFigure !== undefined;
72
+ const redraws = renderFigure !== undefined && writeFigure === undefined;
110
73
 
111
74
  const t = useChromeT();
112
75
  const [isOpen, setIsOpen] = useState(false);
@@ -115,19 +78,23 @@ export function useFigureDownload(
115
78
  png: defaultScale,
116
79
  svg: defaultFigureScale('svg'),
117
80
  }));
118
- const scale = picked[format];
81
+ const scale = format === 'svg' && svgAtOwnSize ? 1 : picked[format];
119
82
  const [size, setSize] = useState<FigurePixels | null>(null);
83
+ const opening = useRef(0);
120
84
  const [layout, setLayout] = useState<FigureLayout>('screen');
121
85
  const [custom, setCustom] = useState<FigurePixels | null>(null);
122
- const { redraw, portal } = useFigureRedraw(renderFigure);
86
+ const { redraw, portal } = useFigureRedraw(
87
+ redraws ? renderFigure : undefined,
88
+ );
123
89
  const redrawAt =
124
- renderFigure !== undefined &&
90
+ redraws &&
125
91
  size !== null &&
126
92
  figureLayoutRedraws(layout, size, custom ?? size)
127
93
  ? figureLayoutSize(layout, size, custom ?? size)
128
94
  : null;
129
95
  const { save, copy, busy, failure, notice, clear } = useFigureActions({
130
96
  targetId,
97
+ writeFigure,
131
98
  format,
132
99
  scale,
133
100
  fileName,
@@ -144,10 +111,26 @@ export function useFigureDownload(
144
111
  (next: boolean) => {
145
112
  setIsOpen(next);
146
113
  if (!next) return;
147
- setSize(figureSize(targetId));
148
114
  clear();
115
+ if (writeFigure === undefined) {
116
+ setSize(targetId === undefined ? null : figureSize(targetId));
117
+ return;
118
+ }
119
+ // A written figure is measured once it is written; only the last
120
+ // opening is answered.
121
+ opening.current += 1;
122
+ const ticket = opening.current;
123
+ writeFigure().then(
124
+ (figure) => {
125
+ if (ticket !== opening.current) return;
126
+ setSize({ width: figure.width, height: figure.height });
127
+ },
128
+ () => {
129
+ if (ticket === opening.current) setSize(null);
130
+ },
131
+ );
149
132
  },
150
- [targetId, clear],
133
+ [targetId, writeFigure, clear],
151
134
  );
152
135
 
153
136
  // What the last copy came to only describes the choices it was made with.
@@ -164,25 +147,28 @@ export function useFigureDownload(
164
147
  format={format}
165
148
  scale={scale}
166
149
  scales={scales}
150
+ unit={unit}
151
+ svgAtOwnSize={svgAtOwnSize}
167
152
  size={size}
168
153
  failure={failure}
169
154
  notice={notice}
170
155
  saving={busy}
171
156
  onFormatChange={changed(setFormat)}
172
- onScaleChange={changed((next: number) =>
173
- setPicked((current) => ({ ...current, [format]: next })),
174
- )}
157
+ onScaleChange={changed((next: number) => {
158
+ setPicked((current) => ({ ...current, [format]: next }));
159
+ if (format === 'png') onScaleChange?.(next);
160
+ })}
175
161
  onSave={save}
176
162
  onCopy={copy}
177
163
  sizing={
178
- renderFigure === undefined
179
- ? undefined
180
- : {
164
+ redraws
165
+ ? {
181
166
  layout,
182
167
  custom,
183
168
  onLayoutChange: changed(setLayout),
184
169
  onCustomChange: changed(setCustom),
185
170
  }
171
+ : undefined
186
172
  }
187
173
  />
188
174
  );
@@ -350,6 +350,20 @@ export const ECOSYSTEM_SITES: readonly EcosystemSite[] = [
350
350
  brandAlt: '#a16207',
351
351
  mark: { plate: '#0072b2', accent: '#e69f00' },
352
352
  },
353
+ {
354
+ id: 'draw',
355
+ name: { lead: 'draw', alt: 'cheminfo', dot: true },
356
+ host: 'draw.cheminfo.org',
357
+ tagline: 'Journal-grade structures, in an SVG that keeps the chemistry.',
358
+ group: 'computing',
359
+ // The ink a structure is printed in.
360
+ brand: '#1f2a44',
361
+ // The red curly arrows are taught in, at 5.9:1 on white.
362
+ brandAlt: '#c0261d',
363
+ // Ink and red on paper: a red nib on the navy stays under 4:1, where on
364
+ // white it reads at 5.9:1.
365
+ mark: { plate: '#ffffff', accent: '#c0261d', edge: '#dfe3e8' },
366
+ },
353
367
  ];
354
368
 
355
369
  /** How a link to a site is written, beyond the site itself. */
@@ -35,7 +35,8 @@ export type SiteId =
35
35
  | 'chembio'
36
36
  | 'wikidata'
37
37
  | 'mz'
38
- | 'vibrations';
38
+ | 'vibrations'
39
+ | 'draw';
39
40
 
40
41
  /** A site's name, split the way its own wordmark splits it. */
41
42
  export interface SiteName {
@@ -602,4 +602,24 @@ export const GLYPHS: Record<SiteId, (alt: string) => ReactNode> = {
602
602
  />
603
603
  </>
604
604
  ),
605
+ // A ring in ink, with a pen nib drawing its last bond in the answering
606
+ // colour: a structure being drawn by hand.
607
+ draw: (alt) => (
608
+ <>
609
+ <path
610
+ d="M19 15.25 19 22.75 12.5 26.5 6 22.75 6 15.25 12.5 11.5 15.3 13.1"
611
+ fill="none"
612
+ stroke="#1f2a44"
613
+ strokeWidth="2.4"
614
+ strokeLinecap="round"
615
+ strokeLinejoin="round"
616
+ />
617
+ <path
618
+ d="M15.6 13 22.32 11.94 26.35 6.78 21.82 2.25 16.66 6.28Z"
619
+ fill={alt}
620
+ />
621
+ <path d="M16.59 12.01 20.13 8.47" stroke="#ffffff" strokeWidth="1.1" />
622
+ <circle cx="20.55" cy="8.05" r="1.25" fill="#ffffff" />
623
+ </>
624
+ ),
605
625
  };
@@ -109,7 +109,7 @@ export function connectHost(options: HostConnectionOptions): () => void {
109
109
  const result =
110
110
  request.type === 'load'
111
111
  ? await applyLoad(request)
112
- : answerGet(request, tool, outputs);
112
+ : await answerGet(request, tool, outputs);
113
113
  port?.postMessage(result);
114
114
  })
115
115
  // A request that failed must not stop the ones after it being served,