react-cheminfo 0.22.0 → 0.24.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 (464) hide show
  1. package/README.md +51 -28
  2. package/lib/chrome/ui/HeaderToggle.d.ts +52 -0
  3. package/lib/chrome/ui/HeaderToggle.d.ts.map +1 -0
  4. package/lib/chrome/ui/HeaderToggle.js +31 -0
  5. package/lib/chrome/ui/HeaderToggle.js.map +1 -0
  6. package/lib/chrome/ui/index.d.ts +2 -0
  7. package/lib/chrome/ui/index.d.ts.map +1 -1
  8. package/lib/chrome/ui/index.js +1 -0
  9. package/lib/chrome/ui/index.js.map +1 -1
  10. package/lib/citation/core/gfn2Paper.d.ts +10 -0
  11. package/lib/citation/core/gfn2Paper.d.ts.map +1 -0
  12. package/lib/citation/core/gfn2Paper.js +28 -0
  13. package/lib/citation/core/gfn2Paper.js.map +1 -0
  14. package/lib/citation/core/index.d.ts +1 -0
  15. package/lib/citation/core/index.d.ts.map +1 -1
  16. package/lib/citation/core/index.js +1 -0
  17. package/lib/citation/core/index.js.map +1 -1
  18. package/lib/clipboard/ui/ClickToCopy.d.ts +8 -7
  19. package/lib/clipboard/ui/ClickToCopy.d.ts.map +1 -1
  20. package/lib/clipboard/ui/ClickToCopy.js +3 -3
  21. package/lib/clipboard/ui/ClickToCopy.js.map +1 -1
  22. package/lib/conformers.d.ts +27 -0
  23. package/lib/conformers.d.ts.map +1 -0
  24. package/lib/conformers.js +19 -0
  25. package/lib/conformers.js.map +1 -0
  26. package/lib/core.d.ts +1 -0
  27. package/lib/core.d.ts.map +1 -1
  28. package/lib/core.js +1 -0
  29. package/lib/core.js.map +1 -1
  30. package/lib/credits/core/credits.d.ts +12 -0
  31. package/lib/credits/core/credits.d.ts.map +1 -1
  32. package/lib/credits/core/credits.js +14 -0
  33. package/lib/credits/core/credits.js.map +1 -1
  34. package/lib/ecosystem/core/index.d.ts +1 -1
  35. package/lib/ecosystem/core/index.d.ts.map +1 -1
  36. package/lib/ecosystem/core/index.js.map +1 -1
  37. package/lib/ecosystem/core/sites.d.ts +11 -1
  38. package/lib/ecosystem/core/sites.d.ts.map +1 -1
  39. package/lib/ecosystem/core/sites.js +7 -2
  40. package/lib/ecosystem/core/sites.js.map +1 -1
  41. package/lib/ecosystem/ui/EcosystemLinks.d.ts.map +1 -1
  42. package/lib/ecosystem/ui/EcosystemLinks.js +3 -1
  43. package/lib/ecosystem/ui/EcosystemLinks.js.map +1 -1
  44. package/lib/ecosystem/ui/SiteTile.d.ts.map +1 -1
  45. package/lib/ecosystem/ui/SiteTile.js +3 -1
  46. package/lib/ecosystem/ui/SiteTile.js.map +1 -1
  47. package/lib/format/core/index.d.ts +1 -1
  48. package/lib/format/core/index.d.ts.map +1 -1
  49. package/lib/format/core/index.js +1 -1
  50. package/lib/format/core/index.js.map +1 -1
  51. package/lib/format/core/words.d.ts +9 -0
  52. package/lib/format/core/words.d.ts.map +1 -1
  53. package/lib/format/core/words.js +16 -0
  54. package/lib/format/core/words.js.map +1 -1
  55. package/lib/language/core/index.d.ts +3 -0
  56. package/lib/language/core/index.d.ts.map +1 -0
  57. package/lib/language/core/index.js +3 -0
  58. package/lib/language/core/index.js.map +1 -0
  59. package/lib/language/core/languageName.d.ts +8 -0
  60. package/lib/language/core/languageName.d.ts.map +1 -0
  61. package/lib/language/core/languageName.js +16 -0
  62. package/lib/language/core/languageName.js.map +1 -0
  63. package/lib/language/core/languageParam.d.ts +35 -0
  64. package/lib/language/core/languageParam.d.ts.map +1 -0
  65. package/lib/language/core/languageParam.js +67 -0
  66. package/lib/language/core/languageParam.js.map +1 -0
  67. package/lib/language/ui/SiteLanguage.d.ts +20 -0
  68. package/lib/language/ui/SiteLanguage.d.ts.map +1 -0
  69. package/lib/language/ui/SiteLanguage.js +14 -0
  70. package/lib/language/ui/SiteLanguage.js.map +1 -0
  71. package/lib/language/ui/index.d.ts +4 -0
  72. package/lib/language/ui/index.d.ts.map +1 -0
  73. package/lib/language/ui/index.js +3 -0
  74. package/lib/language/ui/index.js.map +1 -0
  75. package/lib/language/ui/siteLanguageContext.d.ts +12 -0
  76. package/lib/language/ui/siteLanguageContext.d.ts.map +1 -0
  77. package/lib/language/ui/siteLanguageContext.js +19 -0
  78. package/lib/language/ui/siteLanguageContext.js.map +1 -0
  79. package/lib/orbital/core/atomicOrbitals.d.ts +9 -1
  80. package/lib/orbital/core/atomicOrbitals.d.ts.map +1 -1
  81. package/lib/orbital/core/atomicOrbitals.js +7 -0
  82. package/lib/orbital/core/atomicOrbitals.js.map +1 -1
  83. package/lib/orbital/core/hydrogenic.d.ts +2 -1
  84. package/lib/orbital/core/hydrogenic.d.ts.map +1 -1
  85. package/lib/orbital/core/hydrogenic.js +2 -1
  86. package/lib/orbital/core/hydrogenic.js.map +1 -1
  87. package/lib/orbital/core/index.d.ts +1 -0
  88. package/lib/orbital/core/index.d.ts.map +1 -1
  89. package/lib/orbital/core/index.js +1 -0
  90. package/lib/orbital/core/index.js.map +1 -1
  91. package/lib/orbital/core/slaterEnergy.d.ts +35 -0
  92. package/lib/orbital/core/slaterEnergy.d.ts.map +1 -0
  93. package/lib/orbital/core/slaterEnergy.js +66 -0
  94. package/lib/orbital/core/slaterEnergy.js.map +1 -0
  95. package/lib/overlay/core/index.d.ts +2 -2
  96. package/lib/overlay/core/index.d.ts.map +1 -1
  97. package/lib/overlay/core/index.js +1 -1
  98. package/lib/overlay/core/index.js.map +1 -1
  99. package/lib/overlay/core/overlayMarks.d.ts +20 -5
  100. package/lib/overlay/core/overlayMarks.d.ts.map +1 -1
  101. package/lib/overlay/core/overlayMarks.js +31 -5
  102. package/lib/overlay/core/overlayMarks.js.map +1 -1
  103. package/lib/overlay/ui/OverlayLegendMark.js +5 -0
  104. package/lib/overlay/ui/OverlayLegendMark.js.map +1 -1
  105. package/lib/projection/core/index.d.ts +4 -4
  106. package/lib/projection/core/index.d.ts.map +1 -1
  107. package/lib/projection/core/index.js +2 -2
  108. package/lib/projection/core/index.js.map +1 -1
  109. package/lib/projection/core/projectionCopy.d.ts +2 -0
  110. package/lib/projection/core/projectionCopy.d.ts.map +1 -1
  111. package/lib/projection/core/projectionCopy.js +1 -0
  112. package/lib/projection/core/projectionCopy.js.map +1 -1
  113. package/lib/projection/core/projectionGroupings.d.ts +44 -0
  114. package/lib/projection/core/projectionGroupings.d.ts.map +1 -0
  115. package/lib/projection/core/projectionGroupings.js +132 -0
  116. package/lib/projection/core/projectionGroupings.js.map +1 -0
  117. package/lib/projection/core/projectionOptions.d.ts +16 -6
  118. package/lib/projection/core/projectionOptions.d.ts.map +1 -1
  119. package/lib/projection/core/projectionOptions.js +7 -1
  120. package/lib/projection/core/projectionOptions.js.map +1 -1
  121. package/lib/projection/core/projectionPanelWords.d.ts +6 -0
  122. package/lib/projection/core/projectionPanelWords.d.ts.map +1 -1
  123. package/lib/projection/core/projectionPanelWords.js +4 -0
  124. package/lib/projection/core/projectionPanelWords.js.map +1 -1
  125. package/lib/projection/core/projectionSamples.d.ts +63 -32
  126. package/lib/projection/core/projectionSamples.d.ts.map +1 -1
  127. package/lib/projection/core/projectionSamples.js +1 -80
  128. package/lib/projection/core/projectionSamples.js.map +1 -1
  129. package/lib/projection/core/projectionStrings.d.ts +2 -0
  130. package/lib/projection/core/projectionStrings.d.ts.map +1 -1
  131. package/lib/projection/core/projectionStrings.js +10 -1
  132. package/lib/projection/core/projectionStrings.js.map +1 -1
  133. package/lib/projection/core/resolveProjectionOptions.d.ts +8 -3
  134. package/lib/projection/core/resolveProjectionOptions.d.ts.map +1 -1
  135. package/lib/projection/core/resolveProjectionOptions.js +58 -5
  136. package/lib/projection/core/resolveProjectionOptions.js.map +1 -1
  137. package/lib/projection/ui/ProjectionBar.d.ts +1 -1
  138. package/lib/projection/ui/ProjectionBar.d.ts.map +1 -1
  139. package/lib/projection/ui/ProjectionBar.js +3 -1
  140. package/lib/projection/ui/ProjectionBar.js.map +1 -1
  141. package/lib/projection/ui/ProjectionGroupingPickers.d.ts +38 -0
  142. package/lib/projection/ui/ProjectionGroupingPickers.d.ts.map +1 -0
  143. package/lib/projection/ui/ProjectionGroupingPickers.js +33 -0
  144. package/lib/projection/ui/ProjectionGroupingPickers.js.map +1 -0
  145. package/lib/projection/ui/ProjectionMapControls.d.ts +6 -7
  146. package/lib/projection/ui/ProjectionMapControls.d.ts.map +1 -1
  147. package/lib/projection/ui/ProjectionMapControls.js +11 -9
  148. package/lib/projection/ui/ProjectionMapControls.js.map +1 -1
  149. package/lib/projection/ui/ProjectionMapLegend.d.ts.map +1 -1
  150. package/lib/projection/ui/ProjectionMapLegend.js +1 -1
  151. package/lib/projection/ui/ProjectionMapLegend.js.map +1 -1
  152. package/lib/projection/ui/ProjectionMapMore.d.ts +2 -2
  153. package/lib/projection/ui/ProjectionMapMore.d.ts.map +1 -1
  154. package/lib/projection/ui/ProjectionMapMore.js +7 -5
  155. package/lib/projection/ui/ProjectionMapMore.js.map +1 -1
  156. package/lib/projection/ui/ProjectionMapTab.d.ts +15 -6
  157. package/lib/projection/ui/ProjectionMapTab.d.ts.map +1 -1
  158. package/lib/projection/ui/ProjectionMapTab.js +11 -7
  159. package/lib/projection/ui/ProjectionMapTab.js.map +1 -1
  160. package/lib/projection/ui/ProjectionPairsMore.d.ts +3 -7
  161. package/lib/projection/ui/ProjectionPairsMore.d.ts.map +1 -1
  162. package/lib/projection/ui/ProjectionPairsMore.js +4 -5
  163. package/lib/projection/ui/ProjectionPairsMore.js.map +1 -1
  164. package/lib/projection/ui/ProjectionPairsTab.d.ts.map +1 -1
  165. package/lib/projection/ui/ProjectionPairsTab.js +2 -2
  166. package/lib/projection/ui/ProjectionPairsTab.js.map +1 -1
  167. package/lib/projection/ui/ProjectionPanel.d.ts +1 -1
  168. package/lib/projection/ui/ProjectionPanel.d.ts.map +1 -1
  169. package/lib/projection/ui/ProjectionPanel.js +1 -1
  170. package/lib/projection/ui/ProjectionPanel.js.map +1 -1
  171. package/lib/projection/ui/ProjectionReadout.d.ts +7 -1
  172. package/lib/projection/ui/ProjectionReadout.d.ts.map +1 -1
  173. package/lib/projection/ui/ProjectionReadout.js +19 -7
  174. package/lib/projection/ui/ProjectionReadout.js.map +1 -1
  175. package/lib/projection/ui/ProjectionSpaceControls.d.ts +3 -5
  176. package/lib/projection/ui/ProjectionSpaceControls.d.ts.map +1 -1
  177. package/lib/projection/ui/ProjectionSpaceControls.js +9 -7
  178. package/lib/projection/ui/ProjectionSpaceControls.js.map +1 -1
  179. package/lib/projection/ui/ProjectionSpaceMore.d.ts +2 -2
  180. package/lib/projection/ui/ProjectionSpaceMore.d.ts.map +1 -1
  181. package/lib/projection/ui/ProjectionSpaceMore.js +5 -4
  182. package/lib/projection/ui/ProjectionSpaceMore.js.map +1 -1
  183. package/lib/projection/ui/ProjectionSpaceTab.d.ts +11 -3
  184. package/lib/projection/ui/ProjectionSpaceTab.d.ts.map +1 -1
  185. package/lib/projection/ui/ProjectionSpaceTab.js +7 -4
  186. package/lib/projection/ui/ProjectionSpaceTab.js.map +1 -1
  187. package/lib/projection/ui/ProjectionViewer.d.ts.map +1 -1
  188. package/lib/projection/ui/ProjectionViewer.js +1 -0
  189. package/lib/projection/ui/ProjectionViewer.js.map +1 -1
  190. package/lib/projection/ui/projectionBarReadings.d.ts +4 -1
  191. package/lib/projection/ui/projectionBarReadings.d.ts.map +1 -1
  192. package/lib/projection/ui/projectionBarReadings.js +14 -4
  193. package/lib/projection/ui/projectionBarReadings.js.map +1 -1
  194. package/lib/projection/ui/projectionBarSlots.d.ts +4 -2
  195. package/lib/projection/ui/projectionBarSlots.d.ts.map +1 -1
  196. package/lib/projection/ui/projectionBarSlots.js +3 -7
  197. package/lib/projection/ui/projectionBarSlots.js.map +1 -1
  198. package/lib/projection/ui/projectionMapChoices.d.ts +31 -6
  199. package/lib/projection/ui/projectionMapChoices.d.ts.map +1 -1
  200. package/lib/projection/ui/projectionMapChoices.js +58 -9
  201. package/lib/projection/ui/projectionMapChoices.js.map +1 -1
  202. package/lib/projection/ui/projectionMapChrome.d.ts +3 -9
  203. package/lib/projection/ui/projectionMapChrome.d.ts.map +1 -1
  204. package/lib/projection/ui/projectionMapChrome.js +41 -27
  205. package/lib/projection/ui/projectionMapChrome.js.map +1 -1
  206. package/lib/projection/ui/projectionMapCorner.d.ts +25 -0
  207. package/lib/projection/ui/projectionMapCorner.d.ts.map +1 -0
  208. package/lib/projection/ui/projectionMapCorner.js +46 -0
  209. package/lib/projection/ui/projectionMapCorner.js.map +1 -0
  210. package/lib/projection/ui/projectionMapModel.d.ts +9 -18
  211. package/lib/projection/ui/projectionMapModel.d.ts.map +1 -1
  212. package/lib/projection/ui/projectionMapModel.js +14 -39
  213. package/lib/projection/ui/projectionMapModel.js.map +1 -1
  214. package/lib/projection/ui/projectionMapView.d.ts +3 -1
  215. package/lib/projection/ui/projectionMapView.d.ts.map +1 -1
  216. package/lib/projection/ui/projectionMapView.js +9 -4
  217. package/lib/projection/ui/projectionMapView.js.map +1 -1
  218. package/lib/projection/ui/projectionSelectionSentence.d.ts +10 -0
  219. package/lib/projection/ui/projectionSelectionSentence.d.ts.map +1 -0
  220. package/lib/projection/ui/projectionSelectionSentence.js +18 -0
  221. package/lib/projection/ui/projectionSelectionSentence.js.map +1 -0
  222. package/lib/projection/ui/projectionStateApi.d.ts +47 -0
  223. package/lib/projection/ui/projectionStateApi.d.ts.map +1 -0
  224. package/lib/projection/ui/projectionStateApi.js +9 -0
  225. package/lib/projection/ui/projectionStateApi.js.map +1 -0
  226. package/lib/projection/ui/projectionTabModels.js +1 -1
  227. package/lib/projection/ui/projectionTabModels.js.map +1 -1
  228. package/lib/projection/ui/useProjectionState.d.ts +1 -29
  229. package/lib/projection/ui/useProjectionState.d.ts.map +1 -1
  230. package/lib/projection/ui/useProjectionState.js +13 -5
  231. package/lib/projection/ui/useProjectionState.js.map +1 -1
  232. package/lib/scatter/core/index.d.ts +1 -0
  233. package/lib/scatter/core/index.d.ts.map +1 -1
  234. package/lib/scatter/core/index.js +1 -0
  235. package/lib/scatter/core/index.js.map +1 -1
  236. package/lib/scatter/core/pointShape.d.ts +18 -0
  237. package/lib/scatter/core/pointShape.d.ts.map +1 -0
  238. package/lib/scatter/core/pointShape.js +70 -0
  239. package/lib/scatter/core/pointShape.js.map +1 -0
  240. package/lib/scatter/ui/ScatterPlot.d.ts.map +1 -1
  241. package/lib/scatter/ui/ScatterPlot.js +3 -2
  242. package/lib/scatter/ui/ScatterPlot.js.map +1 -1
  243. package/lib/scatter/ui/ScatterPointLayer.d.ts +14 -1
  244. package/lib/scatter/ui/ScatterPointLayer.d.ts.map +1 -1
  245. package/lib/scatter/ui/ScatterPointLayer.js +15 -3
  246. package/lib/scatter/ui/ScatterPointLayer.js.map +1 -1
  247. package/lib/scatter/ui/scatterFigureProps.d.ts +13 -0
  248. package/lib/scatter/ui/scatterFigureProps.d.ts.map +1 -1
  249. package/lib/scatter/ui/scatterMarkGlyph.d.ts +2 -1
  250. package/lib/scatter/ui/scatterMarkGlyph.d.ts.map +1 -1
  251. package/lib/scatter/ui/scatterMarkGlyph.js +7 -1
  252. package/lib/scatter/ui/scatterMarkGlyph.js.map +1 -1
  253. package/lib/scatter3d/ui/ScatterCloud.d.ts.map +1 -1
  254. package/lib/scatter3d/ui/ScatterCloud.js +2 -1
  255. package/lib/scatter3d/ui/ScatterCloud.js.map +1 -1
  256. package/lib/shared/ui/MenuButton.d.ts +3 -2
  257. package/lib/shared/ui/MenuButton.d.ts.map +1 -1
  258. package/lib/shared/ui/MenuButton.js +1 -1
  259. package/lib/shared/ui/MenuButton.js.map +1 -1
  260. package/lib/structure/core/conformerMinimise.d.ts +36 -0
  261. package/lib/structure/core/conformerMinimise.d.ts.map +1 -0
  262. package/lib/structure/core/conformerMinimise.js +81 -0
  263. package/lib/structure/core/conformerMinimise.js.map +1 -0
  264. package/lib/structure/core/conformerMinimum.d.ts +62 -0
  265. package/lib/structure/core/conformerMinimum.d.ts.map +1 -0
  266. package/lib/structure/core/conformerMinimum.js +90 -0
  267. package/lib/structure/core/conformerMinimum.js.map +1 -0
  268. package/lib/structure/core/conformerOptions.d.ts +62 -0
  269. package/lib/structure/core/conformerOptions.d.ts.map +1 -0
  270. package/lib/structure/core/conformerOptions.js +83 -0
  271. package/lib/structure/core/conformerOptions.js.map +1 -0
  272. package/lib/structure/core/conformerRefine.d.ts +104 -0
  273. package/lib/structure/core/conformerRefine.d.ts.map +1 -0
  274. package/lib/structure/core/conformerRefine.js +130 -0
  275. package/lib/structure/core/conformerRefine.js.map +1 -0
  276. package/lib/structure/core/conformerRefineRank.d.ts +36 -0
  277. package/lib/structure/core/conformerRefineRank.d.ts.map +1 -0
  278. package/lib/structure/core/conformerRefineRank.js +69 -0
  279. package/lib/structure/core/conformerRefineRank.js.map +1 -0
  280. package/lib/structure/core/conformerSession.d.ts +50 -0
  281. package/lib/structure/core/conformerSession.d.ts.map +1 -0
  282. package/lib/structure/core/conformerSession.js +88 -0
  283. package/lib/structure/core/conformerSession.js.map +1 -0
  284. package/lib/structure/core/conformerShape.d.ts +36 -0
  285. package/lib/structure/core/conformerShape.d.ts.map +1 -0
  286. package/lib/structure/core/conformerShape.js +150 -0
  287. package/lib/structure/core/conformerShape.js.map +1 -0
  288. package/lib/structure/core/conformers.d.ts +107 -0
  289. package/lib/structure/core/conformers.d.ts.map +1 -0
  290. package/lib/structure/core/conformers.js +149 -0
  291. package/lib/structure/core/conformers.js.map +1 -0
  292. package/lib/structure/core/geometryRelaxer.d.ts +66 -0
  293. package/lib/structure/core/geometryRelaxer.d.ts.map +1 -0
  294. package/lib/structure/core/geometryRelaxer.js +2 -0
  295. package/lib/structure/core/geometryRelaxer.js.map +1 -0
  296. package/lib/structure/core/index.d.ts +4 -0
  297. package/lib/structure/core/index.d.ts.map +1 -1
  298. package/lib/structure/core/index.js +2 -0
  299. package/lib/structure/core/index.js.map +1 -1
  300. package/lib/structure/core/moleculeCoordinates.d.ts +31 -0
  301. package/lib/structure/core/moleculeCoordinates.d.ts.map +1 -0
  302. package/lib/structure/core/moleculeCoordinates.js +80 -0
  303. package/lib/structure/core/moleculeCoordinates.js.map +1 -0
  304. package/lib/structure/core/molfileExport.d.ts +42 -0
  305. package/lib/structure/core/molfileExport.d.ts.map +1 -0
  306. package/lib/structure/core/molfileExport.js +47 -0
  307. package/lib/structure/core/molfileExport.js.map +1 -0
  308. package/lib/structure/core/oclResources.d.ts +12 -0
  309. package/lib/structure/core/oclResources.d.ts.map +1 -0
  310. package/lib/structure/core/oclResources.js +35 -0
  311. package/lib/structure/core/oclResources.js.map +1 -0
  312. package/lib/translate/core/catalog.d.ts +61 -0
  313. package/lib/translate/core/catalog.d.ts.map +1 -0
  314. package/lib/translate/core/catalog.js +49 -0
  315. package/lib/translate/core/catalog.js.map +1 -0
  316. package/lib/translate/core/checkTranslation.d.ts +32 -0
  317. package/lib/translate/core/checkTranslation.d.ts.map +1 -0
  318. package/lib/translate/core/checkTranslation.js +98 -0
  319. package/lib/translate/core/checkTranslation.js.map +1 -0
  320. package/lib/translate/core/contribution.d.ts +88 -0
  321. package/lib/translate/core/contribution.d.ts.map +1 -0
  322. package/lib/translate/core/contribution.js +14 -0
  323. package/lib/translate/core/contribution.js.map +1 -0
  324. package/lib/translate/core/index.d.ts +19 -0
  325. package/lib/translate/core/index.d.ts.map +1 -0
  326. package/lib/translate/core/index.js +15 -0
  327. package/lib/translate/core/index.js.map +1 -0
  328. package/lib/translate/core/marker.d.ts +45 -0
  329. package/lib/translate/core/marker.d.ts.map +1 -0
  330. package/lib/translate/core/marker.js +79 -0
  331. package/lib/translate/core/marker.js.map +1 -0
  332. package/lib/translate/core/mergeMessages.d.ts +35 -0
  333. package/lib/translate/core/mergeMessages.d.ts.map +1 -0
  334. package/lib/translate/core/mergeMessages.js +69 -0
  335. package/lib/translate/core/mergeMessages.js.map +1 -0
  336. package/lib/translate/core/session.d.ts +102 -0
  337. package/lib/translate/core/session.d.ts.map +1 -0
  338. package/lib/translate/core/session.js +162 -0
  339. package/lib/translate/core/session.js.map +1 -0
  340. package/lib/translate/core/start.d.ts +70 -0
  341. package/lib/translate/core/start.d.ts.map +1 -0
  342. package/lib/translate/core/start.js +73 -0
  343. package/lib/translate/core/start.js.map +1 -0
  344. package/lib/translate/core/suggestions.d.ts +77 -0
  345. package/lib/translate/core/suggestions.d.ts.map +1 -0
  346. package/lib/translate/core/suggestions.js +143 -0
  347. package/lib/translate/core/suggestions.js.map +1 -0
  348. package/lib/translate/core/tables.d.ts +100 -0
  349. package/lib/translate/core/tables.d.ts.map +1 -0
  350. package/lib/translate/core/tables.js +51 -0
  351. package/lib/translate/core/tables.js.map +1 -0
  352. package/lib/translate.d.ts +2 -0
  353. package/lib/translate.d.ts.map +1 -0
  354. package/lib/translate.js +6 -0
  355. package/lib/translate.js.map +1 -0
  356. package/lib/ui.d.ts +1 -0
  357. package/lib/ui.d.ts.map +1 -1
  358. package/lib/ui.js +1 -0
  359. package/lib/ui.js.map +1 -1
  360. package/lib/xtb/core/xtbRelaxer.d.ts +61 -0
  361. package/lib/xtb/core/xtbRelaxer.d.ts.map +1 -0
  362. package/lib/xtb/core/xtbRelaxer.js +108 -0
  363. package/lib/xtb/core/xtbRelaxer.js.map +1 -0
  364. package/lib/xtb.d.ts +11 -0
  365. package/lib/xtb.d.ts.map +1 -0
  366. package/lib/xtb.js +10 -0
  367. package/lib/xtb.js.map +1 -0
  368. package/package.json +18 -11
  369. package/src/chrome/ui/HeaderToggle.tsx +100 -0
  370. package/src/chrome/ui/index.ts +2 -0
  371. package/src/citation/core/gfn2Paper.ts +32 -0
  372. package/src/citation/core/index.ts +1 -0
  373. package/src/clipboard/ui/ClickToCopy.tsx +8 -7
  374. package/src/conformers.ts +87 -0
  375. package/src/core.ts +1 -0
  376. package/src/credits/core/credits.ts +16 -0
  377. package/src/ecosystem/core/index.ts +1 -0
  378. package/src/ecosystem/core/sites.ts +20 -2
  379. package/src/ecosystem/ui/EcosystemLinks.tsx +3 -1
  380. package/src/ecosystem/ui/SiteTile.tsx +3 -1
  381. package/src/format/core/index.ts +1 -1
  382. package/src/format/core/words.ts +19 -0
  383. package/src/language/core/index.ts +7 -0
  384. package/src/language/core/languageName.ts +16 -0
  385. package/src/language/core/languageParam.ts +70 -0
  386. package/src/language/ui/SiteLanguage.tsx +26 -0
  387. package/src/language/ui/index.ts +3 -0
  388. package/src/language/ui/siteLanguageContext.ts +20 -0
  389. package/src/orbital/core/atomicOrbitals.ts +17 -1
  390. package/src/orbital/core/hydrogenic.ts +2 -1
  391. package/src/orbital/core/index.ts +1 -0
  392. package/src/orbital/core/slaterEnergy.ts +83 -0
  393. package/src/overlay/core/index.ts +6 -2
  394. package/src/overlay/core/overlayMarks.ts +51 -6
  395. package/src/overlay/ui/OverlayLegendMark.tsx +5 -0
  396. package/src/projection/core/index.ts +11 -3
  397. package/src/projection/core/projectionCopy.ts +3 -0
  398. package/src/projection/core/projectionGroupings.ts +174 -0
  399. package/src/projection/core/projectionOptions.ts +18 -7
  400. package/src/projection/core/projectionPanelWords.ts +10 -0
  401. package/src/projection/core/projectionSamples.ts +62 -120
  402. package/src/projection/core/projectionStrings.ts +12 -1
  403. package/src/projection/core/resolveProjectionOptions.ts +66 -4
  404. package/src/projection/ui/ProjectionBar.tsx +4 -2
  405. package/src/projection/ui/ProjectionGroupingPickers.tsx +91 -0
  406. package/src/projection/ui/ProjectionMapControls.tsx +29 -32
  407. package/src/projection/ui/ProjectionMapLegend.tsx +1 -1
  408. package/src/projection/ui/ProjectionMapMore.tsx +14 -4
  409. package/src/projection/ui/ProjectionMapTab.tsx +27 -9
  410. package/src/projection/ui/ProjectionPairsMore.tsx +12 -21
  411. package/src/projection/ui/ProjectionPairsTab.tsx +5 -2
  412. package/src/projection/ui/ProjectionPanel.tsx +7 -3
  413. package/src/projection/ui/ProjectionReadout.tsx +28 -8
  414. package/src/projection/ui/ProjectionSpaceControls.tsx +20 -27
  415. package/src/projection/ui/ProjectionSpaceMore.tsx +12 -3
  416. package/src/projection/ui/ProjectionSpaceTab.tsx +23 -6
  417. package/src/projection/ui/ProjectionViewer.tsx +1 -0
  418. package/src/projection/ui/projectionBarReadings.ts +24 -8
  419. package/src/projection/ui/projectionBarSlots.tsx +10 -9
  420. package/src/projection/ui/projectionMapChoices.ts +71 -14
  421. package/src/projection/ui/projectionMapChrome.ts +55 -30
  422. package/src/projection/ui/projectionMapCorner.ts +67 -0
  423. package/src/projection/ui/projectionMapModel.ts +20 -59
  424. package/src/projection/ui/projectionMapView.ts +15 -8
  425. package/src/projection/ui/projectionSelectionSentence.ts +22 -0
  426. package/src/projection/ui/projectionStateApi.ts +57 -0
  427. package/src/projection/ui/projectionTabModels.ts +1 -1
  428. package/src/projection/ui/useProjectionState.ts +33 -37
  429. package/src/scatter/core/index.ts +1 -0
  430. package/src/scatter/core/pointShape.ts +80 -0
  431. package/src/scatter/ui/ScatterPlot.tsx +4 -1
  432. package/src/scatter/ui/ScatterPointLayer.tsx +39 -11
  433. package/src/scatter/ui/scatterFigureProps.ts +13 -0
  434. package/src/scatter/ui/scatterMarkGlyph.tsx +9 -1
  435. package/src/scatter3d/ui/ScatterCloud.tsx +3 -0
  436. package/src/shared/ui/MenuButton.tsx +4 -3
  437. package/src/structure/core/conformerMinimise.ts +99 -0
  438. package/src/structure/core/conformerMinimum.ts +125 -0
  439. package/src/structure/core/conformerOptions.ts +125 -0
  440. package/src/structure/core/conformerRefine.ts +234 -0
  441. package/src/structure/core/conformerRefineRank.ts +89 -0
  442. package/src/structure/core/conformerSession.ts +123 -0
  443. package/src/structure/core/conformerShape.ts +181 -0
  444. package/src/structure/core/conformers.ts +282 -0
  445. package/src/structure/core/geometryRelaxer.ts +71 -0
  446. package/src/structure/core/index.ts +13 -0
  447. package/src/structure/core/moleculeCoordinates.ts +93 -0
  448. package/src/structure/core/molfileExport.ts +62 -0
  449. package/src/structure/core/oclResources.ts +41 -0
  450. package/src/translate/core/catalog.ts +83 -0
  451. package/src/translate/core/checkTranslation.ts +128 -0
  452. package/src/translate/core/contribution.ts +99 -0
  453. package/src/translate/core/index.ts +72 -0
  454. package/src/translate/core/marker.ts +85 -0
  455. package/src/translate/core/mergeMessages.ts +74 -0
  456. package/src/translate/core/session.ts +250 -0
  457. package/src/translate/core/start.ts +121 -0
  458. package/src/translate/core/suggestions.ts +211 -0
  459. package/src/translate/core/tables.ts +120 -0
  460. package/src/translate.ts +5 -0
  461. package/src/ui.ts +1 -0
  462. package/src/xtb/core/xtbRelaxer.ts +160 -0
  463. package/src/xtb.ts +16 -0
  464. package/styles/chrome.css +61 -30
@@ -8,8 +8,12 @@ import type {
8
8
  ProjectionOptionId,
9
9
  ProjectionOptions,
10
10
  } from './projectionOptions.ts';
11
- import { DEFAULT_PROJECTION_OPTIONS } from './projectionOptions.ts';
11
+ import {
12
+ DEFAULT_PROJECTION_OPTIONS,
13
+ NO_GROUPING,
14
+ } from './projectionOptions.ts';
12
15
  import type { ProjectionResult } from './projectionResult.ts';
16
+ import type { ProjectionGrouping } from './projectionSamples.ts';
13
17
  import { drawableVariablesView } from './variablesView.ts';
14
18
 
15
19
  /**
@@ -19,15 +23,20 @@ import { drawableVariablesView } from './variablesView.ts';
19
23
  * A saved option outlives the data it was made on: reload with fewer samples
20
24
  * and axis eight no longer exists. Rather than let a plot ask for a column
21
25
  * that is not there, the two axes are pulled back inside what was computed and
22
- * kept apart, the counts are held inside what exists, and a view whose data is
23
- * missing falls back to `weights`.
26
+ * kept apart, the counts are held inside what exists, a view whose data is
27
+ * missing falls back to `weights`, and the colour and the shape name groupings
28
+ * the samples actually carry.
24
29
  * @param overrides - What the caller asked for.
25
30
  * @param result - The reduced space the options will be applied to.
31
+ * @param groupings - The groupings the samples carry.
32
+ * @default undefined — the colour and the shape are left as they were asked
33
+ * for, since nothing says which groupings exist
26
34
  * @returns Every option, complete and safe.
27
35
  */
28
36
  export function resolveProjectionOptions(
29
37
  overrides: Partial<ProjectionOptions> | undefined,
30
38
  result: ProjectionResult,
39
+ groupings?: readonly ProjectionGrouping[],
31
40
  ): ProjectionOptions {
32
41
  const axisCount = result.axes.length;
33
42
  const lastAxis = Math.max(0, axisCount - 1);
@@ -36,6 +45,7 @@ export function resolveProjectionOptions(
36
45
  pick(overrides, 'yAxis'),
37
46
  axisCount,
38
47
  );
48
+ const colorBy = colourChoice(pick(overrides, 'colorBy'), groupings);
39
49
 
40
50
  return {
41
51
  xAxis,
@@ -46,7 +56,8 @@ export function resolveProjectionOptions(
46
56
  lastAxis,
47
57
  ),
48
58
  cloudGesture: pick(overrides, 'cloudGesture'),
49
- colorBy: pick(overrides, 'colorBy'),
59
+ colorBy,
60
+ shapeBy: shapeChoice(pick(overrides, 'shapeBy'), groupings, colorBy),
50
61
  ellipse: pick(overrides, 'ellipse'),
51
62
  pointRadius: atLeast(pick(overrides, 'pointRadius'), 3.5, 0),
52
63
  showGroupMeans: pick(overrides, 'showGroupMeans'),
@@ -90,6 +101,57 @@ function pick<Key extends ProjectionOptionId>(
90
101
  return value === undefined ? DEFAULT_PROJECTION_OPTIONS[key] : value;
91
102
  }
92
103
 
104
+ /**
105
+ * The grouping the colour will actually stand for.
106
+ *
107
+ * A saved choice outlives the data it was made on, so an id no grouping
108
+ * carries — or the empty string, which is how "the usual one" is asked for —
109
+ * falls to the first grouping, while `none` stays none.
110
+ * @param wanted - The id asked for.
111
+ * @param groupings - The groupings the samples carry.
112
+ * @returns A grouping's id, or `none`.
113
+ */
114
+ function colourChoice(
115
+ wanted: string,
116
+ groupings: readonly ProjectionGrouping[] | undefined,
117
+ ): string {
118
+ if (wanted === NO_GROUPING || groupings === undefined) return wanted;
119
+ const ids = groupingIds(groupings);
120
+ return ids.includes(wanted) ? wanted : (ids[0] ?? NO_GROUPING);
121
+ }
122
+
123
+ /**
124
+ * The grouping the shape will actually stand for.
125
+ *
126
+ * The usual one is the second grouping, since the first is the colour's; it is
127
+ * never read as "whichever the colour leaves free", or turning the colour off
128
+ * would suddenly give the dots shapes they did not have. Only when the colour
129
+ * has taken the second does the shape fall back to the first.
130
+ * @param wanted - The id asked for.
131
+ * @param groupings - The groupings the samples carry.
132
+ * @param colorBy - The grouping the colour already stands for.
133
+ * @returns A grouping's id, or `none`.
134
+ */
135
+ function shapeChoice(
136
+ wanted: string,
137
+ groupings: readonly ProjectionGrouping[] | undefined,
138
+ colorBy: string,
139
+ ): string {
140
+ if (wanted === NO_GROUPING || groupings === undefined) return wanted;
141
+ const ids = groupingIds(groupings);
142
+ if (wanted !== colorBy && ids.includes(wanted)) return wanted;
143
+ const [first, second] = ids;
144
+ if (second === undefined) return NO_GROUPING;
145
+ if (second !== colorBy) return second;
146
+ return first ?? NO_GROUPING;
147
+ }
148
+
149
+ function groupingIds(groupings: readonly ProjectionGrouping[]): string[] {
150
+ const ids: string[] = [];
151
+ for (const { id } of groupings) ids.push(id);
152
+ return ids;
153
+ }
154
+
93
155
  /**
94
156
  * An axis that is none of the ones already drawn.
95
157
  *
@@ -27,8 +27,8 @@ import {
27
27
  projectionFoldedCaptionStyle,
28
28
  } from './projectionBarStyles.ts';
29
29
  import type { ProjectionMapView } from './projectionMapView.ts';
30
+ import type { ProjectionStateApi } from './projectionStateApi.ts';
30
31
  import type { ProjectionModels } from './projectionTabModels.ts';
31
- import type { ProjectionStateApi } from './useProjectionState.ts';
32
32
 
33
33
  /** What {@link ProjectionBar} needs. */
34
34
  interface ProjectionBarProps {
@@ -81,7 +81,8 @@ interface ProjectionBarProps {
81
81
  export function ProjectionBar(props: ProjectionBarProps): ReactElement {
82
82
  const { state, result, copy, models, map, baseId, panelId } = props;
83
83
  const { fileName, width } = props;
84
- const { tab, tabs, options, groups, selected, setOptions, setTab } = state;
84
+ const { tab, tabs, options, groups, groupings, selected } = state;
85
+ const { setOptions, setTab } = state;
85
86
 
86
87
  // Read here rather than off the surface below, because the row the bar is
87
88
  // laid into is the surface's own parent: it has to know how tall a control
@@ -119,6 +120,7 @@ export function ProjectionBar(props: ProjectionBarProps): ReactElement {
119
120
  map,
120
121
  options,
121
122
  groups,
123
+ groupings,
122
124
  selected,
123
125
  width,
124
126
  readings,
@@ -0,0 +1,91 @@
1
+ import type { ReactElement } from 'react';
2
+
3
+ import { OverlaySegmented } from '../../overlay/ui/OverlaySegmented.tsx';
4
+ import { OverlaySelect } from '../../overlay/ui/OverlaySelect.tsx';
5
+ import type { ProjectionCopy } from '../core/projectionCopy.ts';
6
+ import type { ProjectionOptions } from '../core/projectionOptions.ts';
7
+ import type { ProjectionGrouping } from '../core/projectionSamples.ts';
8
+
9
+ import {
10
+ projectionColourChoices,
11
+ projectionColourPatch,
12
+ projectionShapeChoices,
13
+ } from './projectionMapChoices.ts';
14
+
15
+ /** What a grouping picker needs. */
16
+ interface ProjectionGroupingPickerProps {
17
+ /** What the figure is showing, already resolved against the result. */
18
+ options: ProjectionOptions;
19
+ /** Called with only the options that changed. */
20
+ onChange: (patch: Partial<ProjectionOptions>) => void;
21
+ /** The words the viewer writes. */
22
+ copy: ProjectionCopy;
23
+ /** Every grouping the samples carry. */
24
+ groupings: readonly ProjectionGrouping[];
25
+ /** What the setting is called beside the control. */
26
+ label: string;
27
+ }
28
+
29
+ /** What the shape picker needs on top of what every grouping picker takes. */
30
+ interface ProjectionShapePickerProps extends ProjectionGroupingPickerProps {
31
+ /** How many rows there are, which is what a grouping is cut over. */
32
+ rows: number;
33
+ }
34
+
35
+ /**
36
+ * What the colour stands for, as segments while the choices fit on one row
37
+ * and as a list past that.
38
+ * @param props - See {@link ProjectionGroupingPickerProps}.
39
+ * @returns The picker, greyed while the samples carry no grouping.
40
+ */
41
+ export function ProjectionColourPicker(
42
+ props: ProjectionGroupingPickerProps,
43
+ ): ReactElement {
44
+ const { options, onChange, copy, groupings, label } = props;
45
+ const choices = projectionColourChoices(groupings, copy.bar.uncoloured);
46
+ const Picker =
47
+ choices.length > MOST_SEGMENTS ? OverlaySelect : OverlaySegmented;
48
+
49
+ return (
50
+ <Picker
51
+ label={label}
52
+ help={copy.help.colorBy}
53
+ value={options.colorBy}
54
+ disabled={groupings.length === 0}
55
+ options={choices}
56
+ onChange={(colorBy: string) =>
57
+ onChange(projectionColourPatch(options, colorBy))
58
+ }
59
+ />
60
+ );
61
+ }
62
+
63
+ /**
64
+ * What the shape stands for. It is always a list, so a grouping that cannot be
65
+ * shaped keeps its name, greyed, with the reason on the pointer.
66
+ * @param props - See {@link ProjectionShapePickerProps}.
67
+ * @returns The picker, greyed while the samples carry no grouping.
68
+ */
69
+ export function ProjectionShapePicker(
70
+ props: ProjectionShapePickerProps,
71
+ ): ReactElement {
72
+ const { options, onChange, copy, groupings, label, rows } = props;
73
+
74
+ return (
75
+ <OverlaySelect
76
+ label={label}
77
+ help={copy.help.shapeBy}
78
+ value={options.shapeBy}
79
+ disabled={groupings.length === 0}
80
+ options={projectionShapeChoices(groupings, options, rows, copy)}
81
+ onChange={(shapeBy) => onChange({ shapeBy })}
82
+ />
83
+ );
84
+ }
85
+
86
+ /**
87
+ * How many choices a row of segments holds before it is written as a list: a
88
+ * segment carries a grouping's whole name, and past three they no longer fit
89
+ * the width of a panel.
90
+ */
91
+ const MOST_SEGMENTS = 3;
@@ -2,16 +2,15 @@ import type { ReactElement } from 'react';
2
2
 
3
3
  import type { OverlayTier } from '../../overlay/core/overlayTiers.ts';
4
4
  import { OverlayChip } from '../../overlay/ui/OverlayChip.tsx';
5
- import { OverlaySegmented } from '../../overlay/ui/OverlaySegmented.tsx';
6
5
  import { OverlaySelect } from '../../overlay/ui/OverlaySelect.tsx';
7
6
  import { OverlayToggle } from '../../overlay/ui/OverlayToggle.tsx';
8
7
  import { OverlayValueMenu } from '../../overlay/ui/OverlayValueMenu.tsx';
9
8
  import type { ProjectionCopy } from '../core/projectionCopy.ts';
10
- import type {
11
- ProjectionColorBy,
12
- ProjectionOptions,
13
- } from '../core/projectionOptions.ts';
9
+ import type { ProjectionOptions } from '../core/projectionOptions.ts';
10
+ import { NO_GROUPING } from '../core/projectionOptions.ts';
11
+ import type { ProjectionGrouping } from '../core/projectionSamples.ts';
14
12
 
13
+ import { ProjectionColourPicker } from './ProjectionGroupingPickers.tsx';
15
14
  import type { ProjectionReading } from './projectionBarReadings.ts';
16
15
  import { projectionChipSettings } from './projectionBarReadings.ts';
17
16
  import {
@@ -21,6 +20,7 @@ import {
21
20
  } from './projectionEllipse.ts';
22
21
  import {
23
22
  projectionColourChoices,
23
+ projectionColourPatch,
24
24
  projectionOutlineChoices,
25
25
  } from './projectionMapChoices.ts';
26
26
 
@@ -32,15 +32,13 @@ export interface ProjectionMapControlsProps {
32
32
  onChange: (patch: Partial<ProjectionOptions>) => void;
33
33
  /** The words the bar writes, already merged over the defaults. */
34
34
  copy: ProjectionCopy;
35
- /** What the set of groups is called, which is what `Colour by` offers. */
36
- groupLabel: string;
37
35
  /**
38
- * Whether the samples carry groups at all. Without them the colour and the
39
- * outlines stand for nothing, so their controls are greyed rather than
40
- * removed: a reader who cannot find a control assumes the figure has none.
41
- * @default false
36
+ * Every grouping the samples carry, which is what `Colour by` offers.
37
+ * Without one the colour and the outlines stand for nothing, so their
38
+ * controls are greyed rather than removed: a reader who cannot find a
39
+ * control assumes the figure has none.
42
40
  */
43
- hasGroups?: boolean;
41
+ groupings: readonly ProjectionGrouping[];
44
42
  /**
45
43
  * What the two settings currently read, with the figure's own colours. They
46
44
  * are built once for the bar and handed down rather than spelled again here,
@@ -88,18 +86,18 @@ export interface ProjectionMapControlsProps {
88
86
  export function ProjectionMapControls(
89
87
  props: ProjectionMapControlsProps,
90
88
  ): ReactElement {
91
- const { options, onChange, copy, groupLabel, hasGroups = false } = props;
89
+ const { options, onChange, copy, groupings } = props;
92
90
  const { readings = NO_READINGS, tier = 'full' } = props;
93
91
  const { bar, help, reason } = copy;
94
92
 
95
- const uncoloured = !hasGroups || options.colorBy === 'none';
93
+ const hasGroups = groupings.length > 0;
94
+ const uncoloured = !hasGroups || options.colorBy === NO_GROUPING;
96
95
  const settings = (
97
96
  <MapSettings
98
97
  options={options}
99
98
  onChange={onChange}
100
99
  copy={copy}
101
- groupLabel={groupLabel}
102
- hasGroups={hasGroups}
100
+ groupings={groupings}
103
101
  />
104
102
  );
105
103
 
@@ -142,7 +140,7 @@ export function ProjectionMapControls(
142
140
 
143
141
  return (
144
142
  <>
145
- <OverlayValueMenu<ProjectionColorBy>
143
+ <OverlayValueMenu
146
144
  label={help.colorBy.title}
147
145
  keyWord={bar.key.colorBy}
148
146
  showKey={tier === 'full'}
@@ -150,8 +148,10 @@ export function ProjectionMapControls(
150
148
  swatches={swatchesOf(readings)}
151
149
  disabled={!hasGroups}
152
150
  disabledReason={reason.noGroups}
153
- options={projectionColourChoices(groupLabel, bar.uncoloured)}
154
- onChange={(colorBy) => onChange({ colorBy })}
151
+ options={projectionColourChoices(groupings, bar.uncoloured)}
152
+ onChange={(colorBy) =>
153
+ onChange(projectionColourPatch(options, colorBy))
154
+ }
155
155
  />
156
156
  <OverlayValueMenu
157
157
  label={help.ellipse.title}
@@ -191,10 +191,8 @@ interface MapSettingsProps {
191
191
  onChange: (patch: Partial<ProjectionOptions>) => void;
192
192
  /** The words the panel writes. */
193
193
  copy: ProjectionCopy;
194
- /** What the set of groups is called. */
195
- groupLabel: string;
196
- /** Whether the samples carry groups at all. */
197
- hasGroups: boolean;
194
+ /** Every grouping the samples carry. */
195
+ groupings: readonly ProjectionGrouping[];
198
196
  }
199
197
 
200
198
  /**
@@ -207,24 +205,23 @@ interface MapSettingsProps {
207
205
  * @returns The captioned controls.
208
206
  */
209
207
  function MapSettings(props: MapSettingsProps): ReactElement {
210
- const { options, onChange, copy, groupLabel, hasGroups } = props;
211
- const { bar, help, outline } = copy;
208
+ const { options, onChange, copy, groupings } = props;
209
+ const { help, outline } = copy;
212
210
 
213
211
  return (
214
212
  <>
215
- <OverlaySegmented<ProjectionColorBy>
213
+ <ProjectionColourPicker
216
214
  label={help.colorBy.title}
217
- help={help.colorBy}
218
- value={options.colorBy}
219
- disabled={!hasGroups}
220
- options={projectionColourChoices(groupLabel, bar.uncoloured)}
221
- onChange={(colorBy) => onChange({ colorBy })}
215
+ options={options}
216
+ onChange={onChange}
217
+ copy={copy}
218
+ groupings={groupings}
222
219
  />
223
220
  <OverlaySelect
224
221
  label={help.ellipse.title}
225
222
  help={help.ellipse}
226
223
  value={ellipseKey(options.ellipse)}
227
- disabled={!hasGroups || options.colorBy === 'none'}
224
+ disabled={groupings.length === 0 || options.colorBy === NO_GROUPING}
228
225
  options={ellipseChoices(options.ellipse, outline)}
229
226
  onChange={(value) => onChange({ ellipse: ellipseSize(value) })}
230
227
  />
@@ -3,8 +3,8 @@ import type { ReactElement } from 'react';
3
3
  import type { OverlayLegendEntry } from '../../overlay/ui/OverlayLegend.tsx';
4
4
  import { OverlayLegend } from '../../overlay/ui/OverlayLegend.tsx';
5
5
 
6
+ import { projectionMapCorner } from './projectionMapCorner.ts';
6
7
  import type { ProjectionMapCloud } from './projectionMapModel.ts';
7
- import { projectionMapCorner } from './projectionMapModel.ts';
8
8
  import {
9
9
  PROJECTION_PLOT_AREA_STYLE,
10
10
  PROJECTION_PLOT_ROOM,
@@ -8,9 +8,11 @@ import { OverlaySegmented } from '../../overlay/ui/OverlaySegmented.tsx';
8
8
  import { OverlaySelect } from '../../overlay/ui/OverlaySelect.tsx';
9
9
  import { OverlayToggle } from '../../overlay/ui/OverlayToggle.tsx';
10
10
  import type { ScatterSelectionMode } from '../../scatter/core/scatterSelection.ts';
11
+ import { NO_GROUPING } from '../core/projectionOptions.ts';
11
12
  import type { ProjectionResult } from '../core/projectionResult.ts';
12
13
  import { PROJECTION_TAB_DEFAULTS } from '../core/projectionTabDefaults.ts';
13
14
 
15
+ import { ProjectionShapePicker } from './ProjectionGroupingPickers.tsx';
14
16
  import type { ProjectionMapControlsProps } from './ProjectionMapControls.tsx';
15
17
  import { projectionAxisChoices } from './projectionAxisChoices.ts';
16
18
  import { projectionSelectModeChoices } from './projectionWordChoices.ts';
@@ -34,8 +36,8 @@ interface ProjectionMapMoreProps extends ProjectionMapControlsProps {
34
36
  }
35
37
 
36
38
  /**
37
- * What the map keeps behind the cog: the axes, the dot size, what a drag does,
38
- * and the three buttons that act rather than change.
39
+ * What the map keeps behind the cog: the axes, the dot size and shape, what a
40
+ * drag does, and the three buttons that act rather than change.
39
41
  *
40
42
  * Five settings is where a flat list stops being scannable, so they are filed
41
43
  * under three headings — the two directions of the picture, the marks drawn in
@@ -54,13 +56,13 @@ interface ProjectionMapMoreProps extends ProjectionMapControlsProps {
54
56
  * @returns The panel behind the cog.
55
57
  */
56
58
  export function ProjectionMapMore(props: ProjectionMapMoreProps): ReactElement {
57
- const { result, options, onChange, copy, hasGroups = false } = props;
59
+ const { result, options, onChange, copy, groupings } = props;
58
60
  const { selectedCount = 0, onZoomToSelection } = props;
59
61
  const { onResetView, onClearSelection } = props;
60
62
  const { action, help, panel, reason, tab } = copy;
61
63
 
62
64
  const nothingPicked = selectedCount === 0;
63
- const uncoloured = !hasGroups || options.colorBy === 'none';
65
+ const uncoloured = groupings.length === 0 || options.colorBy === NO_GROUPING;
64
66
 
65
67
  return (
66
68
  <OverlayPanel
@@ -124,6 +126,14 @@ export function ProjectionMapMore(props: ProjectionMapMoreProps): ReactElement {
124
126
  unit="px"
125
127
  onChange={(pointRadius) => onChange({ pointRadius })}
126
128
  />
129
+ <ProjectionShapePicker
130
+ label={panel.name.shapeBy}
131
+ options={options}
132
+ onChange={onChange}
133
+ copy={copy}
134
+ groupings={groupings}
135
+ rows={result.scores.rows}
136
+ />
127
137
  <OverlayToggle
128
138
  label={panel.name.showGroupMeans}
129
139
  help={help.showGroupMeans}
@@ -7,11 +7,15 @@ import type { ScatterPointOpen } from '../../scatter/ui/scatterFigureProps.ts';
7
7
  import type { SelectionChange } from '../../scatter/ui/useScatterSelection.ts';
8
8
  import type { ProjectionCopy } from '../core/projectionCopy.ts';
9
9
  import type { ProjectionOptions } from '../core/projectionOptions.ts';
10
+ import { NO_GROUPING } from '../core/projectionOptions.ts';
10
11
  import type {
11
12
  ProjectionMarker,
12
13
  ProjectionResult,
13
14
  } from '../core/projectionResult.ts';
14
- import type { ResolvedProjectionGroups } from '../core/projectionSamples.ts';
15
+ import type {
16
+ ResolvedProjectionGroups,
17
+ ResolvedProjectionShapes,
18
+ } from '../core/projectionSamples.ts';
15
19
 
16
20
  import type { SelectionReport } from './ProjectionMapCaption.tsx';
17
21
  import { ProjectionMapCaption } from './ProjectionMapCaption.tsx';
@@ -25,14 +29,23 @@ import {
25
29
  projectionMapDomain,
26
30
  projectionMapMarkers,
27
31
  projectionScatterGroups,
32
+ projectionScatterShapes,
28
33
  } from './projectionMapModel.ts';
29
34
 
30
35
  /** What {@link ProjectionMapTab} needs. */
31
36
  interface ProjectionMapTabProps {
32
37
  /** What the run produced, whatever produced it. */
33
38
  result: ProjectionResult;
34
- /** The groups, resolved once by the viewer so every tab colours alike. */
39
+ /**
40
+ * The grouping the dots are coloured by, resolved once by the viewer so every
41
+ * tab colours alike; empty while the colour stands for nothing.
42
+ */
35
43
  groups: ResolvedProjectionGroups;
44
+ /**
45
+ * The grouping the dots are shaped by, resolved once by the viewer.
46
+ * @default null — every dot is a disc
47
+ */
48
+ shapes?: ResolvedProjectionShapes | null;
36
49
  /** What the map is showing, already resolved against `result`. */
37
50
  options: ProjectionOptions;
38
51
  /** The words the map writes, already merged over the defaults. */
@@ -44,7 +57,7 @@ interface ProjectionMapTabProps {
44
57
  * "Sample ID" setting to write beside its dot.
45
58
  * @default undefined — the setting has nothing to write and draws nothing
46
59
  */
47
- ids?: readonly string[];
60
+ names?: readonly string[];
48
61
  /** Width of the figure, in pixels. */
49
62
  width: number;
50
63
  /** Height of the figure, in pixels. */
@@ -110,9 +123,10 @@ interface ProjectionMapTabProps {
110
123
  * The map: one dot per sample, an outline per group, and a key floating in the
111
124
  * emptiest corner of the plot.
112
125
  *
113
- * Colour stands for the group and for nothing else, and a selected dot keeps
114
- * its colour and gains a ring — recolouring it would trade the answer the
115
- * reader came for against the question they have just asked. A sample the
126
+ * Colour stands for one grouping and shape, when there is a second, for that
127
+ * one, and a selected dot keeps both and gains a ring — recolouring it would
128
+ * trade the answer the reader came for against the question they have just
129
+ * asked. A sample the
116
130
  * model was built from is drawn filled and one placed into the finished model
117
131
  * afterwards is drawn hollow, because the second kind can land anywhere and
118
132
  * its landing far out is the finding rather than a fault.
@@ -125,7 +139,8 @@ interface ProjectionMapTabProps {
125
139
  */
126
140
  export function ProjectionMapTab(props: ProjectionMapTabProps): ReactElement {
127
141
  const { result, groups, options, copy, chrome, width, height } = props;
128
- const { ids, selected, viewport = null, report = null } = props;
142
+ const { names, shapes = null, selected } = props;
143
+ const { viewport = null, report = null } = props;
129
144
  const { onSelectionChange, onHoverChange, hoverCard } = props;
130
145
  const { onPointDoubleClick } = props;
131
146
  const { onViewportChange, wheelZoom, touchLasso, testId } = props;
@@ -147,7 +162,8 @@ export function ProjectionMapTab(props: ProjectionMapTabProps): ReactElement {
147
162
  [scores, yAxis],
148
163
  );
149
164
 
150
- const colored = colorBy === 'group' && groups.entries.length > 0;
165
+ const shapeList = useMemo(() => projectionScatterShapes(shapes), [shapes]);
166
+ const colored = colorBy !== NO_GROUPING && groups.entries.length > 0;
151
167
  const ellipse = colored ? outlines : null;
152
168
 
153
169
  return (
@@ -160,11 +176,13 @@ export function ProjectionMapTab(props: ProjectionMapTabProps): ReactElement {
160
176
  yAxis={{ domain: yDomain, label: projectionAxisTitle(result, yAxis) }}
161
177
  groupOf={colored ? groups.groupOf : undefined}
162
178
  groups={colored ? projectionScatterGroups(groups) : undefined}
179
+ shapeOf={shapes?.shapeOf}
180
+ shapes={shapeList}
163
181
  ellipse={ellipse}
164
182
  ellipseMinimumPoints={MINIMUM_OUTLINE_POINTS}
165
183
  showGroupMeans={colored && showGroupMeans}
166
184
  showGroupLabels={colored && showGroupLabels}
167
- pointLabels={showIds ? ids : undefined}
185
+ pointLabels={showIds ? names : undefined}
168
186
  markers={projectionMapMarkers(
169
187
  markers ?? NO_MARKERS,
170
188
  groups,
@@ -2,15 +2,12 @@ import type { ReactElement } from 'react';
2
2
 
3
3
  import { OverlayNumber } from '../../overlay/ui/OverlayNumber.tsx';
4
4
  import { OverlayPanel } from '../../overlay/ui/OverlayPanel.tsx';
5
- import { OverlaySegmented } from '../../overlay/ui/OverlaySegmented.tsx';
6
5
  import type { ProjectionCopy } from '../core/projectionCopy.ts';
7
- import type {
8
- ProjectionColorBy,
9
- ProjectionOptions,
10
- } from '../core/projectionOptions.ts';
6
+ import type { ProjectionOptions } from '../core/projectionOptions.ts';
7
+ import type { ProjectionGrouping } from '../core/projectionSamples.ts';
11
8
  import { PROJECTION_TAB_DEFAULTS } from '../core/projectionTabDefaults.ts';
12
9
 
13
- import { projectionColourChoices } from './projectionMapChoices.ts';
10
+ import { ProjectionColourPicker } from './ProjectionGroupingPickers.tsx';
14
11
  import { projectionPairsCeiling } from './projectionPairsCeiling.ts';
15
12
 
16
13
  /** What the grid keeps behind the cog is drawn from. */
@@ -21,17 +18,12 @@ interface ProjectionPairsMoreProps {
21
18
  onChange: (patch: Partial<ProjectionOptions>) => void;
22
19
  /** The words the bar writes, already merged over the defaults. */
23
20
  copy: ProjectionCopy;
24
- /** What the set of groups is called, which is what `Colour by` offers. */
25
- groupLabel: string;
21
+ /** Every grouping the samples carry, which is what `Colour by` offers. */
22
+ groupings: readonly ProjectionGrouping[];
26
23
  /** How many components the run produced, which caps the grid. */
27
24
  axisCount: number;
28
25
  /** Width of the figure, in pixels, which caps it again. */
29
26
  width: number;
30
- /**
31
- * Whether the samples carry groups at all.
32
- * @default false
33
- */
34
- hasGroups?: boolean;
35
27
  }
36
28
 
37
29
  /**
@@ -52,9 +44,9 @@ interface ProjectionPairsMoreProps {
52
44
  export function ProjectionPairsMore(
53
45
  props: ProjectionPairsMoreProps,
54
46
  ): ReactElement {
55
- const { options, onChange, copy, groupLabel, hasGroups = false } = props;
47
+ const { options, onChange, copy, groupings } = props;
56
48
  const { axisCount, width } = props;
57
- const { bar, help, panel, tab } = copy;
49
+ const { help, panel, tab } = copy;
58
50
  const ceiling = projectionPairsCeiling(axisCount, width);
59
51
 
60
52
  return (
@@ -70,13 +62,12 @@ export function ProjectionPairsMore(
70
62
  max={ceiling.max}
71
63
  onChange={(pairCount) => onChange({ pairCount })}
72
64
  />
73
- <OverlaySegmented<ProjectionColorBy>
65
+ <ProjectionColourPicker
74
66
  label={panel.name.colorBy}
75
- help={help.colorBy}
76
- value={options.colorBy}
77
- disabled={!hasGroups}
78
- options={projectionColourChoices(groupLabel, bar.uncoloured)}
79
- onChange={(colorBy) => onChange({ colorBy })}
67
+ options={options}
68
+ onChange={onChange}
69
+ copy={copy}
70
+ groupings={groupings}
80
71
  />
81
72
  <OverlayNumber
82
73
  label={panel.name.pointRadius}
@@ -11,7 +11,10 @@ import { fillCopy } from '../core/fillCopy.ts';
11
11
  import type { ProjectionCopy } from '../core/projectionCopy.ts';
12
12
  import { PROJECTION_COPY } from '../core/projectionCopy.ts';
13
13
  import type { ProjectionOptions } from '../core/projectionOptions.ts';
14
- import { DEFAULT_PROJECTION_OPTIONS } from '../core/projectionOptions.ts';
14
+ import {
15
+ DEFAULT_PROJECTION_OPTIONS,
16
+ NO_GROUPING,
17
+ } from '../core/projectionOptions.ts';
15
18
  import type { ProjectionResult } from '../core/projectionResult.ts';
16
19
  import type { ResolvedProjectionGroups } from '../core/projectionSamples.ts';
17
20
 
@@ -96,7 +99,7 @@ export function ProjectionPairsTab(
96
99
  [groups],
97
100
  );
98
101
 
99
- const colored = options.colorBy === 'group' && inks.length > 0;
102
+ const colored = options.colorBy !== NO_GROUPING && inks.length > 0;
100
103
 
101
104
  return (
102
105
  <div style={{ minHeight: height }} data-testid={testId}>
@@ -13,10 +13,10 @@ import { ProjectionSharesTab } from './ProjectionSharesTab.tsx';
13
13
  import { ProjectionSpaceTab } from './ProjectionSpaceTab.tsx';
14
14
  import { ProjectionVariablesTab } from './ProjectionVariablesTab.tsx';
15
15
  import type { ProjectionMapView } from './projectionMapView.ts';
16
+ import type { ProjectionStateApi } from './projectionStateApi.ts';
16
17
  import type { ProjectionModels } from './projectionTabModels.ts';
17
18
  import type { ProjectionVariableTrack } from './projectionVariablesModel.ts';
18
19
  import type { ProjectionSampleOpen } from './projectionViewerProps.ts';
19
- import type { ProjectionStateApi } from './useProjectionState.ts';
20
20
 
21
21
  /** What {@link ProjectionPanel} needs. */
22
22
  interface ProjectionPanelProps {
@@ -172,7 +172,8 @@ export function ProjectionPanel(props: ProjectionPanelProps): ReactElement {
172
172
  options={state.options}
173
173
  copy={copy}
174
174
  chrome={map.spaceChrome}
175
- ids={samples.ids}
175
+ shapes={state.shapes}
176
+ names={samples.labels ?? samples.ids}
176
177
  width={width}
177
178
  height={height}
178
179
  selected={state.selected}
@@ -192,6 +193,7 @@ export function ProjectionPanel(props: ProjectionPanelProps): ReactElement {
192
193
  result={result}
193
194
  samples={samples}
194
195
  groups={state.groups}
196
+ colorBy={state.options.colorBy}
195
197
  xAxis={state.options.xAxis}
196
198
  yAxis={state.options.yAxis}
197
199
  zAxis={state.options.zAxis}
@@ -212,7 +214,8 @@ export function ProjectionPanel(props: ProjectionPanelProps): ReactElement {
212
214
  options={state.options}
213
215
  copy={copy}
214
216
  chrome={map.chrome}
215
- ids={samples.ids}
217
+ shapes={state.shapes}
218
+ names={samples.labels ?? samples.ids}
216
219
  viewport={map.viewport}
217
220
  onViewportChange={map.setViewport}
218
221
  wheelZoom={wheelZoom}
@@ -231,6 +234,7 @@ export function ProjectionPanel(props: ProjectionPanelProps): ReactElement {
231
234
  result={result}
232
235
  samples={samples}
233
236
  groups={state.groups}
237
+ colorBy={state.options.colorBy}
234
238
  xAxis={state.options.xAxis}
235
239
  yAxis={state.options.yAxis}
236
240
  x={anchor.x}