matterviz 0.3.1 → 0.3.3

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 (358) hide show
  1. package/dist/EmptyState.svelte +10 -2
  2. package/dist/FilePicker.svelte +154 -96
  3. package/dist/Icon.svelte +20 -14
  4. package/dist/MillerIndexInput.svelte +27 -21
  5. package/dist/api/optimade.js +6 -6
  6. package/dist/app.css +216 -178
  7. package/dist/brillouin/BrillouinZone.svelte +299 -198
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +74 -55
  11. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte +277 -165
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  15. package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
  16. package/dist/brillouin/compute.js +11 -6
  17. package/dist/chempot-diagram/ChemPotDiagram.svelte +327 -0
  18. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
  19. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +847 -0
  20. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
  21. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +3194 -0
  22. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
  23. package/dist/chempot-diagram/ChemPotScene3D.svelte +11 -0
  24. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
  25. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  26. package/dist/chempot-diagram/async-compute.svelte.js +77 -0
  27. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  28. package/dist/chempot-diagram/chempot-worker.js +11 -0
  29. package/dist/chempot-diagram/color.d.ts +10 -0
  30. package/dist/chempot-diagram/color.js +32 -0
  31. package/dist/chempot-diagram/compute.d.ts +48 -0
  32. package/dist/chempot-diagram/compute.js +812 -0
  33. package/dist/chempot-diagram/index.d.ts +6 -0
  34. package/dist/chempot-diagram/index.js +6 -0
  35. package/dist/chempot-diagram/pointer.d.ts +16 -0
  36. package/dist/chempot-diagram/pointer.js +40 -0
  37. package/dist/chempot-diagram/temperature.d.ts +15 -0
  38. package/dist/chempot-diagram/temperature.js +36 -0
  39. package/dist/chempot-diagram/types.d.ts +86 -0
  40. package/dist/chempot-diagram/types.js +28 -0
  41. package/dist/colors/index.d.ts +3 -1
  42. package/dist/colors/index.js +9 -3
  43. package/dist/composition/BarChart.svelte +141 -77
  44. package/dist/composition/BubbleChart.svelte +107 -52
  45. package/dist/composition/Composition.svelte +100 -79
  46. package/dist/composition/Formula.svelte +108 -62
  47. package/dist/composition/FormulaFilter.svelte +973 -353
  48. package/dist/composition/FormulaFilter.svelte.d.ts +35 -1
  49. package/dist/composition/PieChart.svelte +199 -99
  50. package/dist/composition/PieChart.svelte.d.ts +1 -1
  51. package/dist/composition/format.d.ts +5 -0
  52. package/dist/composition/format.js +20 -3
  53. package/dist/composition/parse.js +14 -9
  54. package/dist/convex-hull/ConvexHull.svelte +93 -38
  55. package/dist/convex-hull/ConvexHull2D.svelte +551 -393
  56. package/dist/convex-hull/ConvexHull3D.svelte +1303 -825
  57. package/dist/convex-hull/ConvexHull4D.svelte +1012 -686
  58. package/dist/convex-hull/ConvexHullControls.svelte +115 -28
  59. package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
  60. package/dist/convex-hull/ConvexHullStats.svelte +821 -249
  61. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
  62. package/dist/convex-hull/ConvexHullTooltip.svelte +41 -16
  63. package/dist/convex-hull/GasPressureControls.svelte +104 -61
  64. package/dist/convex-hull/StructurePopup.svelte +25 -4
  65. package/dist/convex-hull/TemperatureSlider.svelte +45 -25
  66. package/dist/convex-hull/barycentric-coords.js +13 -7
  67. package/dist/convex-hull/demo-temperature.d.ts +6 -0
  68. package/dist/convex-hull/demo-temperature.js +40 -0
  69. package/dist/convex-hull/gas-thermodynamics.js +17 -12
  70. package/dist/convex-hull/helpers.d.ts +10 -1
  71. package/dist/convex-hull/helpers.js +79 -38
  72. package/dist/convex-hull/index.d.ts +1 -0
  73. package/dist/convex-hull/index.js +1 -0
  74. package/dist/convex-hull/thermodynamics.d.ts +8 -21
  75. package/dist/convex-hull/thermodynamics.js +163 -69
  76. package/dist/convex-hull/types.d.ts +12 -12
  77. package/dist/convex-hull/types.js +0 -12
  78. package/dist/coordination/CoordinationBarPlot.svelte +232 -176
  79. package/dist/element/BohrAtom.svelte +56 -13
  80. package/dist/element/ElementHeading.svelte +7 -2
  81. package/dist/element/ElementPhoto.svelte +15 -9
  82. package/dist/element/ElementStats.svelte +10 -4
  83. package/dist/element/ElementTile.svelte +137 -73
  84. package/dist/element/Nucleus.svelte +39 -11
  85. package/dist/element/data.js +2 -14
  86. package/dist/element/data.json.gz +0 -0
  87. package/dist/element/types.d.ts +1 -0
  88. package/dist/feedback/ClickFeedback.svelte +16 -5
  89. package/dist/feedback/DragOverlay.svelte +10 -2
  90. package/dist/feedback/Spinner.svelte +4 -2
  91. package/dist/feedback/StatusMessage.svelte +8 -2
  92. package/dist/fermi-surface/FermiSlice.svelte +118 -88
  93. package/dist/fermi-surface/FermiSurface.svelte +336 -239
  94. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  95. package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
  96. package/dist/fermi-surface/FermiSurfaceScene.svelte +536 -343
  97. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  98. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
  99. package/dist/fermi-surface/compute.js +16 -20
  100. package/dist/fermi-surface/parse.js +37 -33
  101. package/dist/fermi-surface/symmetry.js +2 -7
  102. package/dist/fermi-surface/types.d.ts +3 -5
  103. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1527 -0
  104. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
  105. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
  106. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +30 -0
  107. package/dist/heatmap-matrix/index.d.ts +53 -0
  108. package/dist/heatmap-matrix/index.js +100 -0
  109. package/dist/heatmap-matrix/shared.d.ts +2 -0
  110. package/dist/heatmap-matrix/shared.js +4 -0
  111. package/dist/icons.d.ts +111 -0
  112. package/dist/icons.js +158 -0
  113. package/dist/index.d.ts +5 -2
  114. package/dist/index.js +5 -2
  115. package/dist/io/decompress.js +1 -1
  116. package/dist/io/export.d.ts +3 -0
  117. package/dist/io/export.js +138 -140
  118. package/dist/io/file-drop.d.ts +7 -0
  119. package/dist/io/file-drop.js +43 -0
  120. package/dist/io/index.d.ts +2 -2
  121. package/dist/io/index.js +2 -112
  122. package/dist/io/is-binary.js +2 -3
  123. package/dist/io/types.d.ts +1 -0
  124. package/dist/io/url-drop.d.ts +2 -0
  125. package/dist/io/url-drop.js +117 -0
  126. package/dist/isosurface/Isosurface.svelte +220 -110
  127. package/dist/isosurface/IsosurfaceControls.svelte +65 -28
  128. package/dist/isosurface/parse.js +104 -56
  129. package/dist/isosurface/slice.d.ts +2 -1
  130. package/dist/isosurface/slice.js +8 -13
  131. package/dist/isosurface/types.d.ts +14 -1
  132. package/dist/isosurface/types.js +152 -5
  133. package/dist/labels.d.ts +2 -1
  134. package/dist/labels.js +12 -8
  135. package/dist/layout/FullscreenToggle.svelte +11 -2
  136. package/dist/layout/InfoCard.svelte +38 -6
  137. package/dist/layout/InfoTag.svelte +125 -94
  138. package/dist/layout/PropertyFilter.svelte +82 -37
  139. package/dist/layout/SettingsSection.svelte +85 -55
  140. package/dist/layout/SubpageGrid.svelte +82 -0
  141. package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
  142. package/dist/layout/index.d.ts +1 -0
  143. package/dist/layout/index.js +1 -0
  144. package/dist/layout/json-tree/JsonNode.svelte +266 -223
  145. package/dist/layout/json-tree/JsonTree.svelte +516 -429
  146. package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
  147. package/dist/layout/json-tree/JsonValue.svelte +281 -173
  148. package/dist/layout/json-tree/types.d.ts +10 -2
  149. package/dist/layout/json-tree/utils.d.ts +2 -0
  150. package/dist/layout/json-tree/utils.js +37 -2
  151. package/dist/marching-cubes.js +25 -2
  152. package/dist/math.d.ts +20 -17
  153. package/dist/math.js +474 -57
  154. package/dist/overlays/ContextMenu.svelte +66 -40
  155. package/dist/overlays/DraggablePane.svelte +331 -154
  156. package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
  157. package/dist/periodic-table/PeriodicTable.svelte +278 -145
  158. package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
  159. package/dist/periodic-table/PropertySelect.svelte +25 -7
  160. package/dist/periodic-table/TableInset.svelte +8 -3
  161. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +559 -267
  162. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
  163. package/dist/phase-diagram/PhaseDiagramControls.svelte +131 -51
  164. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
  165. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
  166. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
  167. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +160 -110
  168. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +8 -1
  169. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +217 -86
  170. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
  171. package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
  172. package/dist/phase-diagram/build-diagram.js +9 -9
  173. package/dist/phase-diagram/colors.js +1 -3
  174. package/dist/phase-diagram/index.d.ts +2 -0
  175. package/dist/phase-diagram/index.js +2 -0
  176. package/dist/phase-diagram/parse.js +10 -9
  177. package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
  178. package/dist/phase-diagram/svg-to-diagram.js +869 -0
  179. package/dist/phase-diagram/types.d.ts +10 -0
  180. package/dist/phase-diagram/utils.d.ts +8 -4
  181. package/dist/phase-diagram/utils.js +219 -74
  182. package/dist/plot/AxisLabel.svelte +51 -0
  183. package/dist/plot/AxisLabel.svelte.d.ts +16 -0
  184. package/dist/plot/BarPlot.svelte +1461 -768
  185. package/dist/plot/BarPlot.svelte.d.ts +3 -3
  186. package/dist/plot/BarPlotControls.svelte +33 -6
  187. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  188. package/dist/plot/ColorBar.svelte +533 -383
  189. package/dist/plot/ColorBar.svelte.d.ts +1 -1
  190. package/dist/plot/ColorScaleSelect.svelte +28 -7
  191. package/dist/plot/ElementScatter.svelte +38 -16
  192. package/dist/plot/FillArea.svelte +152 -92
  193. package/dist/plot/Histogram.svelte +1162 -709
  194. package/dist/plot/Histogram.svelte.d.ts +1 -1
  195. package/dist/plot/HistogramControls.svelte +81 -18
  196. package/dist/plot/HistogramControls.svelte.d.ts +6 -2
  197. package/dist/plot/InteractiveAxisLabel.svelte +34 -11
  198. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  199. package/dist/plot/Line.svelte +63 -28
  200. package/dist/plot/PlotControls.svelte +221 -96
  201. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  202. package/dist/plot/PlotLegend.svelte +174 -91
  203. package/dist/plot/PlotTooltip.svelte +45 -6
  204. package/dist/plot/PortalSelect.svelte +175 -146
  205. package/dist/plot/ReferenceLine.svelte +77 -22
  206. package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
  207. package/dist/plot/ReferenceLine3D.svelte +132 -107
  208. package/dist/plot/ReferencePlane.svelte +146 -123
  209. package/dist/plot/ScatterPlot.svelte +1880 -1156
  210. package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
  211. package/dist/plot/ScatterPlot3D.svelte +256 -131
  212. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  213. package/dist/plot/ScatterPlot3DControls.svelte +300 -297
  214. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
  215. package/dist/plot/ScatterPlot3DScene.svelte +608 -406
  216. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  217. package/dist/plot/ScatterPlotControls.svelte +150 -70
  218. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  219. package/dist/plot/ScatterPoint.svelte +98 -26
  220. package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
  221. package/dist/plot/SpacegroupBarPlot.svelte +142 -85
  222. package/dist/plot/Surface3D.svelte +159 -108
  223. package/dist/plot/ZeroLines.svelte +96 -0
  224. package/dist/plot/ZeroLines.svelte.d.ts +32 -0
  225. package/dist/plot/ZoomRect.svelte +23 -0
  226. package/dist/plot/ZoomRect.svelte.d.ts +8 -0
  227. package/dist/plot/axis-utils.d.ts +1 -1
  228. package/dist/plot/axis-utils.js +1 -3
  229. package/dist/plot/data-cleaning.js +12 -28
  230. package/dist/plot/data-transform.js +2 -1
  231. package/dist/plot/fill-utils.js +2 -0
  232. package/dist/plot/index.d.ts +6 -2
  233. package/dist/plot/index.js +6 -2
  234. package/dist/plot/interactions.d.ts +8 -10
  235. package/dist/plot/interactions.js +2 -3
  236. package/dist/plot/layout.d.ts +11 -2
  237. package/dist/plot/layout.js +44 -17
  238. package/dist/plot/reference-line.d.ts +5 -22
  239. package/dist/plot/reference-line.js +12 -84
  240. package/dist/plot/scales.js +24 -36
  241. package/dist/plot/types.d.ts +53 -40
  242. package/dist/plot/types.js +12 -7
  243. package/dist/plot/utils/label-placement.d.ts +32 -15
  244. package/dist/plot/utils/label-placement.js +227 -63
  245. package/dist/plot/utils/series-visibility.js +2 -3
  246. package/dist/plot/utils.d.ts +1 -0
  247. package/dist/plot/utils.js +14 -0
  248. package/dist/rdf/RdfPlot.svelte +173 -132
  249. package/dist/rdf/calc-rdf.js +4 -5
  250. package/dist/sanitize.d.ts +4 -0
  251. package/dist/sanitize.js +107 -0
  252. package/dist/settings.d.ts +21 -6
  253. package/dist/settings.js +63 -19
  254. package/dist/spectral/Bands.svelte +963 -412
  255. package/dist/spectral/Bands.svelte.d.ts +22 -2
  256. package/dist/spectral/BandsAndDos.svelte +90 -49
  257. package/dist/spectral/BrillouinBandsDos.svelte +151 -93
  258. package/dist/spectral/Dos.svelte +389 -258
  259. package/dist/spectral/helpers.d.ts +23 -1
  260. package/dist/spectral/helpers.js +119 -51
  261. package/dist/spectral/types.d.ts +2 -0
  262. package/dist/state.svelte.d.ts +1 -1
  263. package/dist/state.svelte.js +3 -2
  264. package/dist/structure/Arrow.svelte +59 -20
  265. package/dist/structure/AtomLegend.svelte +231 -129
  266. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  267. package/dist/structure/Bond.svelte +73 -47
  268. package/dist/structure/CanvasTooltip.svelte +10 -2
  269. package/dist/structure/CellSelect.svelte +148 -51
  270. package/dist/structure/Cylinder.svelte +33 -17
  271. package/dist/structure/Lattice.svelte +88 -33
  272. package/dist/structure/Structure.svelte +1077 -821
  273. package/dist/structure/Structure.svelte.d.ts +1 -1
  274. package/dist/structure/StructureControls.svelte +373 -139
  275. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  276. package/dist/structure/StructureExportPane.svelte +124 -89
  277. package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
  278. package/dist/structure/StructureInfoPane.svelte +304 -231
  279. package/dist/structure/StructureScene.svelte +919 -445
  280. package/dist/structure/StructureScene.svelte.d.ts +16 -7
  281. package/dist/structure/atom-properties.d.ts +6 -2
  282. package/dist/structure/atom-properties.js +42 -29
  283. package/dist/structure/bonding.js +6 -7
  284. package/dist/structure/export.js +22 -34
  285. package/dist/structure/ferrox-wasm-types.d.ts +3 -2
  286. package/dist/structure/ferrox-wasm-types.js +0 -3
  287. package/dist/structure/ferrox-wasm.d.ts +3 -2
  288. package/dist/structure/ferrox-wasm.js +2 -3
  289. package/dist/structure/index.d.ts +16 -0
  290. package/dist/structure/index.js +88 -6
  291. package/dist/structure/measure.d.ts +2 -2
  292. package/dist/structure/measure.js +4 -44
  293. package/dist/structure/parse.js +130 -155
  294. package/dist/structure/partial-occupancy.d.ts +25 -0
  295. package/dist/structure/partial-occupancy.js +99 -0
  296. package/dist/structure/pbc.d.ts +1 -0
  297. package/dist/structure/pbc.js +16 -6
  298. package/dist/structure/supercell.d.ts +2 -2
  299. package/dist/structure/supercell.js +12 -22
  300. package/dist/structure/validation.js +5 -3
  301. package/dist/symmetry/SymmetryStats.svelte +94 -37
  302. package/dist/symmetry/WyckoffTable.svelte +42 -14
  303. package/dist/symmetry/cell-transform.js +5 -3
  304. package/dist/symmetry/index.d.ts +7 -4
  305. package/dist/symmetry/index.js +87 -21
  306. package/dist/symmetry/spacegroups.js +148 -148
  307. package/dist/table/HeatmapTable.svelte +1112 -516
  308. package/dist/table/HeatmapTable.svelte.d.ts +12 -1
  309. package/dist/table/ToggleMenu.svelte +125 -90
  310. package/dist/table/index.d.ts +2 -0
  311. package/dist/table/index.js +2 -4
  312. package/dist/theme/ThemeControl.svelte +21 -12
  313. package/dist/time.js +4 -1
  314. package/dist/tooltip/TooltipContent.svelte +33 -8
  315. package/dist/trajectory/Trajectory.svelte +889 -687
  316. package/dist/trajectory/TrajectoryError.svelte +14 -3
  317. package/dist/trajectory/TrajectoryExportPane.svelte +148 -90
  318. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
  319. package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
  320. package/dist/trajectory/constants.d.ts +6 -0
  321. package/dist/trajectory/constants.js +7 -0
  322. package/dist/trajectory/extract.js +13 -31
  323. package/dist/trajectory/format-detect.d.ts +9 -0
  324. package/dist/trajectory/format-detect.js +76 -0
  325. package/dist/trajectory/frame-reader.d.ts +17 -0
  326. package/dist/trajectory/frame-reader.js +332 -0
  327. package/dist/trajectory/helpers.d.ts +14 -0
  328. package/dist/trajectory/helpers.js +172 -0
  329. package/dist/trajectory/index.d.ts +1 -0
  330. package/dist/trajectory/index.js +23 -14
  331. package/dist/trajectory/parse/ase.d.ts +2 -0
  332. package/dist/trajectory/parse/ase.js +77 -0
  333. package/dist/trajectory/parse/hdf5.d.ts +2 -0
  334. package/dist/trajectory/parse/hdf5.js +129 -0
  335. package/dist/trajectory/parse/index.d.ts +12 -0
  336. package/dist/trajectory/parse/index.js +299 -0
  337. package/dist/trajectory/parse/lammps.d.ts +5 -0
  338. package/dist/trajectory/parse/lammps.js +179 -0
  339. package/dist/trajectory/parse/vasp.d.ts +2 -0
  340. package/dist/trajectory/parse/vasp.js +68 -0
  341. package/dist/trajectory/parse/xyz.d.ts +2 -0
  342. package/dist/trajectory/parse/xyz.js +110 -0
  343. package/dist/trajectory/plotting.js +13 -8
  344. package/dist/trajectory/types.d.ts +11 -0
  345. package/dist/trajectory/types.js +1 -0
  346. package/dist/utils.d.ts +3 -0
  347. package/dist/utils.js +17 -0
  348. package/dist/xrd/XrdPlot.svelte +337 -245
  349. package/dist/xrd/broadening.js +14 -9
  350. package/dist/xrd/calc-xrd.js +12 -19
  351. package/dist/xrd/parse.d.ts +1 -1
  352. package/dist/xrd/parse.js +17 -17
  353. package/package.json +103 -101
  354. package/readme.md +4 -4
  355. package/dist/trajectory/parse.d.ts +0 -42
  356. package/dist/trajectory/parse.js +0 -1267
  357. /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
  358. /package/dist/theme/{themes.js → themes.mjs} +0 -0
@@ -1,59 +1,113 @@
1
- <script lang="ts">import { ELEMENT_COLOR_SCHEMES, pick_contrast_color } from '../colors';
2
- import { hierarchy, pack } from 'd3-hierarchy';
3
- import { get_chart_font_scale } from './index';
4
- import { count_atoms_in_composition } from './parse';
5
- let { composition, size = 200, padding = 0, show_labels = true, show_amounts = true, color_scheme = `Vesta`, bubble_content, interactive = true, svg_node = $bindable(null), children, ...rest } = $props();
6
- let element_colors = $derived(ELEMENT_COLOR_SCHEMES[color_scheme] || ELEMENT_COLOR_SCHEMES.Vesta);
7
- // Calculate bubble data with proper circle packing
8
- let bubbles = $derived.by(() => {
9
- const element_entries = Object.entries(composition).filter(([_, amount]) => amount && amount > 0);
10
- if (element_entries.length === 0)
11
- return [];
12
- const hierarchy_data = {
13
- children: element_entries.map(([element, amount]) => ({
14
- element,
15
- amount: amount ?? 0,
16
- color: element_colors[element] || `#cccccc`,
17
- })),
18
- };
1
+ <script lang="ts">
2
+ import type { ColorSchemeName } from '../colors'
3
+ import { ELEMENT_COLOR_SCHEMES, pick_contrast_color } from '../colors'
4
+ import type { CompositionType } from './'
5
+ import type { ElementSymbol } from '../element'
6
+ import { hierarchy, pack } from 'd3-hierarchy'
7
+ import type { Snippet } from 'svelte'
8
+ import type { SVGAttributes } from 'svelte/elements'
9
+ import { type ChartSegmentData, get_chart_font_scale } from './index'
10
+ import { count_atoms_in_composition } from './parse'
11
+
12
+ type BubbleSegmentData = ChartSegmentData & { radius: number; x: number; y: number }
13
+
14
+ let {
15
+ composition,
16
+ size = 200,
17
+ padding = 0,
18
+ show_labels = true,
19
+ show_amounts = true,
20
+ color_scheme = `Vesta`,
21
+ bubble_content,
22
+ interactive = true,
23
+ svg_node = $bindable(null),
24
+ children,
25
+ ...rest
26
+ }: SVGAttributes<SVGSVGElement> & {
27
+ composition: CompositionType
28
+ size?: number
29
+ padding?: number
30
+ show_labels?: boolean
31
+ show_amounts?: boolean
32
+ color_scheme?: ColorSchemeName
33
+ bubble_content?: Snippet<[BubbleSegmentData]>
34
+ interactive?: boolean
35
+ svg_node?: SVGSVGElement | null
36
+ children?: Snippet<[{ hovered_element: ElementSymbol | null }]>
37
+ } = $props()
38
+
39
+ let element_colors = $derived(
40
+ ELEMENT_COLOR_SCHEMES[color_scheme] || ELEMENT_COLOR_SCHEMES.Vesta,
41
+ )
42
+
43
+ // Calculate bubble data with proper circle packing
44
+ let bubbles = $derived.by<BubbleSegmentData[]>(() => {
45
+ const element_entries = Object.entries(composition).filter(
46
+ ([_, amount]) => amount && amount > 0,
47
+ )
48
+ if (element_entries.length === 0) return []
49
+
50
+ // Create hierarchy data structure for D3 pack
51
+ type Child = { element: string; amount: number; color: string }
52
+ type HierarchyData = { children: Child[] }
53
+
54
+ const hierarchy_data: HierarchyData = {
55
+ children: element_entries.map(([element, amount]) => ({
56
+ element,
57
+ amount: amount ?? 0,
58
+ color: element_colors[element] || `#cccccc`,
59
+ })),
60
+ }
61
+
19
62
  // Use D3's pack layout for proper circle packing
20
- const pack_layout = pack().size([
21
- size - 2 * padding,
22
- size - 2 * padding,
23
- ]).padding(padding * 0.1); // Small padding between circles
24
- const root = pack_layout(hierarchy(hierarchy_data).sum((data) => (`amount` in data ? data.amount : 0)));
63
+ const pack_layout = pack<HierarchyData | Child>().size([
64
+ size - 2 * padding,
65
+ size - 2 * padding,
66
+ ]).padding(padding * 0.1) // Small padding between circles
67
+
68
+ const root = pack_layout(
69
+ hierarchy<HierarchyData | Child>(hierarchy_data).sum(
70
+ (data) => (`amount` in data ? data.amount : 0),
71
+ ),
72
+ )
73
+
25
74
  // Get max radius for font scaling
26
- const max_radius = Math.max(...root.leaves().map((data) => data.r || 0));
27
- const total_atoms = count_atoms_in_composition(composition);
75
+ const max_radius = Math.max(...root.leaves().map((data) => data.r || 0))
76
+ const total_atoms = count_atoms_in_composition(composition)
77
+
28
78
  return root.leaves().map((node) => {
29
- const radius = node.r || 0;
30
- const data = node.data;
31
- // Calculate font scale based on bubble size and smart text fitting
32
- const [min_font_scale, max_font_scale] = [0.6, 2];
33
- const scale_factor = radius / max_radius;
34
- const base_scale = min_font_scale +
35
- scale_factor * (max_font_scale - min_font_scale);
36
- const label_text = data.element + (show_amounts ? data.amount.toString() : ``);
37
- const available_space = radius * 2 * 0.8; // 80% of bubble diameter for text
38
- const font_scale = get_chart_font_scale(base_scale, label_text, available_space);
39
- return {
40
- element: data.element,
41
- amount: data.amount,
42
- fraction: total_atoms > 0 ? data.amount / total_atoms : 0,
43
- radius,
44
- x: (node.x || 0) + padding, // Offset by padding
45
- y: (node.y || 0) + padding,
46
- color: data.color,
47
- font_scale,
48
- text_color: pick_contrast_color({ bg_color: data.color }),
49
- };
50
- });
51
- });
52
- let hovered_element = $state(null);
79
+ const radius = node.r || 0
80
+ const data = node.data as Child
81
+
82
+ // Calculate font scale based on bubble size and smart text fitting
83
+ const [min_font_scale, max_font_scale] = [0.6, 2] as const
84
+ const scale_factor = radius / max_radius
85
+ const base_scale = min_font_scale +
86
+ scale_factor * (max_font_scale - min_font_scale)
87
+ const label_text = data.element + (show_amounts ? data.amount.toString() : ``)
88
+ const available_space = radius * 2 * 0.8 // 80% of bubble diameter for text
89
+ const font_scale = get_chart_font_scale(base_scale, label_text, available_space)
90
+
91
+ return {
92
+ element: data.element as ElementSymbol,
93
+ amount: data.amount,
94
+ fraction: total_atoms > 0 ? data.amount / total_atoms : 0,
95
+ radius,
96
+ x: (node.x || 0) + padding, // Offset by padding
97
+ y: (node.y || 0) + padding,
98
+ color: data.color,
99
+ font_scale,
100
+ text_color: pick_contrast_color({ bg_color: data.color }),
101
+ }
102
+ })
103
+ })
104
+
105
+ let hovered_element: ElementSymbol | null = $state(null)
53
106
  </script>
54
107
 
55
108
  <svg
56
109
  viewBox="0 0 {size} {size}"
110
+ style:max-width="{size}px"
57
111
  {...rest}
58
112
  class="bubble-chart {rest.class ?? ``}"
59
113
  bind:this={svg_node}
@@ -104,9 +158,10 @@ let hovered_element = $state(null);
104
158
  bubble.element
105
159
  }</span>
106
160
  {#if show_amounts}
107
- <sub class="amount" style:font-size="{10 * bubble.font_scale}px">
108
- {bubble.amount}
109
- </sub>{/if}
161
+ <sub class="amount" style:font-size="{8 * bubble.font_scale}px">{
162
+ bubble.amount
163
+ }</sub>
164
+ {/if}
110
165
  </div>
111
166
  </foreignObject>
112
167
  {/each}
@@ -1,107 +1,128 @@
1
- <script lang="ts">import { untrack } from 'svelte';
2
- import { ContextMenu } from '../overlays';
3
- import { export_svg_as_png, export_svg_as_svg } from '../io/export';
4
- import { get_electro_neg_formula } from './format';
5
- import { BarChart, BubbleChart, PieChart } from './index';
6
- import { parse_composition } from './parse';
7
- let { composition, mode = `pie`, on_composition_change, color_scheme = `Vesta`, ...rest } = $props();
8
- // Using $state with untrack() - initialized from props but mutated by context menu
9
- let current_color_scheme = $state(untrack(() => color_scheme));
10
- let current_mode = $state(untrack(() => mode));
11
- let svg_node = $state(null);
12
- let Component = $derived({ pie: PieChart, bubble: BubbleChart, bar: BarChart }[current_mode]);
13
- let parsed = $derived.by(() => {
1
+ <script lang="ts">
2
+ import type { ColorSchemeName } from '../colors'
3
+ import type { CompositionType } from './'
4
+ import { untrack } from 'svelte'
5
+ import { ContextMenu } from '../overlays'
6
+ import { export_svg_as_png, export_svg_as_svg } from '../io/export'
7
+ import type { SVGAttributes } from 'svelte/elements'
8
+ import { get_electro_neg_formula } from './format'
9
+ import { BarChart, BubbleChart, PieChart } from './index'
10
+ import { parse_composition } from './parse'
11
+
12
+ type CompositionChartMode = `pie` | `bubble` | `bar`
13
+ let {
14
+ composition,
15
+ mode = `pie`,
16
+ on_composition_change,
17
+ color_scheme = `Vesta`,
18
+ ...rest
19
+ }: SVGAttributes<SVGSVGElement> & {
20
+ composition: string | CompositionType
21
+ mode?: CompositionChartMode
22
+ on_composition_change?: (composition: CompositionType) => void
23
+ color_scheme?: ColorSchemeName
24
+ size?: number
25
+ interactive?: boolean
26
+ } = $props()
27
+
28
+ // Using $state with untrack() - initialized from props but mutated by context menu
29
+ let current_color_scheme = $state(untrack(() => color_scheme as ColorSchemeName))
30
+ let current_mode = $state(untrack(() => mode))
31
+ let svg_node = $state<SVGSVGElement | null>(null)
32
+
33
+ let Component = $derived(
34
+ { pie: PieChart, bubble: BubbleChart, bar: BarChart }[current_mode],
35
+ )
36
+ let parsed: CompositionType = $derived.by(() => {
14
37
  try {
15
- return parse_composition(composition);
16
- }
17
- catch (error) {
18
- console.error(`Failed to parse composition:`, error);
19
- return {};
38
+ return parse_composition(composition)
39
+ } catch (error) {
40
+ console.error(`Failed to parse composition:`, error)
41
+ return {}
20
42
  }
21
- });
22
- // Call the composition change callback in an effect, not in the derived
23
- $effect(() => on_composition_change?.(parsed));
24
- let context_menu = $state({ open: false, x: 0, y: 0 });
25
- function handle_right_click(event) {
26
- event.preventDefault();
27
- context_menu.open = false; // Close any existing context menu first
28
- context_menu.x = event.pageX;
29
- context_menu.y = event.pageY;
43
+ })
44
+ // Call the composition change callback in an effect, not in the derived
45
+ $effect(() => on_composition_change?.(parsed))
46
+
47
+ let context_menu = $state({ open: false, x: 0, y: 0 })
48
+
49
+ function handle_right_click(event: MouseEvent) { // open context menu
50
+ event.preventDefault()
51
+ context_menu.open = false // Close any existing context menu first
52
+ context_menu.x = event.pageX
53
+ context_menu.y = event.pageY
30
54
  // Use a small delay to ensure the prev context menu closes happens before opening new one
31
- setTimeout(() => context_menu.open = true, 0);
32
- }
33
- const mode_options = [
55
+ setTimeout(() => context_menu.open = true, 0)
56
+ }
57
+
58
+ const mode_options = [
34
59
  { value: `pie`, icon: `Circle`, label: `Pie Chart` },
35
60
  { value: `bubble`, icon: `Circle`, label: `Bubble Chart` },
36
61
  { value: `bar`, icon: `Graph`, label: `Bar Chart` },
37
- ];
38
- const color_scheme_options = [
62
+ ] as const
63
+
64
+ const color_scheme_options = [
39
65
  { value: `Vesta`, icon: `ColorPalette`, label: `Vesta` },
40
66
  { value: `Jmol`, icon: `ColorPalette`, label: `Jmol` },
41
67
  { value: `Alloy`, icon: `ColorPalette`, label: `Alloy` },
42
68
  { value: `Pastel`, icon: `ColorPalette`, label: `Pastel` },
43
69
  { value: `Muted`, icon: `ColorPalette`, label: `Muted` },
44
70
  { value: `Dark Mode`, icon: `ColorPalette`, label: `Dark Mode` },
45
- ];
46
- const export_options = [
71
+ ] as const
72
+
73
+ const export_options = [
47
74
  { value: `copy_formula`, icon: `Copy`, label: `Copy Formula` },
48
75
  { value: `copy_data`, icon: `Copy`, label: `Copy Data` },
49
76
  { value: `export_svg`, icon: `Download`, label: `Export SVG` },
50
77
  { value: `export_png`, icon: `Download`, label: `Export PNG` },
51
- ];
52
- const sec_titles = {
78
+ ] as const
79
+
80
+ const sec_titles = {
53
81
  display_mode: `Display Mode`,
54
82
  color_scheme: `Color Scheme`,
55
83
  export: `Export`,
56
- };
57
- const context_menu_sections = [
84
+ } as const
85
+
86
+ const context_menu_sections = [
58
87
  { title: sec_titles.display_mode, options: mode_options },
59
88
  { title: sec_titles.color_scheme, options: color_scheme_options },
60
89
  { title: sec_titles.export, options: export_options },
61
- ];
62
- function handle_context_menu_select(section_title, option) {
90
+ ] as const
91
+
92
+ function handle_context_menu_select(
93
+ section_title: string,
94
+ option: { value: string },
95
+ ) {
63
96
  if (section_title === sec_titles.display_mode) {
64
- current_mode = option.value;
65
- }
66
- else if (section_title === sec_titles.color_scheme) {
67
- current_color_scheme = option.value;
68
- }
69
- else if (section_title === sec_titles.export)
70
- handle_export(option.value);
71
- context_menu.open = false;
72
- }
73
- // Handle export actions
74
- function handle_export(export_type) {
97
+ current_mode = option.value as CompositionChartMode
98
+ } else if (section_title === sec_titles.color_scheme) {
99
+ current_color_scheme = option.value as ColorSchemeName
100
+ } else if (section_title === sec_titles.export) handle_export(option.value)
101
+ context_menu.open = false
102
+ }
103
+
104
+ // Handle export actions
105
+ function handle_export(export_type: string) {
75
106
  try {
76
- if (export_type === `copy_formula`) {
77
- const formula = get_electro_neg_formula(composition);
78
- navigator.clipboard.writeText(formula);
79
- }
80
- else if (export_type === `copy_data`) {
81
- const data = JSON.stringify(parsed, null, 2);
82
- navigator.clipboard.writeText(data);
83
- }
84
- else if (export_type === `export_svg`) {
85
- const filename = `${get_electro_neg_formula(composition, true, ``)}.svg`;
86
- if (svg_node)
87
- export_svg_as_svg(svg_node, filename);
88
- else
89
- console.warn(`Chart SVG not available for SVG export`);
90
- }
91
- else if (export_type === `export_png`) {
92
- const filename = `${get_electro_neg_formula(composition, true, ``)}.png`;
93
- if (svg_node)
94
- export_svg_as_png(svg_node, filename, 150);
95
- else
96
- console.warn(`Chart SVG not available for PNG export`);
97
- }
98
- else
99
- console.warn(`Invalid export type:`, export_type);
100
- }
101
- catch (error) {
102
- console.error(`Export failed:`, error);
107
+ if (export_type === `copy_formula`) {
108
+ const formula = get_electro_neg_formula(composition)
109
+ navigator.clipboard.writeText(formula)
110
+ } else if (export_type === `copy_data`) {
111
+ const data = JSON.stringify(parsed, null, 2)
112
+ navigator.clipboard.writeText(data)
113
+ } else if (export_type === `export_svg`) {
114
+ const filename = `${get_electro_neg_formula(composition, true, ``)}.svg`
115
+ if (svg_node) export_svg_as_svg(svg_node, filename)
116
+ else console.warn(`Chart SVG not available for SVG export`)
117
+ } else if (export_type === `export_png`) {
118
+ const filename = `${get_electro_neg_formula(composition, true, ``)}.png`
119
+ if (svg_node) export_svg_as_png(svg_node, filename, 150)
120
+ else console.warn(`Chart SVG not available for PNG export`)
121
+ } else console.warn(`Invalid export type:`, export_type)
122
+ } catch (error) {
123
+ console.error(`Export failed:`, error)
103
124
  }
104
- }
125
+ }
105
126
  </script>
106
127
 
107
128
  <Component
@@ -1,75 +1,121 @@
1
- <script lang="ts">import { ELEMENT_COLOR_SCHEMES, luminance } from '../colors';
2
- import { element_data } from '../element';
3
- import ElementTile from '../element/ElementTile.svelte';
4
- import { format_num } from '../labels';
5
- import { format_oxi_state, sort_by_electronegativity, sort_by_hill_notation, } from './format';
6
- import { oxi_composition_to_elements, parse_formula_with_oxidation } from './parse';
7
- let { formula, color_scheme = `Vesta`, ordering = `original`, as = `span`, amount_format = `.3~s`, tooltip_side = `bottom`, tooltip_offset = 5, on_click, ...rest } = $props();
8
- const parsed_elements = $derived.by(() => {
1
+ <script lang="ts">
2
+ import type { ColorSchemeName } from '../colors'
3
+ import { ELEMENT_COLOR_SCHEMES, luminance } from '../colors'
4
+ import type { ElementSymbol } from '../element'
5
+ import { element_data } from '../element'
6
+ import ElementTile from '../element/ElementTile.svelte'
7
+ import { format_num } from '../labels'
8
+ import type { HTMLAttributes } from 'svelte/elements'
9
+ import {
10
+ format_oxi_state,
11
+ sort_by_electronegativity,
12
+ sort_by_hill_notation,
13
+ } from './format'
14
+ import type { ElementWithOxidation, OxiComposition } from './parse'
15
+ import { oxi_composition_to_elements, parse_formula_with_oxidation } from './parse'
16
+
17
+ type FormulaOrdering = `electronegativity` | `alphabetical` | `original` | `hill`
18
+ type TooltipSide = `top` | `bottom` | `left` | `right`
19
+ let {
20
+ formula,
21
+ color_scheme = `Vesta`,
22
+ ordering = `original`,
23
+ as = `span`,
24
+ amount_format = `.3~s`,
25
+ tooltip_side = `bottom`,
26
+ tooltip_offset = 5,
27
+ on_click,
28
+ ...rest
29
+ }: HTMLAttributes<HTMLElement> & {
30
+ formula: string | OxiComposition
31
+ color_scheme?: ColorSchemeName
32
+ ordering?: FormulaOrdering
33
+ as?: string
34
+ amount_format?: string
35
+ tooltip_side?: TooltipSide
36
+ tooltip_offset?: number
37
+ on_click?: (element: ElementSymbol, event: MouseEvent | KeyboardEvent) => void
38
+ } = $props()
39
+
40
+ const parsed_elements = $derived.by(() => {
9
41
  try {
10
- return typeof formula === `string`
11
- ? parse_formula_with_oxidation(formula)
12
- : oxi_composition_to_elements(formula);
42
+ return typeof formula === `string`
43
+ ? parse_formula_with_oxidation(formula)
44
+ : oxi_composition_to_elements(formula)
45
+ } catch (error) {
46
+ console.error(`Failed to parse formula:`, error)
47
+ return []
13
48
  }
14
- catch (error) {
15
- console.error(`Failed to parse formula:`, error);
16
- return [];
17
- }
18
- });
19
- const COMPARATORS = {
49
+ })
50
+
51
+ const COMPARATORS: Record<
52
+ FormulaOrdering,
53
+ (el1: ElementWithOxidation, el2: ElementWithOxidation) => number
54
+ > = {
20
55
  alphabetical: (el1, el2) => el1.element.localeCompare(el2.element),
21
56
  original: (el1, el2) => el1.orig_idx - el2.orig_idx,
22
57
  electronegativity: (el1, el2) => {
23
- const sorted = sort_by_electronegativity([el1.element, el2.element]);
24
- return sorted[0] === el1.element ? -1 : 1;
58
+ const sorted = sort_by_electronegativity([el1.element, el2.element])
59
+ return sorted[0] === el1.element ? -1 : 1
25
60
  },
26
61
  hill: (el1, el2) => {
27
- const sorted = sort_by_hill_notation([el1.element, el2.element]);
28
- return sorted[0] === el1.element ? -1 : 1;
62
+ const sorted = sort_by_hill_notation([el1.element, el2.element])
63
+ return sorted[0] === el1.element ? -1 : 1
29
64
  },
30
- };
31
- const sorted_elements = $derived([...parsed_elements].sort(COMPARATORS[ordering]));
32
- let hovered_element = $state(null);
33
- let tooltip_pos = $state({ x: 0, y: 0 });
34
- const hovered_elem_data = $derived(hovered_element ? element_data.find((el) => el.symbol === hovered_element) : null);
35
- // Format formula as plain text for clipboard: "Li2 O" or "Fe(+3)2 O(-2)3"
36
- const plain_text_formula = $derived(sorted_elements
37
- .map(({ element, amount, oxidation_state }) => {
38
- let text = element;
39
- if (oxidation_state !== undefined && oxidation_state !== 0) {
40
- // Use parentheses to avoid ambiguity like "Fe+32" looking like oxidation +32
41
- text += `(${format_oxi_state(oxidation_state)})`;
42
- }
43
- if (amount !== 1)
44
- text += format_num(amount, amount_format);
45
- return text;
46
- })
47
- .join(` `));
48
- function handle_copy(event) {
49
- const selection = window.getSelection();
65
+ }
66
+ const sorted_elements = $derived(
67
+ [...parsed_elements].sort(COMPARATORS[ordering]),
68
+ )
69
+
70
+ let hovered_element = $state<ElementSymbol | null>(null)
71
+ let tooltip_pos = $state({ x: 0, y: 0 })
72
+
73
+ const hovered_elem_data = $derived(
74
+ hovered_element ? element_data.find((el) => el.symbol === hovered_element) : null,
75
+ )
76
+
77
+ // Format formula as plain text for clipboard: "Li2 O" or "Fe(+3)2 O(-2)3"
78
+ const plain_text_formula = $derived(
79
+ sorted_elements
80
+ .map(({ element, amount, oxidation_state }) => {
81
+ let text = element
82
+ if (oxidation_state !== undefined && oxidation_state !== 0) {
83
+ // Use parentheses to avoid ambiguity like "Fe+32" looking like oxidation +32
84
+ text += `(${format_oxi_state(oxidation_state)})`
85
+ }
86
+ if (amount !== 1) text += format_num(amount, amount_format)
87
+ return text
88
+ })
89
+ .join(` `),
90
+ )
91
+
92
+ function handle_copy(event: ClipboardEvent) {
93
+ const selection = window.getSelection()
50
94
  // Only intercept if user selected text fully within this formula
51
- if (!selection || selection.isCollapsed)
52
- return;
53
- const formula_el = event.currentTarget;
54
- if (!formula_el.contains(selection.anchorNode) ||
55
- !formula_el.contains(selection.focusNode))
56
- return; // Selection extends outside formula, let browser handle normally
57
- event.preventDefault();
58
- event.clipboardData?.setData(`text/plain`, plain_text_formula);
59
- }
60
- function show_tooltip(element, event) {
61
- const { left, width, top, bottom, right, height } = event.target
62
- .getBoundingClientRect();
63
- hovered_element = element;
95
+ if (!selection || selection.isCollapsed) return
96
+ const formula_el = event.currentTarget as HTMLElement
97
+ if (
98
+ !formula_el.contains(selection.anchorNode) ||
99
+ !formula_el.contains(selection.focusNode)
100
+ ) return // Selection extends outside formula, let browser handle normally
101
+ event.preventDefault()
102
+ event.clipboardData?.setData(`text/plain`, plain_text_formula)
103
+ }
104
+
105
+ function show_tooltip(element: ElementSymbol, event: MouseEvent) {
106
+ const { left, width, top, bottom, right, height } = (event.target as HTMLElement)
107
+ .getBoundingClientRect()
108
+ hovered_element = element
109
+
64
110
  const positions = {
65
- top: [left + width / 2, top - tooltip_offset],
66
- bottom: [left + width / 2, bottom + tooltip_offset],
67
- left: [left - tooltip_offset, top + height / 2],
68
- right: [right + tooltip_offset, top + height / 2],
69
- };
70
- const [x, y] = positions[tooltip_side];
71
- tooltip_pos = { x, y };
72
- }
111
+ top: [left + width / 2, top - tooltip_offset],
112
+ bottom: [left + width / 2, bottom + tooltip_offset],
113
+ left: [left - tooltip_offset, top + height / 2],
114
+ right: [right + tooltip_offset, top + height / 2],
115
+ }
116
+ const [x, y] = positions[tooltip_side]
117
+ tooltip_pos = { x, y }
118
+ }
73
119
  </script>
74
120
 
75
121
  <svelte:element