react-cheminfo 0.75.0 → 0.77.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 (342) 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/copySvg.d.ts +12 -0
  19. package/lib/download/core/copySvg.d.ts.map +1 -0
  20. package/lib/download/core/copySvg.js +38 -0
  21. package/lib/download/core/copySvg.js.map +1 -0
  22. package/lib/download/core/downloadFigure.d.ts +12 -1
  23. package/lib/download/core/downloadFigure.d.ts.map +1 -1
  24. package/lib/download/core/downloadFigure.js +21 -0
  25. package/lib/download/core/downloadFigure.js.map +1 -1
  26. package/lib/download/core/figureDpi.d.ts +59 -0
  27. package/lib/download/core/figureDpi.d.ts.map +1 -0
  28. package/lib/download/core/figureDpi.js +75 -0
  29. package/lib/download/core/figureDpi.js.map +1 -0
  30. package/lib/download/core/figurePng.d.ts +4 -1
  31. package/lib/download/core/figurePng.d.ts.map +1 -1
  32. package/lib/download/core/figurePng.js +11 -2
  33. package/lib/download/core/figurePng.js.map +1 -1
  34. package/lib/download/core/index.d.ts +5 -1
  35. package/lib/download/core/index.d.ts.map +1 -1
  36. package/lib/download/core/index.js +4 -1
  37. package/lib/download/core/index.js.map +1 -1
  38. package/lib/download/core/pngDpi.d.ts +22 -0
  39. package/lib/download/core/pngDpi.d.ts.map +1 -0
  40. package/lib/download/core/pngDpi.js +79 -0
  41. package/lib/download/core/pngDpi.js.map +1 -0
  42. package/lib/download/ui/FigureDownloadPanel.d.ts +13 -0
  43. package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
  44. package/lib/download/ui/FigureDownloadPanel.js +18 -34
  45. package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
  46. package/lib/download/ui/figureDownloadHint.d.ts +5 -0
  47. package/lib/download/ui/figureDownloadHint.d.ts.map +1 -1
  48. package/lib/download/ui/figureDownloadHint.js +8 -0
  49. package/lib/download/ui/figureDownloadHint.js.map +1 -1
  50. package/lib/download/ui/figureDownloadOptions.d.ts +84 -0
  51. package/lib/download/ui/figureDownloadOptions.d.ts.map +1 -0
  52. package/lib/download/ui/figureDownloadOptions.js +2 -0
  53. package/lib/download/ui/figureDownloadOptions.js.map +1 -0
  54. package/lib/download/ui/resolutionChoices.d.ts +27 -0
  55. package/lib/download/ui/resolutionChoices.d.ts.map +1 -0
  56. package/lib/download/ui/resolutionChoices.js +48 -0
  57. package/lib/download/ui/resolutionChoices.js.map +1 -0
  58. package/lib/download/ui/useFigureActions.d.ts +4 -1
  59. package/lib/download/ui/useFigureActions.d.ts.map +1 -1
  60. package/lib/download/ui/useFigureActions.js +17 -8
  61. package/lib/download/ui/useFigureActions.js.map +1 -1
  62. package/lib/download/ui/useFigureDownload.d.ts +2 -55
  63. package/lib/download/ui/useFigureDownload.d.ts.map +1 -1
  64. package/lib/download/ui/useFigureDownload.js +45 -13
  65. package/lib/download/ui/useFigureDownload.js.map +1 -1
  66. package/lib/ecosystem/core/sites.d.ts.map +1 -1
  67. package/lib/ecosystem/core/sites.js +14 -0
  68. package/lib/ecosystem/core/sites.js.map +1 -1
  69. package/lib/ecosystem/core/types.d.ts +1 -1
  70. package/lib/ecosystem/core/types.d.ts.map +1 -1
  71. package/lib/ecosystem/ui/glyphs.d.ts.map +1 -1
  72. package/lib/ecosystem/ui/glyphs.js +3 -0
  73. package/lib/ecosystem/ui/glyphs.js.map +1 -1
  74. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  75. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  76. package/lib/ir/core/bandAssignments.d.ts.map +1 -1
  77. package/lib/ir/core/bandAssignments.js +27 -0
  78. package/lib/ir/core/bandAssignments.js.map +1 -1
  79. package/lib/ir/ui/BandRow.d.ts +4 -4
  80. package/lib/ir/ui/BandRow.d.ts.map +1 -1
  81. package/lib/ir/ui/BandRow.js +41 -14
  82. package/lib/ir/ui/BandRow.js.map +1 -1
  83. package/lib/locales/de.json +32 -1
  84. package/lib/locales/en.json +32 -1
  85. package/lib/locales/es.json +32 -1
  86. package/lib/locales/fr.json +32 -1
  87. package/lib/locales/it.json +32 -1
  88. package/lib/molecule3d/ui/Molecule3DStage.d.ts +4 -33
  89. package/lib/molecule3d/ui/Molecule3DStage.d.ts.map +1 -1
  90. package/lib/molecule3d/ui/Molecule3DStage.js +3 -37
  91. package/lib/molecule3d/ui/Molecule3DStage.js.map +1 -1
  92. package/lib/osiris/core/barGeometry.d.ts +42 -0
  93. package/lib/osiris/core/barGeometry.d.ts.map +1 -0
  94. package/lib/osiris/core/barGeometry.js +46 -0
  95. package/lib/osiris/core/barGeometry.js.map +1 -0
  96. package/lib/osiris/core/computeProperties.d.ts +42 -0
  97. package/lib/osiris/core/computeProperties.d.ts.map +1 -0
  98. package/lib/osiris/core/computeProperties.js +115 -0
  99. package/lib/osiris/core/computeProperties.js.map +1 -0
  100. package/lib/osiris/core/constants.d.ts +70 -0
  101. package/lib/osiris/core/constants.d.ts.map +1 -0
  102. package/lib/osiris/core/constants.js +99 -0
  103. package/lib/osiris/core/constants.js.map +1 -0
  104. package/lib/osiris/core/fitness.d.ts +32 -0
  105. package/lib/osiris/core/fitness.d.ts.map +1 -0
  106. package/lib/osiris/core/fitness.js +48 -0
  107. package/lib/osiris/core/fitness.js.map +1 -0
  108. package/lib/osiris/core/index.d.ts +29 -0
  109. package/lib/osiris/core/index.d.ts.map +1 -0
  110. package/lib/osiris/core/index.js +19 -0
  111. package/lib/osiris/core/index.js.map +1 -0
  112. package/lib/osiris/core/poolSize.d.ts +17 -0
  113. package/lib/osiris/core/poolSize.d.ts.map +1 -0
  114. package/lib/osiris/core/poolSize.js +22 -0
  115. package/lib/osiris/core/poolSize.js.map +1 -0
  116. package/lib/osiris/core/poolTypes.d.ts +140 -0
  117. package/lib/osiris/core/poolTypes.d.ts.map +1 -0
  118. package/lib/osiris/core/poolTypes.js +12 -0
  119. package/lib/osiris/core/poolTypes.js.map +1 -0
  120. package/lib/osiris/core/predictIdCode.d.ts +39 -0
  121. package/lib/osiris/core/predictIdCode.d.ts.map +1 -0
  122. package/lib/osiris/core/predictIdCode.js +54 -0
  123. package/lib/osiris/core/predictIdCode.js.map +1 -0
  124. package/lib/osiris/core/predictProtocol.d.ts +67 -0
  125. package/lib/osiris/core/predictProtocol.d.ts.map +1 -0
  126. package/lib/osiris/core/predictProtocol.js +29 -0
  127. package/lib/osiris/core/predictProtocol.js.map +1 -0
  128. package/lib/osiris/core/predictionPool.d.ts +23 -0
  129. package/lib/osiris/core/predictionPool.d.ts.map +1 -0
  130. package/lib/osiris/core/predictionPool.js +186 -0
  131. package/lib/osiris/core/predictionPool.js.map +1 -0
  132. package/lib/osiris/core/predictionQueue.d.ts +46 -0
  133. package/lib/osiris/core/predictionQueue.d.ts.map +1 -0
  134. package/lib/osiris/core/predictionQueue.js +57 -0
  135. package/lib/osiris/core/predictionQueue.js.map +1 -0
  136. package/lib/osiris/core/predictors.d.ts +62 -0
  137. package/lib/osiris/core/predictors.d.ts.map +1 -0
  138. package/lib/osiris/core/predictors.js +100 -0
  139. package/lib/osiris/core/predictors.js.map +1 -0
  140. package/lib/osiris/core/propertyKeys.d.ts +32 -0
  141. package/lib/osiris/core/propertyKeys.d.ts.map +1 -0
  142. package/lib/osiris/core/propertyKeys.js +44 -0
  143. package/lib/osiris/core/propertyKeys.js.map +1 -0
  144. package/lib/osiris/core/riskAppearance.d.ts +60 -0
  145. package/lib/osiris/core/riskAppearance.d.ts.map +1 -0
  146. package/lib/osiris/core/riskAppearance.js +59 -0
  147. package/lib/osiris/core/riskAppearance.js.map +1 -0
  148. package/lib/osiris/core/riskDetail.d.ts +22 -0
  149. package/lib/osiris/core/riskDetail.d.ts.map +1 -0
  150. package/lib/osiris/core/riskDetail.js +86 -0
  151. package/lib/osiris/core/riskDetail.js.map +1 -0
  152. package/lib/osiris/core/riskDetailRequest.d.ts +31 -0
  153. package/lib/osiris/core/riskDetailRequest.d.ts.map +1 -0
  154. package/lib/osiris/core/riskDetailRequest.js +49 -0
  155. package/lib/osiris/core/riskDetailRequest.js.map +1 -0
  156. package/lib/osiris/core/riskFindings.d.ts +26 -0
  157. package/lib/osiris/core/riskFindings.d.ts.map +1 -0
  158. package/lib/osiris/core/riskFindings.js +79 -0
  159. package/lib/osiris/core/riskFindings.js.map +1 -0
  160. package/lib/osiris/core/runPredictionJob.d.ts +20 -0
  161. package/lib/osiris/core/runPredictionJob.d.ts.map +1 -0
  162. package/lib/osiris/core/runPredictionJob.js +43 -0
  163. package/lib/osiris/core/runPredictionJob.js.map +1 -0
  164. package/lib/osiris/core/scales.d.ts +70 -0
  165. package/lib/osiris/core/scales.d.ts.map +1 -0
  166. package/lib/osiris/core/scales.js +185 -0
  167. package/lib/osiris/core/scales.js.map +1 -0
  168. package/lib/osiris/core/types.d.ts +91 -0
  169. package/lib/osiris/core/types.d.ts.map +1 -0
  170. package/lib/osiris/core/types.js +19 -0
  171. package/lib/osiris/core/types.js.map +1 -0
  172. package/lib/osiris/core/valuation.d.ts +28 -0
  173. package/lib/osiris/core/valuation.d.ts.map +1 -0
  174. package/lib/osiris/core/valuation.js +39 -0
  175. package/lib/osiris/core/valuation.js.map +1 -0
  176. package/lib/osiris/ui/PropertyBar.d.ts +27 -0
  177. package/lib/osiris/ui/PropertyBar.d.ts.map +1 -0
  178. package/lib/osiris/ui/PropertyBar.js +27 -0
  179. package/lib/osiris/ui/PropertyBar.js.map +1 -0
  180. package/lib/osiris/ui/PropertyPanel.d.ts +91 -0
  181. package/lib/osiris/ui/PropertyPanel.d.ts.map +1 -0
  182. package/lib/osiris/ui/PropertyPanel.js +77 -0
  183. package/lib/osiris/ui/PropertyPanel.js.map +1 -0
  184. package/lib/osiris/ui/PropertyRows.d.ts +40 -0
  185. package/lib/osiris/ui/PropertyRows.d.ts.map +1 -0
  186. package/lib/osiris/ui/PropertyRows.js +23 -0
  187. package/lib/osiris/ui/PropertyRows.js.map +1 -0
  188. package/lib/osiris/ui/RiskFindings.d.ts +43 -0
  189. package/lib/osiris/ui/RiskFindings.d.ts.map +1 -0
  190. package/lib/osiris/ui/RiskFindings.js +51 -0
  191. package/lib/osiris/ui/RiskFindings.js.map +1 -0
  192. package/lib/osiris/ui/RiskPanel.d.ts +46 -0
  193. package/lib/osiris/ui/RiskPanel.d.ts.map +1 -0
  194. package/lib/osiris/ui/RiskPanel.js +32 -0
  195. package/lib/osiris/ui/RiskPanel.js.map +1 -0
  196. package/lib/osiris/ui/RiskSquare.d.ts +51 -0
  197. package/lib/osiris/ui/RiskSquare.d.ts.map +1 -0
  198. package/lib/osiris/ui/RiskSquare.js +23 -0
  199. package/lib/osiris/ui/RiskSquare.js.map +1 -0
  200. package/lib/osiris/ui/index.d.ts +15 -0
  201. package/lib/osiris/ui/index.d.ts.map +1 -0
  202. package/lib/osiris/ui/index.js +8 -0
  203. package/lib/osiris/ui/index.js.map +1 -0
  204. package/lib/osiris/ui/usePredictions.d.ts +81 -0
  205. package/lib/osiris/ui/usePredictions.d.ts.map +1 -0
  206. package/lib/osiris/ui/usePredictions.js +102 -0
  207. package/lib/osiris/ui/usePredictions.js.map +1 -0
  208. package/lib/osiris-ui.d.ts +11 -0
  209. package/lib/osiris-ui.d.ts.map +1 -0
  210. package/lib/osiris-ui.js +11 -0
  211. package/lib/osiris-ui.js.map +1 -0
  212. package/lib/osiris.d.ts +17 -0
  213. package/lib/osiris.d.ts.map +1 -0
  214. package/lib/osiris.js +17 -0
  215. package/lib/osiris.js.map +1 -0
  216. package/lib/panel/ui/FilterInput.d.ts.map +1 -1
  217. package/lib/panel/ui/FilterInput.js +3 -1
  218. package/lib/panel/ui/FilterInput.js.map +1 -1
  219. package/lib/panel/ui/SidePanelItem.d.ts +39 -0
  220. package/lib/panel/ui/SidePanelItem.d.ts.map +1 -0
  221. package/lib/panel/ui/SidePanelItem.js +63 -0
  222. package/lib/panel/ui/SidePanelItem.js.map +1 -0
  223. package/lib/panel/ui/SidePanelStack.d.ts +11 -10
  224. package/lib/panel/ui/SidePanelStack.d.ts.map +1 -1
  225. package/lib/panel/ui/SidePanelStack.js +22 -15
  226. package/lib/panel/ui/SidePanelStack.js.map +1 -1
  227. package/lib/panel/ui/SpectrumColorSwatch.d.ts.map +1 -1
  228. package/lib/panel/ui/SpectrumColorSwatch.js +4 -2
  229. package/lib/panel/ui/SpectrumColorSwatch.js.map +1 -1
  230. package/lib/panel/ui/usePanelFolds.d.ts +35 -0
  231. package/lib/panel/ui/usePanelFolds.d.ts.map +1 -0
  232. package/lib/panel/ui/usePanelFolds.js +73 -0
  233. package/lib/panel/ui/usePanelFolds.js.map +1 -0
  234. package/lib/shared/ui/FullscreenStage.d.ts +43 -0
  235. package/lib/shared/ui/FullscreenStage.d.ts.map +1 -0
  236. package/lib/shared/ui/FullscreenStage.js +38 -0
  237. package/lib/shared/ui/FullscreenStage.js.map +1 -0
  238. package/lib/shared/ui/canFillScreen.d.ts +7 -0
  239. package/lib/shared/ui/canFillScreen.d.ts.map +1 -0
  240. package/lib/shared/ui/canFillScreen.js +9 -0
  241. package/lib/shared/ui/canFillScreen.js.map +1 -0
  242. package/lib/shared/ui/index.d.ts +3 -0
  243. package/lib/shared/ui/index.d.ts.map +1 -1
  244. package/lib/shared/ui/index.js +2 -0
  245. package/lib/shared/ui/index.js.map +1 -1
  246. package/lib/split/ui/splitPanes.d.ts +3 -3
  247. package/lib/split/ui/splitPanes.js +1 -1
  248. package/lib/structure/core/structureNotations.d.ts +8 -1
  249. package/lib/structure/core/structureNotations.d.ts.map +1 -1
  250. package/lib/structure/core/structureNotations.js +14 -8
  251. package/lib/structure/core/structureNotations.js.map +1 -1
  252. package/lib/structure/ui/CardStructure.d.ts +43 -0
  253. package/lib/structure/ui/CardStructure.d.ts.map +1 -0
  254. package/lib/structure/ui/CardStructure.js +28 -0
  255. package/lib/structure/ui/CardStructure.js.map +1 -0
  256. package/lib/structure/ui/StructureExportPanel.d.ts +8 -0
  257. package/lib/structure/ui/StructureExportPanel.d.ts.map +1 -1
  258. package/lib/structure/ui/StructureExportPanel.js +9 -4
  259. package/lib/structure/ui/StructureExportPanel.js.map +1 -1
  260. package/lib/structure/ui/StructurePicturePane.d.ts +1 -1
  261. package/lib/structure/ui/StructurePicturePane.d.ts.map +1 -1
  262. package/lib/structure/ui/StructurePicturePane.js +5 -2
  263. package/lib/structure/ui/StructurePicturePane.js.map +1 -1
  264. package/lib/structure/ui/index.d.ts +3 -0
  265. package/lib/structure/ui/index.d.ts.map +1 -1
  266. package/lib/structure/ui/index.js +1 -0
  267. package/lib/structure/ui/index.js.map +1 -1
  268. package/package.json +4 -1
  269. package/src/card/core/cardAddress.ts +39 -3
  270. package/src/card/core/cardPageUrl.ts +10 -3
  271. package/src/card/core/index.ts +7 -1
  272. package/src/credits/core/credits.ts +40 -0
  273. package/src/download/core/copySvg.ts +40 -0
  274. package/src/download/core/downloadFigure.ts +26 -1
  275. package/src/download/core/figureDpi.ts +94 -0
  276. package/src/download/core/figurePng.ts +11 -2
  277. package/src/download/core/index.ts +14 -1
  278. package/src/download/core/pngDpi.ts +84 -0
  279. package/src/download/ui/FigureDownloadPanel.tsx +41 -51
  280. package/src/download/ui/figureDownloadHint.ts +13 -0
  281. package/src/download/ui/figureDownloadOptions.ts +85 -0
  282. package/src/download/ui/resolutionChoices.ts +67 -0
  283. package/src/download/ui/useFigureActions.ts +24 -9
  284. package/src/download/ui/useFigureDownload.tsx +57 -71
  285. package/src/ecosystem/core/sites.ts +14 -0
  286. package/src/ecosystem/core/types.ts +2 -1
  287. package/src/ecosystem/ui/glyphs.tsx +20 -0
  288. package/src/ir/core/bandAssignments.ts +27 -0
  289. package/src/ir/ui/BandRow.tsx +84 -26
  290. package/src/locales/de.json +32 -1
  291. package/src/locales/en.json +32 -1
  292. package/src/locales/es.json +32 -1
  293. package/src/locales/fr.json +32 -1
  294. package/src/locales/it.json +32 -1
  295. package/src/molecule3d/ui/Molecule3DStage.tsx +4 -88
  296. package/src/osiris/core/barGeometry.ts +74 -0
  297. package/src/osiris/core/computeProperties.ts +175 -0
  298. package/src/osiris/core/constants.ts +110 -0
  299. package/src/osiris/core/fitness.ts +59 -0
  300. package/src/osiris/core/index.ts +78 -0
  301. package/src/osiris/core/poolSize.ts +24 -0
  302. package/src/osiris/core/poolTypes.ts +140 -0
  303. package/src/osiris/core/predictIdCode.ts +69 -0
  304. package/src/osiris/core/predictProtocol.ts +78 -0
  305. package/src/osiris/core/predictionPool.ts +237 -0
  306. package/src/osiris/core/predictionQueue.ts +89 -0
  307. package/src/osiris/core/predictors.ts +142 -0
  308. package/src/osiris/core/propertyKeys.ts +54 -0
  309. package/src/osiris/core/riskAppearance.ts +86 -0
  310. package/src/osiris/core/riskDetail.ts +120 -0
  311. package/src/osiris/core/riskDetailRequest.ts +64 -0
  312. package/src/osiris/core/riskFindings.ts +92 -0
  313. package/src/osiris/core/runPredictionJob.ts +49 -0
  314. package/src/osiris/core/scales.ts +236 -0
  315. package/src/osiris/core/types.ts +103 -0
  316. package/src/osiris/core/valuation.ts +44 -0
  317. package/src/osiris/ui/PropertyBar.tsx +77 -0
  318. package/src/osiris/ui/PropertyPanel.tsx +227 -0
  319. package/src/osiris/ui/PropertyRows.tsx +92 -0
  320. package/src/osiris/ui/RiskFindings.tsx +137 -0
  321. package/src/osiris/ui/RiskPanel.tsx +81 -0
  322. package/src/osiris/ui/RiskSquare.tsx +108 -0
  323. package/src/osiris/ui/index.ts +17 -0
  324. package/src/osiris/ui/usePredictions.ts +194 -0
  325. package/src/osiris-ui.ts +11 -0
  326. package/src/osiris.ts +17 -0
  327. package/src/panel/ui/FilterInput.tsx +4 -1
  328. package/src/panel/ui/SidePanelItem.tsx +162 -0
  329. package/src/panel/ui/SidePanelStack.tsx +29 -36
  330. package/src/panel/ui/SpectrumColorSwatch.tsx +5 -3
  331. package/src/panel/ui/usePanelFolds.ts +103 -0
  332. package/src/shared/ui/FullscreenStage.tsx +96 -0
  333. package/src/shared/ui/canFillScreen.ts +8 -0
  334. package/src/shared/ui/index.ts +6 -0
  335. package/src/split/ui/splitPanes.tsx +4 -4
  336. package/src/structure/core/structureNotations.ts +25 -8
  337. package/src/structure/ui/CardStructure.tsx +76 -0
  338. package/src/structure/ui/StructureExportPanel.tsx +23 -4
  339. package/src/structure/ui/StructurePicturePane.tsx +14 -1
  340. package/src/structure/ui/index.ts +6 -0
  341. package/styles/chrome.css +3 -3
  342. package/styles/osiris.css +339 -0
@@ -1,12 +1,13 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useLanguage } from "../../i18n/ui/useLanguage.js";
2
3
  import { useChromeT } from "../../i18n/ui/useT.js";
3
4
  import { OverlayAction } from "../../overlay/ui/OverlayAction.js";
4
5
  import { OverlayPanel } from "../../overlay/ui/OverlayPanel.js";
5
6
  import { OverlaySegmented } from "../../overlay/ui/OverlaySegmented.js";
6
7
  import { figureLayoutSize } from "../core/figureLayout.js";
7
- import { figurePixels, figureScaleFits, figureScaleLabel, formatFigurePixels, } from "../core/figureScale.js";
8
8
  import { FigureSizeRows } from "./FigureSizeRows.js";
9
9
  import { hintOf } from "./figureDownloadHint.js";
10
+ import { resolutionHelp, scaleChoices } from "./resolutionChoices.js";
10
11
  /**
11
12
  * The choices behind the save glyph, and the buttons that write the file and
12
13
  * copy the picture.
@@ -30,56 +31,39 @@ export function FigureDownloadPanel(props) {
30
31
  const { title, format, scale, scales, size, failure, saving } = props;
31
32
  const { onFormatChange, onScaleChange, onSave, rasterSvg = false } = props;
32
33
  const { sizing, onCopy, notice = null, children } = props;
34
+ const { unit = 'multiple', svgAtOwnSize = false } = props;
33
35
  const t = useChromeT();
36
+ const language = useLanguage();
34
37
  // What the file is drawn at: the figure on screen, or the shape picked.
35
38
  const drawn = size === null || sizing === undefined
36
39
  ? size
37
40
  : figureLayoutSize(sizing.layout, size, sizing.custom ?? size);
38
41
  const painted = format === 'png' || rasterSvg;
39
- return (_jsxs(OverlayPanel, { title: title, width: PANEL_WIDTH, hint: hintOf({ format, size: drawn, scale, failure, notice, rasterSvg }, t), actions: _jsxs(_Fragment, { children: [_jsx(OverlayAction, { text: t('download.save'), icon: "download", intent: "primary", disabled: size === null, busy: saving, onClick: onSave }), _jsx(OverlayAction, { text: t('clipboard.copy'), icon: "clipboard", disabled: size === null, busy: saving, onClick: onCopy })] }), children: [_jsx(OverlaySegmented, { label: t('download.format'), help: {
42
+ const offerResolution = format === 'png' || !svgAtOwnSize;
43
+ return (_jsxs(OverlayPanel, { title: title, width: unit === 'dpi' ? DPI_PANEL_WIDTH : PANEL_WIDTH, hint: hintOf({
44
+ format,
45
+ size: drawn,
46
+ scale,
47
+ failure,
48
+ notice,
49
+ rasterSvg,
50
+ unit,
51
+ language,
52
+ }, t), actions: _jsxs(_Fragment, { children: [_jsx(OverlayAction, { text: t('download.save'), icon: "download", intent: "primary", disabled: size === null, busy: saving, onClick: onSave }), _jsx(OverlayAction, { text: t('clipboard.copy'), icon: "clipboard", disabled: size === null, busy: saving, onClick: onCopy })] }), children: [_jsx(OverlaySegmented, { label: t('download.format'), help: {
40
53
  title: t('download.format'),
41
54
  body: t('download.formatHelp'),
42
- }, value: format, options: FORMAT_CHOICES, onChange: onFormatChange }), children, sizing === undefined ? null : (_jsx(FigureSizeRows, { sizing: sizing, size: size })), _jsx(OverlaySegmented, { label: t('download.resolution'), help: {
43
- title: t('download.resolution'),
44
- body: t('download.resolutionHelp'),
45
- example: {
46
- code: '2×',
47
- note: t('download.resolutionExample'),
48
- },
49
- }, value: String(scale), options: scaleChoices(scales, drawn, painted), onChange: (picked) => onScaleChange(Number(picked)) })] }));
55
+ }, value: format, options: FORMAT_CHOICES, onChange: onFormatChange }), children, sizing === undefined ? null : (_jsx(FigureSizeRows, { sizing: sizing, size: size })), offerResolution ? (_jsx(OverlaySegmented, { label: t('download.resolution'), help: resolutionHelp(unit, t), value: String(scale), options: scaleChoices(scales, drawn, painted, unit), onChange: (picked) => onScaleChange(Number(picked)) })) : null] }));
50
56
  }
51
57
  /**
52
58
  * Wide enough for the longest hint on one line in English, so switching
53
59
  * between PNG and SVG — whose hints differ in length — never resizes the panel.
54
60
  */
55
61
  const PANEL_WIDTH = '27em';
62
+ /** Wide enough for the four dots per inch on one row, `1200 dpi` last. */
63
+ const DPI_PANEL_WIDTH = '33em';
56
64
  /** The two files a figure can leave the page as. */
57
65
  const FORMAT_CHOICES = [
58
66
  { value: 'png', label: 'PNG' },
59
67
  { value: 'svg', label: 'SVG' },
60
68
  ];
61
- /**
62
- * The multiples offered, each saying what it would actually produce.
63
- *
64
- * One too large for the browser to paint is greyed rather than dropped, so the
65
- * reader learns the ceiling exists before they meet it as a blank file. An SVG
66
- * is not painted, so it has no such ceiling.
67
- * @param scales - The multiples the caller offers.
68
- * @param size - How big the figure is drawn for the file.
69
- * @param painted - Whether the file is painted into pixels.
70
- * @returns The choices, in the order offered.
71
- */
72
- function scaleChoices(scales, size, painted) {
73
- const choices = [];
74
- for (const scale of scales) {
75
- const pixels = size === null ? null : figurePixels(size, scale);
76
- choices.push({
77
- value: String(scale),
78
- label: figureScaleLabel(scale),
79
- title: pixels === null ? undefined : formatFigurePixels(pixels),
80
- disabled: painted && size !== null && !figureScaleFits(size, scale),
81
- });
82
- }
83
- return choices;
84
- }
85
69
  //# sourceMappingURL=FigureDownloadPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FigureDownloadPanel.js","sourceRoot":"","sources":["../../../src/download/ui/FigureDownloadPanel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FigureDownloadPanel.js","sourceRoot":"","sources":["../../../src/download/ui/FigureDownloadPanel.tsx"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ 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';
5
6
  import type { FigurePixels } from '../core/figureScale.ts';
6
7
  /** What the line at the foot of the panel is written from. */
7
8
  export interface HintState {
@@ -17,6 +18,10 @@ export interface HintState {
17
18
  notice: FigureNotice | null;
18
19
  /** Whether the SVG embeds a rendered picture. */
19
20
  rasterSvg: boolean;
21
+ /** How the resolution is offered; in dpi, the printed size is written out. */
22
+ unit: FigureResolutionUnit;
23
+ /** The language of the page, which the printed size is written in. */
24
+ language: string;
20
25
  }
21
26
  /**
22
27
  * The line at the foot of the panel: what pressing save is about to do, or
@@ -1 +1 @@
1
- {"version":3,"file":"figureDownloadHint.d.ts","sourceRoot":"","sources":["../../../src/download/ui/figureDownloadHint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,8DAA8D;AAC9D,MAAM,WAAW,SAAS;IACxB,+CAA+C;IAC/C,MAAM,EAAE,YAAY,CAAC;IACrB,gDAAgD;IAChD,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,+CAA+C;IAC/C,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,MAAM,CAmBxE"}
1
+ {"version":3,"file":"figureDownloadHint.d.ts","sourceRoot":"","sources":["../../../src/download/ui/figureDownloadHint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,8DAA8D;AAC9D,MAAM,WAAW,SAAS;IACxB,+CAA+C;IAC/C,MAAM,EAAE,YAAY,CAAC;IACrB,gDAAgD;IAChD,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,+CAA+C;IAC/C,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,IAAI,EAAE,oBAAoB,CAAC;IAC3B,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,MAAM,CA0BxE"}
@@ -1,3 +1,4 @@
1
+ import { formatFigureCentimetres } from "../core/figureDpi.js";
1
2
  import { figurePixels, formatFigurePixels } from "../core/figureScale.js";
2
3
  /**
3
4
  * The line at the foot of the panel: what pressing save is about to do, or
@@ -9,6 +10,7 @@ import { figurePixels, formatFigurePixels } from "../core/figureScale.js";
9
10
  */
10
11
  export function hintOf(state, t) {
11
12
  const { format, size, scale, failure, notice, rasterSvg } = state;
13
+ const { unit, language } = state;
12
14
  if (failure !== null)
13
15
  return failure;
14
16
  if (size === null)
@@ -26,6 +28,12 @@ export function hintOf(state, t) {
26
28
  });
27
29
  }
28
30
  const pixels = formatFigurePixels(figurePixels(size, scale));
31
+ if (unit === 'dpi') {
32
+ const printed = formatFigureCentimetres(size, language);
33
+ return format === 'svg'
34
+ ? t('download.hintSvgDpi', printed)
35
+ : t('download.hintPngDpi', { pixels, ...printed });
36
+ }
29
37
  return format === 'svg'
30
38
  ? t('download.hintSvg', { pixels })
31
39
  : t('download.hintPng', { pixels });
@@ -1 +1 @@
1
- {"version":3,"file":"figureDownloadHint.js","sourceRoot":"","sources":["../../../src/download/ui/figureDownloadHint.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAkB1E;;;;;;;GAOG;AACH,MAAM,UAAU,MAAM,CAAC,KAAgB,EAAE,CAAuB;IAC9D,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAClE,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC;IACrC,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAAC;IACjD,IAAI,MAAM,KAAK,iBAAiB;QAAE,OAAO,CAAC,CAAC,0BAA0B,CAAC,CAAC;IACvE,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,OAAO,CAAC,CAAC,qBAAqB,EAAE;YAC9B,MAAM,EAAE,kBAAkB,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;SACtD,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,KAAK,KAAK,IAAI,SAAS,EAAE,CAAC;QAClC,OAAO,CAAC,CAAC,wBAAwB,EAAE;YACjC,MAAM,EAAE,kBAAkB,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;SACtD,CAAC,CAAC;IACL,CAAC;IACD,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7D,OAAO,MAAM,KAAK,KAAK;QACrB,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,CAAC;QACnC,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AACxC,CAAC"}
1
+ {"version":3,"file":"figureDownloadHint.js","sourceRoot":"","sources":["../../../src/download/ui/figureDownloadHint.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAsB1E;;;;;;;GAOG;AACH,MAAM,UAAU,MAAM,CAAC,KAAgB,EAAE,CAAuB;IAC9D,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAClE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACjC,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC;IACrC,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAAC;IACjD,IAAI,MAAM,KAAK,iBAAiB;QAAE,OAAO,CAAC,CAAC,0BAA0B,CAAC,CAAC;IACvE,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,OAAO,CAAC,CAAC,qBAAqB,EAAE;YAC9B,MAAM,EAAE,kBAAkB,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;SACtD,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,KAAK,KAAK,IAAI,SAAS,EAAE,CAAC;QAClC,OAAO,CAAC,CAAC,wBAAwB,EAAE;YACjC,MAAM,EAAE,kBAAkB,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;SACtD,CAAC,CAAC;IACL,CAAC;IACD,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7D,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACxD,OAAO,MAAM,KAAK,KAAK;YACrB,CAAC,CAAC,CAAC,CAAC,qBAAqB,EAAE,OAAO,CAAC;YACnC,CAAC,CAAC,CAAC,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,MAAM,KAAK,KAAK;QACrB,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,CAAC;QACnC,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,84 @@
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
+ import type { FigureRenderer } from './useFigureRedraw.tsx';
5
+ /** What the "Save figure" panel is set up with. */
6
+ export interface FigureDownloadOptions {
7
+ /**
8
+ * The `id` of the box the figure is mounted in. Everything drawn inside it
9
+ * is saved — sixteen charts of a pair grid as readily as one scatter plot —
10
+ * and the controls floating over it are left behind. Give this or
11
+ * `writeFigure`.
12
+ * @default undefined
13
+ */
14
+ targetId?: string;
15
+ /**
16
+ * Writes the figure as an SVG document, in place of reading it off the
17
+ * page: for a drawing whose file carries more than its picture, such as the
18
+ * chemistry behind a structure. It is called when the panel opens, to
19
+ * measure the figure, and again for every save and copy. The SVG is saved as
20
+ * written, at the size it states; the resolution paints the PNG alone.
21
+ * @default undefined
22
+ */
23
+ writeFigure?: () => Promise<FigureSvg>;
24
+ /**
25
+ * What the saved file is called, without its extension. Name it after the
26
+ * data rather than after the tool: a reader with four of these in a
27
+ * downloads folder cannot tell four `figure.png` apart.
28
+ * @default 'figure'
29
+ */
30
+ fileName?: string;
31
+ /**
32
+ * The format it opens on.
33
+ * @default 'png'
34
+ */
35
+ defaultFormat?: FigureFormat;
36
+ /**
37
+ * How the resolution is offered: as multiples of the figure on screen, or —
38
+ * for a figure drawn to the size it prints at — in dots per inch. In dots
39
+ * per inch an SVG keeps the size it states, and 1× is 96 dpi.
40
+ * @default 'multiple'
41
+ */
42
+ unit?: FigureResolutionUnit;
43
+ /**
44
+ * The resolution a PNG opens on, as a multiple of the figure on screen:
45
+ * `dpiScale(600)` opens on 600 dpi. An SVG opens at 1×, the size it has on
46
+ * screen, and each format keeps the multiple the reader last picked for it.
47
+ * @default 2, or 300 dpi
48
+ */
49
+ defaultScale?: number;
50
+ /**
51
+ * The resolutions offered, as multiples of the figure on screen.
52
+ * @default [1, 2, 3, 4], or 150, 300, 600 and 1200 dpi
53
+ */
54
+ scales?: readonly number[];
55
+ /**
56
+ * Called with the multiple a PNG is set to, for a page that keeps the
57
+ * reader's choice — to paint its own PNGs at it, or to open on it next time.
58
+ * @default undefined
59
+ */
60
+ onScaleChange?: (scale: number) => void;
61
+ /**
62
+ * What is painted under the figure. `transparent` leaves it unpainted, for a
63
+ * figure going onto a coloured slide. A written figure paints its own.
64
+ * @default the surface the figure is drawn on
65
+ */
66
+ background?: string;
67
+ /**
68
+ * What the panel is called.
69
+ * @default the chrome's own line, in the language of the page
70
+ */
71
+ title?: string;
72
+ /**
73
+ * Draws the figure at a size, for a file. When it is given the panel offers
74
+ * a size — as shown, 4:3, 16:9, a journal column, or typed — and a figure
75
+ * saved at a size other than its own is drawn again at that size, off the
76
+ * page, so its axes and labels are laid out for the new shape rather than
77
+ * stretched into it. Draw exactly what is on screen, with the same data,
78
+ * zoom and colours; only the box changes. A written figure has the size it
79
+ * states, and is offered none.
80
+ * @default undefined — the figure is saved at the size it has on screen
81
+ */
82
+ renderFigure?: FigureRenderer;
83
+ }
84
+ //# sourceMappingURL=figureDownloadOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figureDownloadOptions.d.ts","sourceRoot":"","sources":["../../../src/download/ui/figureDownloadOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,mDAAmD;AACnD,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,cAAc,CAAC;CAC/B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=figureDownloadOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figureDownloadOptions.js","sourceRoot":"","sources":["../../../src/download/ui/figureDownloadOptions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
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 type { FigurePixels } from '../core/figureScale.ts';
7
+ /**
8
+ * The resolutions offered, each saying what it would actually produce.
9
+ *
10
+ * One too large for the browser to paint is greyed rather than dropped, so the
11
+ * reader learns the ceiling exists before they meet it as a blank file. An SVG
12
+ * is not painted, so it has no such ceiling.
13
+ * @param scales - The multiples the caller offers.
14
+ * @param size - How big the figure is drawn for the file.
15
+ * @param painted - Whether the file is painted into pixels.
16
+ * @param unit - How the resolution reads.
17
+ * @returns The choices, in the order offered.
18
+ */
19
+ export declare function scaleChoices(scales: readonly number[], size: FigurePixels | null, painted: boolean, unit: FigureResolutionUnit): readonly OverlayOption[];
20
+ /**
21
+ * What the resolution means, in the unit it is offered in.
22
+ * @param unit - How the resolution reads.
23
+ * @param t - The chrome's formatter.
24
+ * @returns The help of the row.
25
+ */
26
+ export declare function resolutionHelp(unit: FigureResolutionUnit, t: Translate<ChromeKey>): HelpContent;
27
+ //# sourceMappingURL=resolutionChoices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolutionChoices.d.ts","sourceRoot":"","sources":["../../../src/download/ui/resolutionChoices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAO3D;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,IAAI,EAAE,YAAY,GAAG,IAAI,EACzB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,oBAAoB,GACzB,SAAS,aAAa,EAAE,CAY1B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,oBAAoB,EAC1B,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,GACtB,WAAW,CAab"}
@@ -0,0 +1,48 @@
1
+ import { figureResolutionLabel } from "../core/figureDpi.js";
2
+ import { figurePixels, figureScaleFits, formatFigurePixels, } from "../core/figureScale.js";
3
+ /**
4
+ * The resolutions offered, each saying what it would actually produce.
5
+ *
6
+ * One too large for the browser to paint is greyed rather than dropped, so the
7
+ * reader learns the ceiling exists before they meet it as a blank file. An SVG
8
+ * is not painted, so it has no such ceiling.
9
+ * @param scales - The multiples the caller offers.
10
+ * @param size - How big the figure is drawn for the file.
11
+ * @param painted - Whether the file is painted into pixels.
12
+ * @param unit - How the resolution reads.
13
+ * @returns The choices, in the order offered.
14
+ */
15
+ export function scaleChoices(scales, size, painted, unit) {
16
+ const choices = [];
17
+ for (const scale of scales) {
18
+ const pixels = size === null ? null : figurePixels(size, scale);
19
+ choices.push({
20
+ value: String(scale),
21
+ label: figureResolutionLabel(scale, unit),
22
+ title: pixels === null ? undefined : formatFigurePixels(pixels),
23
+ disabled: painted && size !== null && !figureScaleFits(size, scale),
24
+ });
25
+ }
26
+ return choices;
27
+ }
28
+ /**
29
+ * What the resolution means, in the unit it is offered in.
30
+ * @param unit - How the resolution reads.
31
+ * @param t - The chrome's formatter.
32
+ * @returns The help of the row.
33
+ */
34
+ export function resolutionHelp(unit, t) {
35
+ const title = t('download.resolution');
36
+ return unit === 'dpi'
37
+ ? {
38
+ title,
39
+ body: t('download.resolutionDpiHelp'),
40
+ example: { code: '300 dpi', note: t('download.resolutionDpiExample') },
41
+ }
42
+ : {
43
+ title,
44
+ body: t('download.resolutionHelp'),
45
+ example: { code: '2×', note: t('download.resolutionExample') },
46
+ };
47
+ }
48
+ //# sourceMappingURL=resolutionChoices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolutionChoices.js","sourceRoot":"","sources":["../../../src/download/ui/resolutionChoices.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAEhC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAyB,EACzB,IAAyB,EACzB,OAAgB,EAChB,IAA0B;IAE1B,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;YACpB,KAAK,EAAE,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC;YACzC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC;YAC/D,QAAQ,EAAE,OAAO,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC;SACpE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,IAA0B,EAC1B,CAAuB;IAEvB,MAAM,KAAK,GAAG,CAAC,CAAC,qBAAqB,CAAC,CAAC;IACvC,OAAO,IAAI,KAAK,KAAK;QACnB,CAAC,CAAC;YACE,KAAK;YACL,IAAI,EAAE,CAAC,CAAC,4BAA4B,CAAC;YACrC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,+BAA+B,CAAC,EAAE;SACvE;QACH,CAAC,CAAC;YACE,KAAK;YACL,IAAI,EAAE,CAAC,CAAC,yBAAyB,CAAC;YAClC,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,4BAA4B,CAAC,EAAE;SAC/D,CAAC;AACR,CAAC"}
@@ -1,11 +1,14 @@
1
1
  import type { FigureFormat } from '../core/downloadFigure.ts';
2
2
  import type { FigurePixels } from '../core/figureScale.ts';
3
+ import type { FigureSvg } from '../core/figureSvg.ts';
3
4
  import type { FigureRedraw } from './useFigureRedraw.tsx';
4
5
  import type { FigureTask } from './useFigureTask.ts';
5
6
  /** What {@link useFigureActions} works from. */
6
7
  export interface FigureActionsOptions {
7
8
  /** The `id` of the box the figure is mounted in. */
8
- targetId: string;
9
+ targetId?: string;
10
+ /** Writes the figure, in place of reading it off the page. */
11
+ writeFigure?: () => Promise<FigureSvg>;
9
12
  /** Which file save writes. */
10
13
  format: FigureFormat;
11
14
  /** The multiple of the figure on screen it is painted at. */
@@ -1 +1 @@
1
- {"version":3,"file":"useFigureActions.d.ts","sourceRoot":"","sources":["../../../src/download/ui/useFigureActions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAG9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,yDAAyD;IACzD,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;CAChC;AAED,gDAAgD;AAChD,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC;IAC5D,wDAAwD;IACxD,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CA4B7E"}
1
+ {"version":3,"file":"useFigureActions.d.ts","sourceRoot":"","sources":["../../../src/download/ui/useFigureActions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAG9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IACvC,8BAA8B;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,yDAAyD;IACzD,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;CAChC;AAED,gDAAgD;AAChD,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC;IAC5D,wDAAwD;IACxD,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAwC7E"}
@@ -1,5 +1,5 @@
1
1
  import { copyFigure } from "../core/copyFigure.js";
2
- import { downloadFigure } from "../core/downloadFigure.js";
2
+ import { downloadFigure, downloadFigureSvg } from "../core/downloadFigure.js";
3
3
  import { figurePng } from "../core/figurePng.js";
4
4
  import { figureSvg } from "../core/figureSvg.js";
5
5
  import { useFigureTask } from "./useFigureTask.js";
@@ -12,26 +12,35 @@ import { useFigureTask } from "./useFigureTask.js";
12
12
  * @returns See {@link FigureActions}.
13
13
  */
14
14
  export function useFigureActions(options) {
15
- const { targetId, format, scale, fileName, background } = options;
15
+ const { targetId, writeFigure, format, scale, fileName, background } = options;
16
16
  const { redrawAt, redraw } = options;
17
17
  const { run, busy, failure, notice, clear } = useFigureTask();
18
- function withFigure(write) {
18
+ async function withFigure(write) {
19
+ if (targetId === undefined)
20
+ throw new Error('There is no figure to save.');
19
21
  return redrawAt === null
20
22
  ? write(targetId)
21
23
  : redraw(targetId, redrawAt, write);
22
24
  }
23
25
  function save() {
26
+ if (writeFigure !== undefined) {
27
+ const written = writeFigure().then((figure) => downloadFigureSvg(figure, { format, scale, fileName }));
28
+ run(written.then(() => null));
29
+ return;
30
+ }
24
31
  const options = { format, scale, fileName, background };
25
32
  run(withFigure((box) => downloadFigure(box, options)).then(() => null));
26
33
  }
27
34
  function copy() {
28
35
  // The clipboard is written before anything is awaited, with the picture
29
36
  // still being painted: Safari only allows a write the click itself started.
30
- const png = new Promise((resolve, reject) => {
31
- withFigure(async (box) => {
32
- resolve(await figurePng(figureSvg(box, { background }), scale));
33
- }).catch(reject);
34
- });
37
+ const png = writeFigure === undefined
38
+ ? new Promise((resolve, reject) => {
39
+ withFigure(async (box) => {
40
+ resolve(await figurePng(figureSvg(box, { background }), scale));
41
+ }).catch(reject);
42
+ })
43
+ : writeFigure().then((figure) => figurePng(figure, scale));
35
44
  run(copyFigure(png));
36
45
  }
37
46
  return { save, copy, busy, failure, notice, clear };
@@ -1 +1 @@
1
- {"version":3,"file":"useFigureActions.js","sourceRoot":"","sources":["../../../src/download/ui/useFigureActions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA+BnD;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA6B;IAC5D,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAClE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACrC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,EAAE,CAAC;IAE9D,SAAS,UAAU,CAAC,KAA+C;QACjE,OAAO,QAAQ,KAAK,IAAI;YACtB,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;YACjB,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,SAAS,IAAI;QACX,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;QACxD,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,SAAS,IAAI;QACX,wEAAwE;QACxE,4EAA4E;QAC5E,MAAM,GAAG,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAChD,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;gBACvB,OAAO,CAAC,MAAM,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;YAClE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"useFigureActions.js","sourceRoot":"","sources":["../../../src/download/ui/useFigureActions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAiCnD;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA6B;IAC5D,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAClE,OAAO,CAAC;IACV,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACrC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,EAAE,CAAC;IAE9D,KAAK,UAAU,UAAU,CAAC,KAA+C;QACvE,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC3E,OAAO,QAAQ,KAAK,IAAI;YACtB,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;YACjB,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,SAAS,IAAI;QACX,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAC5C,iBAAiB,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CACvD,CAAC;YACF,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;QACxD,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,SAAS,IAAI;QACX,wEAAwE;QACxE,4EAA4E;QAC5E,MAAM,GAAG,GACP,WAAW,KAAK,SAAS;YACvB,CAAC,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACpC,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;oBACvB,OAAO,CAAC,MAAM,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBAClE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC,CAAC;YACJ,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAC/D,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACtD,CAAC"}
@@ -1,60 +1,7 @@
1
1
  import type { ReactElement, ReactNode } from 'react';
2
2
  import type { FigureFormat } from '../core/downloadFigure.ts';
3
- import type { FigureRenderer } from './useFigureRedraw.tsx';
4
- /** What the "Save figure" panel is set up with. */
5
- export interface FigureDownloadOptions {
6
- /**
7
- * The `id` of the box the figure is mounted in. Everything drawn inside it
8
- * is saved — sixteen charts of a pair grid as readily as one scatter plot —
9
- * and the controls floating over it are left behind.
10
- */
11
- targetId: string;
12
- /**
13
- * What the saved file is called, without its extension. Name it after the
14
- * data rather than after the tool: a reader with four of these in a
15
- * downloads folder cannot tell four `figure.png` apart.
16
- * @default 'figure'
17
- */
18
- fileName?: string;
19
- /**
20
- * The format it opens on.
21
- * @default 'png'
22
- */
23
- defaultFormat?: FigureFormat;
24
- /**
25
- * The resolution a PNG opens on, as a multiple of the figure on screen. An
26
- * SVG opens at 1×, the size it has on screen, and each format keeps the
27
- * multiple the reader last picked for it.
28
- * @default 2
29
- */
30
- defaultScale?: number;
31
- /**
32
- * The resolutions offered.
33
- * @default [1, 2, 3, 4]
34
- */
35
- scales?: readonly number[];
36
- /**
37
- * What is painted under the figure. `transparent` leaves it unpainted, for a
38
- * figure going onto a coloured slide.
39
- * @default the surface the figure is drawn on
40
- */
41
- background?: string;
42
- /**
43
- * What the panel is called.
44
- * @default the chrome's own line, in the language of the page
45
- */
46
- title?: string;
47
- /**
48
- * Draws the figure at a size, for a file. When it is given the panel offers
49
- * a size — as shown, 4:3, 16:9, a journal column, or typed — and a figure
50
- * saved at a size other than its own is drawn again at that size, off the
51
- * page, so its axes and labels are laid out for the new shape rather than
52
- * stretched into it. Draw exactly what is on screen, with the same data,
53
- * zoom and colours; only the box changes.
54
- * @default undefined — the figure is saved at the size it has on screen
55
- */
56
- renderFigure?: FigureRenderer;
57
- }
3
+ import type { FigureDownloadOptions } from './figureDownloadOptions.ts';
4
+ export type { FigureDownloadOptions } from './figureDownloadOptions.ts';
58
5
  /** What {@link useFigureDownload} hands back. */
59
6
  export interface FigureDownloadState {
60
7
  /** Whether the panel is showing. */
@@ -1 +1 @@
1
- {"version":3,"file":"useFigureDownload.d.ts","sourceRoot":"","sources":["../../../src/download/ui/useFigureDownload.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAa9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,mDAAmD;AACnD,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,cAAc,CAAC;CAC/B;AAED,iDAAiD;AACjD,MAAM,WAAW,mBAAmB;IAClC,oCAAoC;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,8CAA8C;IAC9C,KAAK,EAAE,YAAY,CAAC;IACpB,sDAAsD;IACtD,MAAM,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,MAAM,EAAE,SAAS,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,qBAAqB,GAC7B,mBAAmB,CAsFrB"}
1
+ {"version":3,"file":"useFigureDownload.d.ts","sourceRoot":"","sources":["../../../src/download/ui/useFigureDownload.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAiB9D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAIxE,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE,iDAAiD;AACjD,MAAM,WAAW,mBAAmB;IAClC,oCAAoC;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,8CAA8C;IAC9C,KAAK,EAAE,YAAY,CAAC;IACpB,sDAAsD;IACtD,MAAM,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,MAAM,EAAE,SAAS,CAAC;CACnB;AAKD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,qBAAqB,GAC7B,mBAAmB,CAqHrB"}
@@ -1,12 +1,15 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useCallback, useState } from 'react';
2
+ import { useCallback, useRef, useState } from 'react';
3
3
  import { useChromeT } from "../../i18n/ui/useT.js";
4
+ import { DEFAULT_FIGURE_DPI, FIGURE_DPIS, dpiScale, } from "../core/figureDpi.js";
4
5
  import { figureLayoutRedraws, figureLayoutSize } from "../core/figureLayout.js";
5
6
  import { DEFAULT_FIGURE_SCALE, FIGURE_SCALES, defaultFigureScale, } from "../core/figureScale.js";
6
7
  import { figureSize } from "../core/figureTarget.js";
7
8
  import { FigureDownloadPanel } from "./FigureDownloadPanel.js";
8
9
  import { useFigureActions } from "./useFigureActions.js";
9
10
  import { useFigureRedraw } from "./useFigureRedraw.js";
11
+ /** The dots per inch offered, as the multiples the figure is painted at. */
12
+ const DPI_SCALES = FIGURE_DPIS.map(dpiScale);
10
13
  /**
11
14
  * The "Save figure" panel — save as PNG or SVG, or copy as PNG — for a caller
12
15
  * that brings its own trigger, such as a button in an editor's toolbar.
@@ -15,9 +18,17 @@ import { useFigureRedraw } from "./useFigureRedraw.js";
15
18
  * @returns See {@link FigureDownloadState}.
16
19
  */
17
20
  export function useFigureDownload(options) {
18
- const { targetId, fileName, background, scales = FIGURE_SCALES } = options;
19
- const { defaultFormat = 'png', defaultScale = DEFAULT_FIGURE_SCALE } = options;
20
- const { title, renderFigure } = options;
21
+ const { targetId, writeFigure, fileName, background } = options;
22
+ const { unit = 'multiple', defaultFormat = 'png' } = options;
23
+ const { title, renderFigure, onScaleChange } = options;
24
+ const dpi = unit === 'dpi';
25
+ const scales = options.scales ?? (dpi ? DPI_SCALES : FIGURE_SCALES);
26
+ const defaultScale = options.defaultScale ??
27
+ (dpi ? dpiScale(DEFAULT_FIGURE_DPI) : DEFAULT_FIGURE_SCALE);
28
+ // A figure with a printed size, or one its page wrote, keeps the size its
29
+ // SVG states: the resolution is then the PNG's alone.
30
+ const svgAtOwnSize = dpi || writeFigure !== undefined;
31
+ const redraws = renderFigure !== undefined && writeFigure === undefined;
21
32
  const t = useChromeT();
22
33
  const [isOpen, setIsOpen] = useState(false);
23
34
  const [format, setFormat] = useState(defaultFormat);
@@ -25,18 +36,20 @@ export function useFigureDownload(options) {
25
36
  png: defaultScale,
26
37
  svg: defaultFigureScale('svg'),
27
38
  }));
28
- const scale = picked[format];
39
+ const scale = format === 'svg' && svgAtOwnSize ? 1 : picked[format];
29
40
  const [size, setSize] = useState(null);
41
+ const opening = useRef(0);
30
42
  const [layout, setLayout] = useState('screen');
31
43
  const [custom, setCustom] = useState(null);
32
- const { redraw, portal } = useFigureRedraw(renderFigure);
33
- const redrawAt = renderFigure !== undefined &&
44
+ const { redraw, portal } = useFigureRedraw(redraws ? renderFigure : undefined);
45
+ const redrawAt = redraws &&
34
46
  size !== null &&
35
47
  figureLayoutRedraws(layout, size, custom ?? size)
36
48
  ? figureLayoutSize(layout, size, custom ?? size)
37
49
  : null;
38
50
  const { save, copy, busy, failure, notice, clear } = useFigureActions({
39
51
  targetId,
52
+ writeFigure,
40
53
  format,
41
54
  scale,
42
55
  fileName,
@@ -52,9 +65,24 @@ export function useFigureDownload(options) {
52
65
  setIsOpen(next);
53
66
  if (!next)
54
67
  return;
55
- setSize(figureSize(targetId));
56
68
  clear();
57
- }, [targetId, clear]);
69
+ if (writeFigure === undefined) {
70
+ setSize(targetId === undefined ? null : figureSize(targetId));
71
+ return;
72
+ }
73
+ // A written figure is measured once it is written; only the last
74
+ // opening is answered.
75
+ opening.current += 1;
76
+ const ticket = opening.current;
77
+ writeFigure().then((figure) => {
78
+ if (ticket !== opening.current)
79
+ return;
80
+ setSize({ width: figure.width, height: figure.height });
81
+ }, () => {
82
+ if (ticket === opening.current)
83
+ setSize(null);
84
+ });
85
+ }, [targetId, writeFigure, clear]);
58
86
  // What the last copy came to only describes the choices it was made with.
59
87
  function changed(apply) {
60
88
  return (value) => {
@@ -62,14 +90,18 @@ export function useFigureDownload(options) {
62
90
  apply(value);
63
91
  };
64
92
  }
65
- const panel = (_jsx(FigureDownloadPanel, { title: title ?? t('download.saveFigure'), format: format, scale: scale, scales: scales, size: size, failure: failure, notice: notice, saving: busy, onFormatChange: changed(setFormat), onScaleChange: changed((next) => setPicked((current) => ({ ...current, [format]: next }))), onSave: save, onCopy: copy, sizing: renderFigure === undefined
66
- ? undefined
67
- : {
93
+ const panel = (_jsx(FigureDownloadPanel, { title: title ?? t('download.saveFigure'), format: format, scale: scale, scales: scales, unit: unit, svgAtOwnSize: svgAtOwnSize, size: size, failure: failure, notice: notice, saving: busy, onFormatChange: changed(setFormat), onScaleChange: changed((next) => {
94
+ setPicked((current) => ({ ...current, [format]: next }));
95
+ if (format === 'png')
96
+ onScaleChange?.(next);
97
+ }), onSave: save, onCopy: copy, sizing: redraws
98
+ ? {
68
99
  layout,
69
100
  custom,
70
101
  onLayoutChange: changed(setLayout),
71
102
  onCustomChange: changed(setCustom),
72
- } }));
103
+ }
104
+ : undefined }));
73
105
  return { isOpen, setOpen, panel, format, portal };
74
106
  }
75
107
  //# sourceMappingURL=useFigureDownload.js.map