react-cheminfo 0.50.0 → 0.52.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 (314) hide show
  1. package/README.md +71 -16
  2. package/bin/check-seo.mjs +0 -0
  3. package/lib/clipboard/core/index.d.ts +0 -1
  4. package/lib/clipboard/core/index.d.ts.map +1 -1
  5. package/lib/clipboard/core/index.js +0 -1
  6. package/lib/clipboard/core/index.js.map +1 -1
  7. package/lib/clipboard/ui/CopyButton.d.ts +6 -0
  8. package/lib/clipboard/ui/CopyButton.d.ts.map +1 -1
  9. package/lib/clipboard/ui/CopyButton.js +5 -2
  10. package/lib/clipboard/ui/CopyButton.js.map +1 -1
  11. package/lib/color/core/index.d.ts +3 -0
  12. package/lib/color/core/index.d.ts.map +1 -1
  13. package/lib/color/core/index.js +2 -0
  14. package/lib/color/core/index.js.map +1 -1
  15. package/lib/color/core/interpolate.d.ts +4 -2
  16. package/lib/color/core/interpolate.d.ts.map +1 -1
  17. package/lib/color/core/interpolate.js +34 -12
  18. package/lib/color/core/interpolate.js.map +1 -1
  19. package/lib/color/core/stops.d.ts +43 -0
  20. package/lib/color/core/stops.d.ts.map +1 -0
  21. package/lib/color/core/stops.js +66 -0
  22. package/lib/color/core/stops.js.map +1 -0
  23. package/lib/color/core/tone.d.ts +25 -0
  24. package/lib/color/core/tone.d.ts.map +1 -0
  25. package/lib/color/core/tone.js +67 -0
  26. package/lib/color/core/tone.js.map +1 -0
  27. package/lib/color/core/uniform.d.ts +36 -0
  28. package/lib/color/core/uniform.d.ts.map +1 -0
  29. package/lib/color/core/uniform.js +61 -0
  30. package/lib/color/core/uniform.js.map +1 -0
  31. package/lib/color/ui/ColorScaleEditor.d.ts +5 -6
  32. package/lib/color/ui/ColorScaleEditor.d.ts.map +1 -1
  33. package/lib/color/ui/ColorScaleEditor.js +74 -84
  34. package/lib/color/ui/ColorScaleEditor.js.map +1 -1
  35. package/lib/color/ui/ColorScaleSelect.d.ts +16 -0
  36. package/lib/color/ui/ColorScaleSelect.d.ts.map +1 -1
  37. package/lib/color/ui/ColorScaleSelect.js +69 -17
  38. package/lib/color/ui/ColorScaleSelect.js.map +1 -1
  39. package/lib/color/ui/ColorScaleTone.d.ts +17 -0
  40. package/lib/color/ui/ColorScaleTone.d.ts.map +1 -0
  41. package/lib/color/ui/ColorScaleTone.js +55 -0
  42. package/lib/color/ui/ColorScaleTone.js.map +1 -0
  43. package/lib/color/ui/ColorScaleTrack.d.ts +29 -0
  44. package/lib/color/ui/ColorScaleTrack.d.ts.map +1 -0
  45. package/lib/color/ui/ColorScaleTrack.js +143 -0
  46. package/lib/color/ui/ColorScaleTrack.js.map +1 -0
  47. package/lib/download/core/copyFigure.d.ts +14 -0
  48. package/lib/download/core/copyFigure.d.ts.map +1 -0
  49. package/lib/download/core/copyFigure.js +18 -0
  50. package/lib/download/core/copyFigure.js.map +1 -0
  51. package/lib/download/core/figureHtml.js +1 -0
  52. package/lib/download/core/figureHtml.js.map +1 -1
  53. package/lib/download/core/figureHtmlMarkup.d.ts +10 -0
  54. package/lib/download/core/figureHtmlMarkup.d.ts.map +1 -1
  55. package/lib/download/core/figureHtmlMarkup.js +7 -1
  56. package/lib/download/core/figureHtmlMarkup.js.map +1 -1
  57. package/lib/download/core/index.d.ts +2 -0
  58. package/lib/download/core/index.d.ts.map +1 -1
  59. package/lib/download/core/index.js +1 -0
  60. package/lib/download/core/index.js.map +1 -1
  61. package/lib/download/ui/FigureDownloadPanel.d.ts +2 -3
  62. package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
  63. package/lib/download/ui/FigureDownloadPanel.js +1 -1
  64. package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
  65. package/lib/download/ui/figureDownloadHint.d.ts +1 -1
  66. package/lib/download/ui/figureDownloadHint.d.ts.map +1 -1
  67. package/lib/download/ui/figureDownloadHint.js.map +1 -1
  68. package/lib/download/ui/index.d.ts +0 -1
  69. package/lib/download/ui/index.d.ts.map +1 -1
  70. package/lib/download/ui/useFigureActions.d.ts +2 -11
  71. package/lib/download/ui/useFigureActions.d.ts.map +1 -1
  72. package/lib/download/ui/useFigureActions.js +4 -23
  73. package/lib/download/ui/useFigureActions.js.map +1 -1
  74. package/lib/download/ui/useFigureTask.d.ts +21 -0
  75. package/lib/download/ui/useFigureTask.d.ts.map +1 -0
  76. package/lib/download/ui/useFigureTask.js +27 -0
  77. package/lib/download/ui/useFigureTask.js.map +1 -0
  78. package/lib/host/core/connectHost.d.ts +75 -0
  79. package/lib/host/core/connectHost.d.ts.map +1 -0
  80. package/lib/host/core/connectHost.js +171 -0
  81. package/lib/host/core/connectHost.js.map +1 -0
  82. package/lib/host/core/hostStructure.d.ts +52 -0
  83. package/lib/host/core/hostStructure.d.ts.map +1 -0
  84. package/lib/host/core/hostStructure.js +106 -0
  85. package/lib/host/core/hostStructure.js.map +1 -0
  86. package/lib/host/core/index.d.ts +9 -0
  87. package/lib/host/core/index.d.ts.map +1 -0
  88. package/lib/host/core/index.js +5 -0
  89. package/lib/host/core/index.js.map +1 -0
  90. package/lib/host/core/kinds.d.ts +73 -0
  91. package/lib/host/core/kinds.d.ts.map +1 -0
  92. package/lib/host/core/kinds.js +88 -0
  93. package/lib/host/core/kinds.js.map +1 -0
  94. package/lib/host/core/protocol.d.ts +134 -0
  95. package/lib/host/core/protocol.d.ts.map +1 -0
  96. package/lib/host/core/protocol.js +92 -0
  97. package/lib/host/core/protocol.js.map +1 -0
  98. package/lib/host/testing/sciPeaks.d.ts +21 -0
  99. package/lib/host/testing/sciPeaks.d.ts.map +1 -0
  100. package/lib/host/testing/sciPeaks.js +62 -0
  101. package/lib/host/testing/sciPeaks.js.map +1 -0
  102. package/lib/host/testing/standInHost.d.ts +47 -0
  103. package/lib/host/testing/standInHost.d.ts.map +1 -0
  104. package/lib/host/testing/standInHost.js +85 -0
  105. package/lib/host/testing/standInHost.js.map +1 -0
  106. package/lib/host/ui/index.d.ts +3 -0
  107. package/lib/host/ui/index.d.ts.map +1 -0
  108. package/lib/host/ui/index.js +2 -0
  109. package/lib/host/ui/index.js.map +1 -0
  110. package/lib/host/ui/useHostConnection.d.ts +36 -0
  111. package/lib/host/ui/useHostConnection.d.ts.map +1 -0
  112. package/lib/host/ui/useHostConnection.js +62 -0
  113. package/lib/host/ui/useHostConnection.js.map +1 -0
  114. package/lib/host-testing.d.ts +8 -0
  115. package/lib/host-testing.d.ts.map +1 -0
  116. package/lib/host-testing.js +7 -0
  117. package/lib/host-testing.js.map +1 -0
  118. package/lib/host.d.ts +11 -0
  119. package/lib/host.d.ts.map +1 -0
  120. package/lib/host.js +11 -0
  121. package/lib/host.js.map +1 -0
  122. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  123. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  124. package/lib/locales/de.json +28 -2
  125. package/lib/locales/en.json +28 -2
  126. package/lib/locales/es.json +28 -2
  127. package/lib/locales/fr.json +28 -2
  128. package/lib/locales/it.json +28 -2
  129. package/lib/molecule3d/core/index.d.ts +1 -1
  130. package/lib/molecule3d/core/index.d.ts.map +1 -1
  131. package/lib/molecule3d/core/index.js +1 -1
  132. package/lib/molecule3d/core/index.js.map +1 -1
  133. package/lib/molecule3d/core/settings.d.ts +15 -0
  134. package/lib/molecule3d/core/settings.d.ts.map +1 -1
  135. package/lib/molecule3d/core/settings.js +25 -0
  136. package/lib/molecule3d/core/settings.js.map +1 -1
  137. package/lib/molecule3d/ui/Molecule3DExport.d.ts +3 -0
  138. package/lib/molecule3d/ui/Molecule3DExport.d.ts.map +1 -1
  139. package/lib/molecule3d/ui/Molecule3DExport.js +10 -16
  140. package/lib/molecule3d/ui/Molecule3DExport.js.map +1 -1
  141. package/lib/molecule3d/ui/Molecule3DOptions.d.ts +3 -1
  142. package/lib/molecule3d/ui/Molecule3DOptions.d.ts.map +1 -1
  143. package/lib/molecule3d/ui/Molecule3DOptions.js +22 -6
  144. package/lib/molecule3d/ui/Molecule3DOptions.js.map +1 -1
  145. package/lib/molecule3d/ui/MoleculeCanvas3D.d.ts.map +1 -1
  146. package/lib/molecule3d/ui/MoleculeCanvas3D.js +4 -3
  147. package/lib/molecule3d/ui/MoleculeCanvas3D.js.map +1 -1
  148. package/lib/molecule3d/ui/exportMoleculeImage.d.ts +9 -0
  149. package/lib/molecule3d/ui/exportMoleculeImage.d.ts.map +1 -1
  150. package/lib/molecule3d/ui/exportMoleculeImage.js +15 -0
  151. package/lib/molecule3d/ui/exportMoleculeImage.js.map +1 -1
  152. package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts +2 -1
  153. package/lib/molecule3d/ui/moleculeViewer3DProps.d.ts.map +1 -1
  154. package/lib/molecule3d/ui/useImageExport.d.ts +7 -1
  155. package/lib/molecule3d/ui/useImageExport.d.ts.map +1 -1
  156. package/lib/molecule3d/ui/useImageExport.js +12 -3
  157. package/lib/molecule3d/ui/useImageExport.js.map +1 -1
  158. package/lib/overlay/ui/FigureBar.d.ts +41 -0
  159. package/lib/overlay/ui/FigureBar.d.ts.map +1 -0
  160. package/lib/overlay/ui/FigureBar.js +43 -0
  161. package/lib/overlay/ui/FigureBar.js.map +1 -0
  162. package/lib/overlay/ui/OverlayBar.d.ts +13 -4
  163. package/lib/overlay/ui/OverlayBar.d.ts.map +1 -1
  164. package/lib/overlay/ui/OverlayBar.js +2 -2
  165. package/lib/overlay/ui/OverlayBar.js.map +1 -1
  166. package/lib/overlay/ui/OverlayBarStrip.d.ts +2 -1
  167. package/lib/overlay/ui/OverlayBarStrip.d.ts.map +1 -1
  168. package/lib/overlay/ui/OverlayBarStrip.js +9 -5
  169. package/lib/overlay/ui/OverlayBarStrip.js.map +1 -1
  170. package/lib/overlay/ui/OverlayIconButton.d.ts +8 -2
  171. package/lib/overlay/ui/OverlayIconButton.d.ts.map +1 -1
  172. package/lib/overlay/ui/OverlayIconButton.js +2 -1
  173. package/lib/overlay/ui/OverlayIconButton.js.map +1 -1
  174. package/lib/overlay/ui/index.d.ts +4 -0
  175. package/lib/overlay/ui/index.d.ts.map +1 -1
  176. package/lib/overlay/ui/index.js +2 -0
  177. package/lib/overlay/ui/index.js.map +1 -1
  178. package/lib/overlay/ui/overlayBarShape.d.ts +18 -0
  179. package/lib/overlay/ui/overlayBarShape.d.ts.map +1 -1
  180. package/lib/overlay/ui/overlayStyles.d.ts +30 -0
  181. package/lib/overlay/ui/overlayStyles.d.ts.map +1 -1
  182. package/lib/overlay/ui/overlayStyles.js +52 -0
  183. package/lib/overlay/ui/overlayStyles.js.map +1 -1
  184. package/lib/overlay/ui/useFigureBarAwake.d.ts +12 -0
  185. package/lib/overlay/ui/useFigureBarAwake.d.ts.map +1 -0
  186. package/lib/overlay/ui/useFigureBarAwake.js +51 -0
  187. package/lib/overlay/ui/useFigureBarAwake.js.map +1 -0
  188. package/lib/periodic/core/elements.d.ts +6 -3
  189. package/lib/periodic/core/elements.d.ts.map +1 -1
  190. package/lib/periodic/core/elements.js +9 -3
  191. package/lib/periodic/core/elements.js.map +1 -1
  192. package/lib/periodic/core/index.d.ts +2 -2
  193. package/lib/periodic/core/index.d.ts.map +1 -1
  194. package/lib/periodic/core/index.js +1 -1
  195. package/lib/periodic/core/index.js.map +1 -1
  196. package/lib/periodic/core/layout.d.ts +33 -3
  197. package/lib/periodic/core/layout.d.ts.map +1 -1
  198. package/lib/periodic/core/layout.js +14 -0
  199. package/lib/periodic/core/layout.js.map +1 -1
  200. package/lib/periodic/ui/BlockStrip.d.ts +20 -0
  201. package/lib/periodic/ui/BlockStrip.d.ts.map +1 -0
  202. package/lib/periodic/ui/BlockStrip.js +48 -0
  203. package/lib/periodic/ui/BlockStrip.js.map +1 -0
  204. package/lib/periodic/ui/ElementCell.d.ts.map +1 -1
  205. package/lib/periodic/ui/ElementCell.js +9 -8
  206. package/lib/periodic/ui/ElementCell.js.map +1 -1
  207. package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
  208. package/lib/periodic/ui/PeriodicTable.js +3 -1
  209. package/lib/periodic/ui/PeriodicTable.js.map +1 -1
  210. package/lib/periodic/ui/PeriodicTableHelp.d.ts +33 -0
  211. package/lib/periodic/ui/PeriodicTableHelp.d.ts.map +1 -0
  212. package/lib/periodic/ui/PeriodicTableHelp.js +107 -0
  213. package/lib/periodic/ui/PeriodicTableHelp.js.map +1 -0
  214. package/lib/periodic/ui/cellStyles.d.ts +3 -2
  215. package/lib/periodic/ui/cellStyles.d.ts.map +1 -1
  216. package/lib/periodic/ui/cellStyles.js +3 -2
  217. package/lib/periodic/ui/cellStyles.js.map +1 -1
  218. package/lib/periodic/ui/index.d.ts +2 -0
  219. package/lib/periodic/ui/index.d.ts.map +1 -1
  220. package/lib/periodic/ui/index.js +1 -0
  221. package/lib/periodic/ui/index.js.map +1 -1
  222. package/lib/periodic/ui/periodicTableProps.d.ts +5 -4
  223. package/lib/periodic/ui/periodicTableProps.d.ts.map +1 -1
  224. package/lib/periodic/ui/tableLayout.d.ts +3 -1
  225. package/lib/periodic/ui/tableLayout.d.ts.map +1 -1
  226. package/lib/periodic/ui/tableLayout.js +8 -3
  227. package/lib/periodic/ui/tableLayout.js.map +1 -1
  228. package/lib/share/ui/ShareDialogContent.d.ts +3 -2
  229. package/lib/share/ui/ShareDialogContent.d.ts.map +1 -1
  230. package/lib/share/ui/ShareDialogContent.js +5 -6
  231. package/lib/share/ui/ShareDialogContent.js.map +1 -1
  232. package/lib/share/ui/ShareLinkBar.d.ts +8 -2
  233. package/lib/share/ui/ShareLinkBar.d.ts.map +1 -1
  234. package/lib/share/ui/ShareLinkBar.js +6 -5
  235. package/lib/share/ui/ShareLinkBar.js.map +1 -1
  236. package/lib/share/ui/SharePreview.d.ts.map +1 -1
  237. package/lib/share/ui/SharePreview.js +2 -2
  238. package/lib/share/ui/SharePreview.js.map +1 -1
  239. package/lib/structure/ui/StructurePicturePane.js +3 -3
  240. package/lib/structure/ui/StructurePicturePane.js.map +1 -1
  241. package/package.json +4 -1
  242. package/src/clipboard/core/index.ts +0 -1
  243. package/src/clipboard/ui/CopyButton.tsx +12 -1
  244. package/src/color/core/index.ts +9 -0
  245. package/src/color/core/interpolate.ts +51 -22
  246. package/src/color/core/stops.ts +98 -0
  247. package/src/color/core/tone.ts +79 -0
  248. package/src/color/core/uniform.ts +67 -0
  249. package/src/color/ui/ColorScaleEditor.tsx +115 -141
  250. package/src/color/ui/ColorScaleSelect.tsx +160 -36
  251. package/src/color/ui/ColorScaleTone.tsx +103 -0
  252. package/src/color/ui/ColorScaleTrack.tsx +239 -0
  253. package/src/download/core/copyFigure.ts +20 -0
  254. package/src/download/core/figureHtml.ts +1 -0
  255. package/src/download/core/figureHtmlMarkup.ts +14 -1
  256. package/src/download/core/index.ts +2 -0
  257. package/src/download/ui/FigureDownloadPanel.tsx +8 -11
  258. package/src/download/ui/figureDownloadHint.ts +1 -2
  259. package/src/download/ui/index.ts +0 -1
  260. package/src/download/ui/useFigureActions.ts +6 -42
  261. package/src/download/ui/useFigureTask.ts +46 -0
  262. package/src/host/core/connectHost.ts +240 -0
  263. package/src/host/core/hostStructure.ts +129 -0
  264. package/src/host/core/index.ts +46 -0
  265. package/src/host/core/kinds.ts +128 -0
  266. package/src/host/core/protocol.ts +197 -0
  267. package/src/host/testing/sciPeaks.ts +66 -0
  268. package/src/host/testing/standInHost.ts +116 -0
  269. package/src/host/ui/index.ts +2 -0
  270. package/src/host/ui/useHostConnection.ts +85 -0
  271. package/src/host-testing.ts +18 -0
  272. package/src/host.ts +11 -0
  273. package/src/locales/de.json +28 -2
  274. package/src/locales/en.json +28 -2
  275. package/src/locales/es.json +28 -2
  276. package/src/locales/fr.json +28 -2
  277. package/src/locales/it.json +28 -2
  278. package/src/molecule3d/core/index.ts +2 -0
  279. package/src/molecule3d/core/settings.ts +35 -0
  280. package/src/molecule3d/ui/Molecule3DExport.tsx +18 -17
  281. package/src/molecule3d/ui/Molecule3DOptions.tsx +51 -3
  282. package/src/molecule3d/ui/MoleculeCanvas3D.tsx +11 -3
  283. package/src/molecule3d/ui/exportMoleculeImage.ts +20 -0
  284. package/src/molecule3d/ui/moleculeViewer3DProps.ts +2 -1
  285. package/src/molecule3d/ui/useImageExport.ts +25 -3
  286. package/src/overlay/ui/FigureBar.tsx +96 -0
  287. package/src/overlay/ui/OverlayBar.tsx +15 -5
  288. package/src/overlay/ui/OverlayBarStrip.tsx +34 -22
  289. package/src/overlay/ui/OverlayIconButton.tsx +10 -2
  290. package/src/overlay/ui/index.ts +4 -0
  291. package/src/overlay/ui/overlayBarShape.ts +19 -0
  292. package/src/overlay/ui/overlayStyles.ts +61 -0
  293. package/src/overlay/ui/useFigureBarAwake.ts +56 -0
  294. package/src/periodic/core/elements.ts +8 -3
  295. package/src/periodic/core/index.ts +8 -1
  296. package/src/periodic/core/layout.ts +45 -3
  297. package/src/periodic/ui/BlockStrip.tsx +81 -0
  298. package/src/periodic/ui/ElementCell.tsx +9 -8
  299. package/src/periodic/ui/PeriodicTable.tsx +4 -1
  300. package/src/periodic/ui/PeriodicTableHelp.tsx +205 -0
  301. package/src/periodic/ui/cellStyles.ts +3 -2
  302. package/src/periodic/ui/index.ts +5 -0
  303. package/src/periodic/ui/periodicTableProps.ts +5 -4
  304. package/src/periodic/ui/tableLayout.ts +9 -3
  305. package/src/share/ui/ShareDialogContent.tsx +9 -13
  306. package/src/share/ui/ShareLinkBar.tsx +16 -4
  307. package/src/share/ui/SharePreview.tsx +6 -2
  308. package/src/structure/ui/StructurePicturePane.tsx +3 -3
  309. package/styles/chrome.css +43 -32
  310. package/lib/clipboard/core/copyPng.d.ts +0 -13
  311. package/lib/clipboard/core/copyPng.d.ts.map +0 -1
  312. package/lib/clipboard/core/copyPng.js +0 -19
  313. package/lib/clipboard/core/copyPng.js.map +0 -1
  314. package/src/clipboard/core/copyPng.ts +0 -20
@@ -76,7 +76,6 @@
76
76
  "share.copyIframe": "Iframe kopieren",
77
77
  "share.copyIframeHelpTitle": "Die Seite in Ihre einbauen",
78
78
  "share.copyIframeHelp": "Ein HTML-Schnipsel, das dort eingefügt wird, wo das HTML Ihrer Seite bearbeitet wird: das Werkzeug läuft dann darin.",
79
- "share.done": "Fertig",
80
79
  "cite.button": "Zitieren",
81
80
  "cite.copyReferenceAs": "Literaturangabe kopieren als",
82
81
  "cite.pleaseCiteBoth": "Bitte zitieren Sie beide Arbeiten",
@@ -155,13 +154,19 @@
155
154
  "color.custom": "Eigene",
156
155
  "color.customEllipsis": "Eigene…",
157
156
  "color.inUse": "in Gebrauch",
157
+ "color.uniform": "Eine Farbe",
158
+ "color.uniformDescription": "Alle Werte in einer Farbe, die Abbildung braucht keine Legende.",
159
+ "color.uniformColour": "Die Farbe wählen",
158
160
  "color.colourScale": "Farbskala",
159
161
  "color.legendLabel": "{what} von {low} bis {high}",
160
162
  "color.scaleBeingEdited": "Die bearbeitete Skala",
161
163
  "color.anchorColour": "Farbe des Ankers {index}",
162
164
  "color.anchorPosition": "Position des Ankers {index}",
163
165
  "color.removeAnchor": "Anker {index} entfernen",
164
- "color.addColour": "Eine Farbe hinzufügen",
166
+ "color.editorHint": "Klicken Sie auf den Streifen, um eine Farbe hinzuzufügen. Ziehen Sie einen Anker, um ihn zu verschieben, doppelklicken Sie, um ihn umzufärben, zeigen Sie darauf und drücken Sie die Rücktaste, um ihn zu entfernen.",
167
+ "color.saturation": "Sättigung",
168
+ "color.brightness": "Helligkeit",
169
+ "color.toneHelp": "Alle Anker auf einmal; jeder behält seinen Farbton.",
165
170
  "color.path": "Weg zwischen zwei Ankern",
166
171
  "color.interpolation.rgb": "RGB — die Kanäle mischen",
167
172
  "color.interpolation.hsv": "HSV — den kurzen Weg drehen",
@@ -266,7 +271,24 @@
266
271
  "periodic.table": "Periodensystem",
267
272
  "periodic.group": "Gruppe {group}",
268
273
  "periodic.period": "Periode {period}",
274
+ "periodic.block": "{block}-Block",
269
275
  "periodic.allElements": "Alle Elemente",
276
+ "periodic.help.title": "Elemente auswählen",
277
+ "periodic.help.click": "Klick",
278
+ "periodic.help.modClick": "+ Klick",
279
+ "periodic.help.element": "Ein Element",
280
+ "periodic.help.elementClick": "Zeigt es an",
281
+ "periodic.help.elementMod": "Fügt es hinzu oder entfernt es",
282
+ "periodic.help.number": "Eine Perioden- oder Gruppennummer",
283
+ "periodic.help.numberClick": "Wählt die Zeile oder Spalte",
284
+ "periodic.help.runMod": "Fügt sie der Auswahl hinzu",
285
+ "periodic.help.block": "s, p, d oder f, unter der Tabelle",
286
+ "periodic.help.blockClick": "Wählt den Block",
287
+ "periodic.help.corner": "Die Ecke ◢ oben links",
288
+ "periodic.help.cornerClick": "Wählt alle Elemente",
289
+ "periodic.help.arrowsClick": "Durch die Tabelle gehen",
290
+ "periodic.help.note": "Ein zweiter Klick auf eine Nummer oder einen Block hebt sie auf. Nicht Ausgewähltes wird abgeblendet.",
291
+ "periodic.help.ctrl": "Strg",
270
292
  "periodic.cellLabel": "{name} ({symbol}, Z = {atomicNumber})",
271
293
  "periodic.category.alkali-metal": "Alkalimetall",
272
294
  "periodic.category.alkaline-earth-metal": "Erdalkalimetall",
@@ -470,6 +492,10 @@
470
492
  "molecule3d.solventProbeHelp": "Radius der Lösungsmittelkugel, die über die Atome gerollt wird. 1,4 Å entspricht einem Wassermolekül; eine größere Sonde glättet die Oberfläche und schließt die engen Taschen.",
471
493
  "molecule3d.surfaceColour": "Farbe der Oberfläche",
472
494
  "molecule3d.colour": "Farbe",
495
+ "molecule3d.resetSettings": "Auf Standardwerte zurücksetzen",
496
+ "molecule3d.atDefaults": "Bereits auf Standardwerten",
497
+ "molecule3d.surfaceOff": "Die Oberfläche ist ausgeblendet.",
498
+ "molecule3d.showSurface": "Anzeigen",
473
499
  "molecule3d.coloring.uniform": "Einfarbig",
474
500
  "molecule3d.coloring.element": "Element",
475
501
  "molecule3d.coloring.polarity": "Polarität",
@@ -76,7 +76,6 @@
76
76
  "share.copyIframe": "Copy the iframe",
77
77
  "share.copyIframeHelpTitle": "Put the page inside yours",
78
78
  "share.copyIframeHelp": "A snippet of HTML to paste where your own page's HTML is edited: the tool then runs inside it.",
79
- "share.done": "Done",
80
79
  "cite.button": "Cite",
81
80
  "cite.copyReferenceAs": "Copy the reference as",
82
81
  "cite.pleaseCiteBoth": "Please cite both works",
@@ -155,13 +154,19 @@
155
154
  "color.custom": "Custom",
156
155
  "color.customEllipsis": "Custom…",
157
156
  "color.inUse": "in use",
157
+ "color.uniform": "One colour",
158
+ "color.uniformDescription": "Every value in one colour, so the figure needs no key.",
159
+ "color.uniformColour": "Pick the one colour",
158
160
  "color.colourScale": "Colour scale",
159
161
  "color.legendLabel": "{what} from {low} to {high}",
160
162
  "color.scaleBeingEdited": "The scale being edited",
161
163
  "color.anchorColour": "Colour of anchor {index}",
162
164
  "color.anchorPosition": "Position of anchor {index}",
163
165
  "color.removeAnchor": "Remove anchor {index}",
164
- "color.addColour": "Add a colour",
166
+ "color.editorHint": "Click the strip to add a colour. Drag an anchor to move it, double-click it to recolour it, point at it and press Backspace to remove it.",
167
+ "color.saturation": "Saturation",
168
+ "color.brightness": "Brightness",
169
+ "color.toneHelp": "Every anchor at once; each keeps its hue.",
165
170
  "color.path": "Path between two anchors",
166
171
  "color.interpolation.rgb": "RGB — mix the channels",
167
172
  "color.interpolation.hsv": "HSV — turn the short way",
@@ -412,7 +417,24 @@
412
417
  "periodic.table": "Periodic table",
413
418
  "periodic.group": "Group {group}",
414
419
  "periodic.period": "Period {period}",
420
+ "periodic.block": "{block}-block",
415
421
  "periodic.allElements": "All elements",
422
+ "periodic.help.title": "Picking elements",
423
+ "periodic.help.click": "Click",
424
+ "periodic.help.modClick": "+ click",
425
+ "periodic.help.element": "An element",
426
+ "periodic.help.elementClick": "Reads it",
427
+ "periodic.help.elementMod": "Adds or removes it",
428
+ "periodic.help.number": "A period or group number",
429
+ "periodic.help.numberClick": "Picks that row or column",
430
+ "periodic.help.runMod": "Adds it to the set",
431
+ "periodic.help.block": "s, p, d or f, under the table",
432
+ "periodic.help.blockClick": "Picks that block",
433
+ "periodic.help.corner": "The ◢ corner, top left",
434
+ "periodic.help.cornerClick": "Picks every element",
435
+ "periodic.help.arrowsClick": "Walk the table",
436
+ "periodic.help.note": "Clicking a number or a block again drops it. What is not picked is dimmed.",
437
+ "periodic.help.ctrl": "Ctrl",
416
438
  "periodic.cellLabel": "{name} ({symbol}, Z = {atomicNumber})",
417
439
  "periodic.category.alkali-metal": "Alkali metal",
418
440
  "periodic.category.alkaline-earth-metal": "Alkaline earth",
@@ -446,6 +468,10 @@
446
468
  "molecule3d.solventProbeHelp": "Radius of the solvent sphere rolled over the atoms. 1.4 Å is a water molecule; a larger probe smooths the surface and closes the narrow pockets.",
447
469
  "molecule3d.surfaceColour": "Surface colour",
448
470
  "molecule3d.colour": "Colour",
471
+ "molecule3d.resetSettings": "Reset to defaults",
472
+ "molecule3d.atDefaults": "Already at the defaults",
473
+ "molecule3d.surfaceOff": "The surface is hidden.",
474
+ "molecule3d.showSurface": "Show it",
449
475
  "molecule3d.coloring.uniform": "Uniform",
450
476
  "molecule3d.coloring.element": "Element",
451
477
  "molecule3d.coloring.polarity": "Polarity",
@@ -76,7 +76,6 @@
76
76
  "share.copyIframe": "Copiar el iframe",
77
77
  "share.copyIframeHelpTitle": "Poner la página dentro de la tuya",
78
78
  "share.copyIframeHelp": "Un fragmento de HTML para pegar donde se edita el HTML de tu página: la herramienta funciona dentro de él.",
79
- "share.done": "Listo",
80
79
  "cite.button": "Citar",
81
80
  "cite.copyReferenceAs": "Copiar la referencia como",
82
81
  "cite.pleaseCiteBoth": "Por favor, cite ambos trabajos",
@@ -155,13 +154,19 @@
155
154
  "color.custom": "A medida",
156
155
  "color.customEllipsis": "A medida…",
157
156
  "color.inUse": "en uso",
157
+ "color.uniform": "Un solo color",
158
+ "color.uniformDescription": "Todos los valores en un solo color: la figura no necesita leyenda.",
159
+ "color.uniformColour": "Elegir el color",
158
160
  "color.colourScale": "Escala de color",
159
161
  "color.legendLabel": "{what} de {low} a {high}",
160
162
  "color.scaleBeingEdited": "La escala que se está editando",
161
163
  "color.anchorColour": "Color del ancla {index}",
162
164
  "color.anchorPosition": "Posición del ancla {index}",
163
165
  "color.removeAnchor": "Quitar el ancla {index}",
164
- "color.addColour": "Añadir un color",
166
+ "color.editorHint": "Haga clic en la franja para añadir un color. Arrastre un ancla para moverla, haga doble clic para cambiar su color, señálela y pulse Retroceso para quitarla.",
167
+ "color.saturation": "Saturación",
168
+ "color.brightness": "Brillo",
169
+ "color.toneHelp": "Todas las anclas a la vez; cada una conserva su tono.",
165
170
  "color.path": "Camino entre dos anclas",
166
171
  "color.interpolation.rgb": "RGB — mezclar los canales",
167
172
  "color.interpolation.hsv": "HSV — girar por el camino corto",
@@ -266,7 +271,24 @@
266
271
  "periodic.table": "Tabla periódica",
267
272
  "periodic.group": "Grupo {group}",
268
273
  "periodic.period": "Periodo {period}",
274
+ "periodic.block": "Bloque {block}",
269
275
  "periodic.allElements": "Todos los elementos",
276
+ "periodic.help.title": "Elegir elementos",
277
+ "periodic.help.click": "Clic",
278
+ "periodic.help.modClick": "+ clic",
279
+ "periodic.help.element": "Un elemento",
280
+ "periodic.help.elementClick": "Lo muestra",
281
+ "periodic.help.elementMod": "Lo añade o lo quita",
282
+ "periodic.help.number": "Un número de periodo o de grupo",
283
+ "periodic.help.numberClick": "Elige esa fila o columna",
284
+ "periodic.help.runMod": "Lo añade a la selección",
285
+ "periodic.help.block": "s, p, d o f, bajo la tabla",
286
+ "periodic.help.blockClick": "Elige ese bloque",
287
+ "periodic.help.corner": "La esquina ◢, arriba a la izquierda",
288
+ "periodic.help.cornerClick": "Elige todos los elementos",
289
+ "periodic.help.arrowsClick": "Recorren la tabla",
290
+ "periodic.help.note": "Otro clic en un número o un bloque lo quita. Lo que no está elegido aparece atenuado.",
291
+ "periodic.help.ctrl": "Ctrl",
270
292
  "periodic.cellLabel": "{name} ({symbol}, Z = {atomicNumber})",
271
293
  "periodic.category.alkali-metal": "Metal alcalino",
272
294
  "periodic.category.alkaline-earth-metal": "Alcalinotérreo",
@@ -470,6 +492,10 @@
470
492
  "molecule3d.solventProbeHelp": "Radio de la esfera de disolvente que se hace rodar sobre los átomos. 1,4 Å corresponde a una molécula de agua; una sonda mayor suaviza la superficie y cierra los huecos estrechos.",
471
493
  "molecule3d.surfaceColour": "Color de la superficie",
472
494
  "molecule3d.colour": "Color",
495
+ "molecule3d.resetSettings": "Restablecer los valores predeterminados",
496
+ "molecule3d.atDefaults": "Ya en los valores predeterminados",
497
+ "molecule3d.surfaceOff": "La superficie está oculta.",
498
+ "molecule3d.showSurface": "Mostrar",
473
499
  "molecule3d.coloring.uniform": "Uniforme",
474
500
  "molecule3d.coloring.element": "Elemento",
475
501
  "molecule3d.coloring.polarity": "Polaridad",
@@ -76,7 +76,6 @@
76
76
  "share.copyIframe": "Copier l'iframe",
77
77
  "share.copyIframeHelpTitle": "Mettre la page dans la vôtre",
78
78
  "share.copyIframeHelp": "Un extrait de HTML à coller là où le HTML de votre page s'édite : l'outil s'exécute alors à l'intérieur.",
79
- "share.done": "Terminé",
80
79
  "cite.button": "Citer",
81
80
  "cite.copyReferenceAs": "Copier la référence en",
82
81
  "cite.pleaseCiteBoth": "Merci de citer les deux travaux",
@@ -155,13 +154,19 @@
155
154
  "color.custom": "Sur mesure",
156
155
  "color.customEllipsis": "Sur mesure…",
157
156
  "color.inUse": "en usage",
157
+ "color.uniform": "Une seule couleur",
158
+ "color.uniformDescription": "Toutes les valeurs dans une seule couleur : la figure n’a pas besoin de légende.",
159
+ "color.uniformColour": "Choisir la couleur",
158
160
  "color.colourScale": "Échelle de couleurs",
159
161
  "color.legendLabel": "{what} de {low} à {high}",
160
162
  "color.scaleBeingEdited": "L'échelle en cours d'édition",
161
163
  "color.anchorColour": "Couleur de l'ancre {index}",
162
164
  "color.anchorPosition": "Position de l'ancre {index}",
163
165
  "color.removeAnchor": "Retirer l'ancre {index}",
164
- "color.addColour": "Ajouter une couleur",
166
+ "color.editorHint": "Cliquez sur la bande pour ajouter une couleur. Faites glisser une ancre pour la déplacer, double-cliquez pour la recolorer, survolez-la et appuyez sur Retour arrière pour la retirer.",
167
+ "color.saturation": "Saturation",
168
+ "color.brightness": "Luminosité",
169
+ "color.toneHelp": "Toutes les ancres à la fois ; chacune garde sa teinte.",
165
170
  "color.path": "Chemin entre deux ancres",
166
171
  "color.interpolation.rgb": "RVB — mélanger les canaux",
167
172
  "color.interpolation.hsv": "TSV — tourner par le court chemin",
@@ -266,7 +271,24 @@
266
271
  "periodic.table": "Tableau périodique",
267
272
  "periodic.group": "Groupe {group}",
268
273
  "periodic.period": "Période {period}",
274
+ "periodic.block": "Bloc {block}",
269
275
  "periodic.allElements": "Tous les éléments",
276
+ "periodic.help.title": "Choisir des éléments",
277
+ "periodic.help.click": "Clic",
278
+ "periodic.help.modClick": "+ clic",
279
+ "periodic.help.element": "Un élément",
280
+ "periodic.help.elementClick": "Le lit",
281
+ "periodic.help.elementMod": "L’ajoute ou le retire",
282
+ "periodic.help.number": "Un numéro de période ou de groupe",
283
+ "periodic.help.numberClick": "Choisit la ligne ou la colonne",
284
+ "periodic.help.runMod": "L’ajoute à la sélection",
285
+ "periodic.help.block": "s, p, d ou f, sous le tableau",
286
+ "periodic.help.blockClick": "Choisit le bloc",
287
+ "periodic.help.corner": "Le coin ◢, en haut à gauche",
288
+ "periodic.help.cornerClick": "Choisit tous les éléments",
289
+ "periodic.help.arrowsClick": "Parcourent le tableau",
290
+ "periodic.help.note": "Un second clic sur un numéro ou un bloc le retire. Ce qui n’est pas choisi est estompé.",
291
+ "periodic.help.ctrl": "Ctrl",
270
292
  "periodic.cellLabel": "{name} ({symbol}, Z = {atomicNumber})",
271
293
  "periodic.category.alkali-metal": "Métal alcalin",
272
294
  "periodic.category.alkaline-earth-metal": "Alcalino-terreux",
@@ -470,6 +492,10 @@
470
492
  "molecule3d.solventProbeHelp": "Rayon de la sphère de solvant roulée sur les atomes. 1,4 Å correspond à une molécule d'eau ; une sonde plus grande lisse la surface et ferme les poches étroites.",
471
493
  "molecule3d.surfaceColour": "Couleur de la surface",
472
494
  "molecule3d.colour": "Couleur",
495
+ "molecule3d.resetSettings": "Rétablir les valeurs par défaut",
496
+ "molecule3d.atDefaults": "Déjà aux valeurs par défaut",
497
+ "molecule3d.surfaceOff": "La surface est masquée.",
498
+ "molecule3d.showSurface": "Afficher",
473
499
  "molecule3d.coloring.uniform": "Uniforme",
474
500
  "molecule3d.coloring.element": "Élément",
475
501
  "molecule3d.coloring.polarity": "Polarité",
@@ -76,7 +76,6 @@
76
76
  "share.copyIframe": "Copia l'iframe",
77
77
  "share.copyIframeHelpTitle": "Mettere la pagina dentro la tua",
78
78
  "share.copyIframeHelp": "Un frammento di HTML da incollare dove si modifica l'HTML della tua pagina: lo strumento funziona al suo interno.",
79
- "share.done": "Fatto",
80
79
  "cite.button": "Cita",
81
80
  "cite.copyReferenceAs": "Copia il riferimento come",
82
81
  "cite.pleaseCiteBoth": "Si prega di citare entrambi i lavori",
@@ -155,13 +154,19 @@
155
154
  "color.custom": "Personalizzata",
156
155
  "color.customEllipsis": "Personalizzata…",
157
156
  "color.inUse": "in uso",
157
+ "color.uniform": "Un solo colore",
158
+ "color.uniformDescription": "Tutti i valori in un solo colore: la figura non ha bisogno di legenda.",
159
+ "color.uniformColour": "Scegliere il colore",
158
160
  "color.colourScale": "Scala di colore",
159
161
  "color.legendLabel": "{what} da {low} a {high}",
160
162
  "color.scaleBeingEdited": "La scala in corso di modifica",
161
163
  "color.anchorColour": "Colore dell'ancora {index}",
162
164
  "color.anchorPosition": "Posizione dell'ancora {index}",
163
165
  "color.removeAnchor": "Rimuovi l'ancora {index}",
164
- "color.addColour": "Aggiungi un colore",
166
+ "color.editorHint": "Fai clic sulla striscia per aggiungere un colore. Trascina un'ancora per spostarla, fai doppio clic per cambiarne il colore, puntala e premi Backspace per rimuoverla.",
167
+ "color.saturation": "Saturazione",
168
+ "color.brightness": "Luminosità",
169
+ "color.toneHelp": "Tutte le ancore insieme; ognuna conserva la sua tinta.",
165
170
  "color.path": "Percorso fra due ancore",
166
171
  "color.interpolation.rgb": "RGB — mescolare i canali",
167
172
  "color.interpolation.hsv": "HSV — girare dal lato corto",
@@ -412,7 +417,24 @@
412
417
  "periodic.table": "Tavola periodica",
413
418
  "periodic.group": "Gruppo {group}",
414
419
  "periodic.period": "Periodo {period}",
420
+ "periodic.block": "Blocco {block}",
415
421
  "periodic.allElements": "Tutti gli elementi",
422
+ "periodic.help.title": "Scegliere gli elementi",
423
+ "periodic.help.click": "Clic",
424
+ "periodic.help.modClick": "+ clic",
425
+ "periodic.help.element": "Un elemento",
426
+ "periodic.help.elementClick": "Lo mostra",
427
+ "periodic.help.elementMod": "Lo aggiunge o lo toglie",
428
+ "periodic.help.number": "Un numero di periodo o di gruppo",
429
+ "periodic.help.numberClick": "Sceglie la riga o la colonna",
430
+ "periodic.help.runMod": "Lo aggiunge alla selezione",
431
+ "periodic.help.block": "s, p, d o f, sotto la tavola",
432
+ "periodic.help.blockClick": "Sceglie il blocco",
433
+ "periodic.help.corner": "L’angolo ◢, in alto a sinistra",
434
+ "periodic.help.cornerClick": "Sceglie tutti gli elementi",
435
+ "periodic.help.arrowsClick": "Percorrono la tavola",
436
+ "periodic.help.note": "Un altro clic su un numero o un blocco lo toglie. Ciò che non è scelto appare attenuato.",
437
+ "periodic.help.ctrl": "Ctrl",
416
438
  "periodic.cellLabel": "{name} ({symbol}, Z = {atomicNumber})",
417
439
  "periodic.category.alkali-metal": "Metallo alcalino",
418
440
  "periodic.category.alkaline-earth-metal": "Alcalino terroso",
@@ -446,6 +468,10 @@
446
468
  "molecule3d.solventProbeHelp": "Raggio della sfera di solvente fatta rotolare sugli atomi. 1,4 Å corrisponde a una molecola d'acqua; una sonda più grande liscia la superficie e chiude le tasche strette.",
447
469
  "molecule3d.surfaceColour": "Colore della superficie",
448
470
  "molecule3d.colour": "Colore",
471
+ "molecule3d.resetSettings": "Ripristina i valori predefiniti",
472
+ "molecule3d.atDefaults": "Già ai valori predefiniti",
473
+ "molecule3d.surfaceOff": "La superficie è nascosta.",
474
+ "molecule3d.showSurface": "Mostra",
449
475
  "molecule3d.coloring.uniform": "Uniforme",
450
476
  "molecule3d.coloring.element": "Elemento",
451
477
  "molecule3d.coloring.polarity": "Polarità",
@@ -45,5 +45,7 @@ export {
45
45
  isRepresentationId,
46
46
  isSurfaceColoringId,
47
47
  normalizeMolecule3DSettings,
48
+ resetMolecule3DSettings,
48
49
  resolveMolecule3DTools,
50
+ sameMolecule3DSettings,
49
51
  } from './settings.ts';
@@ -185,6 +185,41 @@ export function normalizeMolecule3DSettings(
185
185
  };
186
186
  }
187
187
 
188
+ /**
189
+ * What the options' reset button returns to: the defaults, with the surface
190
+ * left on or off as it is — that is the toolbar's toggle, not an option.
191
+ * @param settings - The settings in force.
192
+ * @param defaults - The settings the viewer opened on.
193
+ * @returns The defaults, keeping `showSurface`.
194
+ */
195
+ export function resetMolecule3DSettings(
196
+ settings: Molecule3DSettings,
197
+ defaults: Molecule3DSettings = DEFAULT_MOLECULE_3D_SETTINGS,
198
+ ): Molecule3DSettings {
199
+ return { ...defaults, showSurface: settings.showSurface };
200
+ }
201
+
202
+ /**
203
+ * Whether two settings draw the same picture.
204
+ * @param first - One settings record.
205
+ * @param second - The other.
206
+ * @returns True when every field is equal.
207
+ */
208
+ export function sameMolecule3DSettings(
209
+ first: Molecule3DSettings,
210
+ second: Molecule3DSettings,
211
+ ): boolean {
212
+ return (
213
+ first.representation === second.representation &&
214
+ first.sizeFactor === second.sizeFactor &&
215
+ first.showSurface === second.showSurface &&
216
+ first.surfaceAlpha === second.surfaceAlpha &&
217
+ first.probeRadius === second.probeRadius &&
218
+ first.surfaceColoring === second.surfaceColoring &&
219
+ first.surfaceColor === second.surfaceColor
220
+ );
221
+ }
222
+
188
223
  /**
189
224
  * Complete a partial tool selection.
190
225
  * @param tools - The tools a site switched on or off.
@@ -6,6 +6,7 @@
6
6
  import type { ReactElement } from 'react';
7
7
  import { useState } from 'react';
8
8
 
9
+ import type { FigureNotice } from '../../download/core/copyFigure.ts';
9
10
  import type { FigureFormat } from '../../download/core/downloadFigure.ts';
10
11
  import type { FigurePixels } from '../../download/core/figureScale.ts';
11
12
  import {
@@ -13,6 +14,7 @@ import {
13
14
  FIGURE_SCALES,
14
15
  } from '../../download/core/figureScale.ts';
15
16
  import { FigureDownloadPanel } from '../../download/ui/FigureDownloadPanel.tsx';
17
+ import { useFigureTask } from '../../download/ui/useFigureTask.ts';
16
18
  import { useChromeT } from '../../i18n/ui/useT.ts';
17
19
 
18
20
  /** Props of {@link Molecule3DExport}. */
@@ -21,6 +23,8 @@ export interface Molecule3DExportProps {
21
23
  getSize: () => FigurePixels | null;
22
24
  /** Writes the file. */
23
25
  onExport: (format: FigureFormat, scale: number) => Promise<void>;
26
+ /** Puts a PNG at that scale on the clipboard, and says what came of it. */
27
+ onCopy: (scale: number) => Promise<FigureNotice>;
24
28
  }
25
29
 
26
30
  /**
@@ -29,24 +33,19 @@ export interface Molecule3DExportProps {
29
33
  * @returns The panel.
30
34
  */
31
35
  export function Molecule3DExport(props: Molecule3DExportProps): ReactElement {
32
- const { getSize, onExport } = props;
36
+ const { getSize, onExport, onCopy } = props;
33
37
  const t = useChromeT();
34
38
  const [size] = useState(getSize);
35
39
  const [format, setFormat] = useState<FigureFormat>('png');
36
40
  const [scale, setScale] = useState(DEFAULT_FIGURE_SCALE);
37
- const [failure, setFailure] = useState<string | null>(null);
38
- const [saving, setSaving] = useState(false);
41
+ const { run, busy, failure, notice, clear } = useFigureTask();
39
42
 
40
- async function save(): Promise<void> {
41
- setSaving(true);
42
- try {
43
- await onExport(format, scale);
44
- setFailure(null);
45
- } catch (error) {
46
- setFailure(error instanceof Error ? error.message : String(error));
47
- } finally {
48
- setSaving(false);
49
- }
43
+ // What the last copy came to only describes the choices it was made with.
44
+ function changed<T>(apply: (value: T) => void): (value: T) => void {
45
+ return (value) => {
46
+ clear();
47
+ apply(value);
48
+ };
50
49
  }
51
50
 
52
51
  return (
@@ -57,11 +56,13 @@ export function Molecule3DExport(props: Molecule3DExportProps): ReactElement {
57
56
  scales={FIGURE_SCALES}
58
57
  size={size}
59
58
  failure={failure}
60
- saving={saving}
59
+ notice={notice}
60
+ saving={busy}
61
61
  rasterSvg
62
- onFormatChange={setFormat}
63
- onScaleChange={setScale}
64
- onSave={() => void save()}
62
+ onFormatChange={changed(setFormat)}
63
+ onScaleChange={changed(setScale)}
64
+ onSave={() => run(onExport(format, scale).then(() => null))}
65
+ onCopy={() => run(onCopy(scale))}
65
66
  />
66
67
  );
67
68
  }
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * The display options of the molecule viewer, shown in the toolbar's popover:
3
3
  * the representation, the size, and the surface's opacity, solvent probe and
4
- * colours.
4
+ * colours, with a button returning them all to the defaults.
5
5
  */
6
6
 
7
- import { SegmentedControl, Slider } from '@blueprintjs/core';
7
+ import { Button, SegmentedControl, Slider } from '@blueprintjs/core';
8
8
  import type { CSSProperties, ReactElement } from 'react';
9
9
 
10
10
  import { formatDecimal } from '../../format/core/numbers.ts';
@@ -15,6 +15,8 @@ import {
15
15
  REPRESENTATIONS,
16
16
  REPRESENTATION_LABELS,
17
17
  isRepresentationId,
18
+ resetMolecule3DSettings,
19
+ sameMolecule3DSettings,
18
20
  } from '../core/settings.ts';
19
21
 
20
22
  import { Molecule3DSurfaceColors } from './Molecule3DSurfaceColors.tsx';
@@ -25,6 +27,8 @@ export interface Molecule3DOptionsProps {
25
27
  onChange: (settings: Molecule3DSettings) => void;
26
28
  /** Topological polar surface area in Ų, or `null` when unknown. */
27
29
  polarSurfaceArea: number | null;
30
+ /** What the reset button returns to; `showSurface` is left as it is. */
31
+ defaults: Molecule3DSettings;
28
32
  }
29
33
 
30
34
  /**
@@ -33,8 +37,10 @@ export interface Molecule3DOptionsProps {
33
37
  * @returns The panel.
34
38
  */
35
39
  export function Molecule3DOptions(props: Molecule3DOptionsProps): ReactElement {
36
- const { settings, onChange, polarSurfaceArea } = props;
40
+ const { settings, onChange, polarSurfaceArea, defaults } = props;
37
41
  const t = useChromeT();
42
+ const reset = resetMolecule3DSettings(settings, defaults);
43
+ const atDefaults = sameMolecule3DSettings(settings, reset);
38
44
 
39
45
  return (
40
46
  <div style={PANEL_STYLE}>
@@ -67,6 +73,20 @@ export function Molecule3DOptions(props: Molecule3DOptionsProps): ReactElement {
67
73
  onChange({ ...settings, sizeFactor });
68
74
  }}
69
75
  />
76
+ {settings.showSurface ? null : (
77
+ <span style={SURFACE_OFF_STYLE} data-testid="molecule3d-surface-off">
78
+ {t('molecule3d.surfaceOff')}
79
+ <Button
80
+ variant="minimal"
81
+ size="small"
82
+ intent="primary"
83
+ text={t('molecule3d.showSurface')}
84
+ onClick={() => {
85
+ onChange({ ...settings, showSurface: true });
86
+ }}
87
+ />
88
+ </span>
89
+ )}
70
90
  <SliderRow
71
91
  label={t('molecule3d.surfaceOpacity')}
72
92
  range={MOLECULE_3D_RANGES.surfaceAlpha}
@@ -96,6 +116,22 @@ export function Molecule3DOptions(props: Molecule3DOptionsProps): ReactElement {
96
116
  onChange={onChange}
97
117
  polarSurfaceArea={polarSurfaceArea}
98
118
  />
119
+ <span style={FOOTER_STYLE}>
120
+ {/* A disabled button fires no hover, so the wrapper carries the why. */}
121
+ <span title={atDefaults ? t('molecule3d.atDefaults') : undefined}>
122
+ <Button
123
+ variant="minimal"
124
+ size="small"
125
+ icon="reset"
126
+ text={t('molecule3d.resetSettings')}
127
+ disabled={atDefaults}
128
+ data-testid="molecule3d-reset-settings"
129
+ onClick={() => {
130
+ onChange(reset);
131
+ }}
132
+ />
133
+ </span>
134
+ </span>
99
135
  </div>
100
136
  );
101
137
  }
@@ -158,6 +194,18 @@ const GRID_STYLE: CSSProperties = {
158
194
 
159
195
  const LABEL_STYLE: CSSProperties = { fontSize: 12 };
160
196
 
197
+ /** Spans the grid, between the size and the surface rows it explains. */
198
+ const SURFACE_OFF_STYLE: CSSProperties = {
199
+ display: 'flex',
200
+ gridColumn: '1 / -1',
201
+ alignItems: 'center',
202
+ justifyContent: 'space-between',
203
+ color: 'var(--text-muted)',
204
+ fontSize: 12,
205
+ };
206
+
207
+ const FOOTER_STYLE: CSSProperties = { display: 'flex', justifyContent: 'end' };
208
+
161
209
  /** Room on both sides, so the handle is never clipped at either end. */
162
210
  const SLIDER_STYLE: CSSProperties = { display: 'block', paddingInline: 8 };
163
211
 
@@ -60,9 +60,12 @@ export function MoleculeCanvas3D(props: MoleculeCanvas3DProps): ReactElement {
60
60
  onFailureChange,
61
61
  } = props;
62
62
  const tools = resolveMolecule3DTools(toolsProp);
63
+ const [initialSettings] = useState(() =>
64
+ normalizeMolecule3DSettings(defaultSettings),
65
+ );
63
66
  const [settings, setSettings] = useControlledState(
64
67
  settingsProp,
65
- () => normalizeMolecule3DSettings(defaultSettings),
68
+ initialSettings,
66
69
  onSettingsChange,
67
70
  );
68
71
  const [spinning, setSpinning] = useControlledState(
@@ -140,7 +143,7 @@ export function MoleculeCanvas3D(props: MoleculeCanvas3DProps): ReactElement {
140
143
  camera: props,
141
144
  });
142
145
 
143
- const { canvasSize, exportImage } = useImageExport(
146
+ const { canvasSize, exportImage, copyImage } = useImageExport(
144
147
  container,
145
148
  viewerRef,
146
149
  fileName,
@@ -171,10 +174,15 @@ export function MoleculeCanvas3D(props: MoleculeCanvas3DProps): ReactElement {
171
174
  settings={settings}
172
175
  onChange={setSettings}
173
176
  polarSurfaceArea={polarSurfaceArea}
177
+ defaults={initialSettings}
174
178
  />
175
179
  }
176
180
  exportPanel={
177
- <Molecule3DExport getSize={canvasSize} onExport={exportImage} />
181
+ <Molecule3DExport
182
+ getSize={canvasSize}
183
+ onExport={exportImage}
184
+ onCopy={copyImage}
185
+ />
178
186
  }
179
187
  />
180
188
  </div>
@@ -24,6 +24,26 @@ export interface MoleculeImageRequest {
24
24
  fileName: string;
25
25
  }
26
26
 
27
+ /**
28
+ * Render the scene as a PNG, for the clipboard.
29
+ * @param viewer - The viewer holding the scene.
30
+ * @param scale - Multiple of the canvas on screen it is rendered at.
31
+ * @param size - Size of the canvas on screen, CSS pixels.
32
+ * @returns The PNG.
33
+ * @throws {Error} When the viewer has nothing to render.
34
+ */
35
+ export async function captureMoleculePng(
36
+ viewer: SceneCapture,
37
+ scale: number,
38
+ size: ImageSize,
39
+ ): Promise<Blob> {
40
+ const dataUri = await viewer.captureImage(figurePixels(size, scale));
41
+ if (dataUri === undefined) {
42
+ throw new Error('There is no picture to copy yet.');
43
+ }
44
+ return new Blob([dataUriBytes(dataUri)], { type: FIGURE_PNG_TYPE });
45
+ }
46
+
27
47
  /**
28
48
  * Render the scene and hand it to the browser as a file.
29
49
  * @param viewer - The viewer holding the scene.
@@ -38,7 +38,8 @@ export interface MoleculeViewer3DProps {
38
38
  */
39
39
  settings?: Molecule3DSettings;
40
40
  /**
41
- * Starting settings when the component owns them.
41
+ * Starting settings when the component owns them, and what the options'
42
+ * reset button returns to either way.
42
43
  * @default DEFAULT_MOLECULE_3D_SETTINGS
43
44
  */
44
45
  defaultSettings?: Partial<Molecule3DSettings>;