matterviz 0.4.0 → 0.4.2

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 (527) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +12 -14
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/app.css +53 -0
  6. package/dist/brillouin/BrillouinZone.svelte +132 -219
  7. package/dist/brillouin/BrillouinZone.svelte.d.ts +9 -20
  8. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  9. package/dist/brillouin/BrillouinZoneExportPane.svelte +47 -96
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  11. package/dist/brillouin/BrillouinZoneInfoPane.svelte +15 -42
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
  13. package/dist/brillouin/BrillouinZoneScene.svelte +63 -230
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +3 -23
  15. package/dist/brillouin/ReciprocalVectors.svelte +39 -0
  16. package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
  17. package/dist/brillouin/compute.d.ts +2 -0
  18. package/dist/brillouin/compute.js +80 -77
  19. package/dist/brillouin/geometry.d.ts +8 -0
  20. package/dist/brillouin/geometry.js +57 -0
  21. package/dist/brillouin/index.d.ts +2 -0
  22. package/dist/brillouin/index.js +2 -0
  23. package/dist/brillouin/types.d.ts +2 -2
  24. package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
  25. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
  26. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +143 -246
  27. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
  28. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +652 -976
  29. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
  30. package/dist/chempot-diagram/async-compute.svelte.js +1 -1
  31. package/dist/chempot-diagram/color.d.ts +3 -6
  32. package/dist/chempot-diagram/color.js +5 -5
  33. package/dist/chempot-diagram/compute.d.ts +3 -3
  34. package/dist/chempot-diagram/compute.js +3 -1
  35. package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
  36. package/dist/chempot-diagram/controls-state.svelte.js +42 -0
  37. package/dist/chempot-diagram/export.d.ts +47 -0
  38. package/dist/chempot-diagram/export.js +133 -0
  39. package/dist/chempot-diagram/index.d.ts +1 -0
  40. package/dist/chempot-diagram/index.js +1 -0
  41. package/dist/chempot-diagram/pointer.d.ts +0 -10
  42. package/dist/chempot-diagram/pointer.js +4 -4
  43. package/dist/chempot-diagram/types.d.ts +3 -3
  44. package/dist/colors/index.d.ts +0 -4
  45. package/dist/colors/index.js +21 -22
  46. package/dist/composition/BarChart.svelte +37 -31
  47. package/dist/composition/BubbleChart.svelte +17 -17
  48. package/dist/composition/Composition.svelte +7 -11
  49. package/dist/composition/Formula.svelte +18 -25
  50. package/dist/composition/FormulaFilter.svelte +96 -98
  51. package/dist/composition/PieChart.svelte +60 -46
  52. package/dist/composition/chem-sys.js +3 -2
  53. package/dist/composition/format.js +4 -3
  54. package/dist/composition/index.d.ts +2 -0
  55. package/dist/composition/index.js +14 -0
  56. package/dist/composition/parse.d.ts +2 -3
  57. package/dist/composition/parse.js +27 -28
  58. package/dist/constants.js +11 -9
  59. package/dist/controls.d.ts +1 -0
  60. package/dist/controls.js +0 -1
  61. package/dist/convex-hull/ConvexHull.svelte +20 -25
  62. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
  63. package/dist/convex-hull/ConvexHull2D.svelte +176 -256
  64. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  65. package/dist/convex-hull/ConvexHull3D.svelte +269 -804
  66. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  67. package/dist/convex-hull/ConvexHull4D.svelte +236 -755
  68. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  69. package/dist/convex-hull/ConvexHullChrome.svelte +264 -0
  70. package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
  71. package/dist/convex-hull/ConvexHullControls.svelte +128 -49
  72. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
  73. package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
  74. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
  75. package/dist/convex-hull/ConvexHullStats.svelte +210 -351
  76. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
  77. package/dist/convex-hull/ConvexHullTooltip.svelte +16 -14
  78. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
  79. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  80. package/dist/convex-hull/StructurePopup.svelte +17 -21
  81. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  82. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  83. package/dist/convex-hull/barycentric-coords.d.ts +2 -4
  84. package/dist/convex-hull/barycentric-coords.js +6 -33
  85. package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
  86. package/dist/convex-hull/canvas-interactions.svelte.js +279 -0
  87. package/dist/convex-hull/helpers.d.ts +47 -17
  88. package/dist/convex-hull/helpers.js +186 -101
  89. package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
  90. package/dist/convex-hull/hull-state.svelte.js +124 -0
  91. package/dist/convex-hull/index.d.ts +9 -7
  92. package/dist/convex-hull/index.js +7 -2
  93. package/dist/convex-hull/thermodynamics.js +109 -937
  94. package/dist/convex-hull/types.d.ts +12 -4
  95. package/dist/convex-hull/types.js +12 -0
  96. package/dist/coordination/CoordinationBarPlot.svelte +41 -43
  97. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  98. package/dist/coordination/calc-coordination.d.ts +1 -1
  99. package/dist/coordination/calc-coordination.js +28 -25
  100. package/dist/element/BohrAtom.svelte +6 -8
  101. package/dist/element/ElementHeading.svelte +4 -1
  102. package/dist/element/ElementPhoto.svelte +11 -9
  103. package/dist/element/ElementStats.svelte +12 -10
  104. package/dist/element/ElementTile.svelte +24 -29
  105. package/dist/element/ElementTile.svelte.d.ts +1 -1
  106. package/dist/element/Nucleus.svelte +4 -2
  107. package/dist/element/data.d.ts +1 -2
  108. package/dist/element/helpers.d.ts +4 -0
  109. package/dist/element/helpers.js +18 -0
  110. package/dist/element/index.d.ts +1 -0
  111. package/dist/element/index.js +3 -0
  112. package/dist/feedback/DragOverlay.svelte +5 -3
  113. package/dist/feedback/DragOverlay.svelte.d.ts +2 -1
  114. package/dist/feedback/StatusMessage.svelte +20 -7
  115. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  116. package/dist/fermi-surface/FermiSurface.svelte +78 -165
  117. package/dist/fermi-surface/FermiSurface.svelte.d.ts +9 -20
  118. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  119. package/dist/fermi-surface/FermiSurfaceScene.svelte +93 -272
  120. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
  121. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  122. package/dist/fermi-surface/compute.js +14 -13
  123. package/dist/fermi-surface/export.js +4 -15
  124. package/dist/fermi-surface/index.d.ts +0 -1
  125. package/dist/fermi-surface/index.js +0 -1
  126. package/dist/fermi-surface/parse.d.ts +1 -1
  127. package/dist/fermi-surface/parse.js +84 -97
  128. package/dist/fermi-surface/types.d.ts +2 -2
  129. package/dist/heatmap-matrix/HeatmapMatrix.svelte +161 -185
  130. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +6 -5
  131. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +12 -9
  132. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
  133. package/dist/heatmap-matrix/index.d.ts +8 -2
  134. package/dist/icons.d.ts +4 -0
  135. package/dist/icons.js +4 -0
  136. package/dist/index.d.ts +1 -0
  137. package/dist/index.js +1 -0
  138. package/dist/io/ExportPane.svelte +170 -0
  139. package/dist/io/ExportPane.svelte.d.ts +17 -0
  140. package/dist/io/decompress.d.ts +2 -1
  141. package/dist/io/decompress.js +22 -36
  142. package/dist/io/export.d.ts +9 -1
  143. package/dist/io/export.js +37 -29
  144. package/dist/io/fetch.d.ts +2 -4
  145. package/dist/io/fetch.js +0 -11
  146. package/dist/io/file-drop.d.ts +7 -0
  147. package/dist/io/file-drop.js +13 -0
  148. package/dist/io/index.d.ts +1 -0
  149. package/dist/io/index.js +3 -0
  150. package/dist/io/is-binary.d.ts +9 -0
  151. package/dist/io/is-binary.js +45 -1
  152. package/dist/io/types.d.ts +13 -0
  153. package/dist/io/url-drop.js +13 -25
  154. package/dist/isosurface/Isosurface.svelte +17 -23
  155. package/dist/isosurface/IsosurfaceControls.svelte +37 -42
  156. package/dist/isosurface/parse-vaspwave.d.ts +3 -0
  157. package/dist/isosurface/parse-vaspwave.js +138 -0
  158. package/dist/isosurface/parse.js +50 -48
  159. package/dist/labels.d.ts +6 -2
  160. package/dist/labels.js +44 -14
  161. package/dist/layout/FullscreenButton.svelte +34 -0
  162. package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
  163. package/dist/layout/FullscreenToggle.svelte +12 -12
  164. package/dist/layout/InfoCard.svelte +7 -18
  165. package/dist/layout/InfoTag.svelte +1 -3
  166. package/dist/layout/NumberRangeInput.svelte +46 -0
  167. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  168. package/dist/layout/PropertyFilter.svelte +2 -6
  169. package/dist/layout/SettingsSection.svelte +21 -17
  170. package/dist/layout/SubpageGrid.svelte +3 -1
  171. package/dist/layout/ViewerChrome.svelte +115 -0
  172. package/dist/layout/ViewerChrome.svelte.d.ts +18 -0
  173. package/dist/layout/fullscreen.d.ts +4 -0
  174. package/dist/layout/fullscreen.js +3 -5
  175. package/dist/layout/fullscreen.svelte.d.ts +8 -0
  176. package/dist/layout/fullscreen.svelte.js +36 -0
  177. package/dist/layout/index.d.ts +4 -0
  178. package/dist/layout/index.js +4 -0
  179. package/dist/layout/json-tree/JsonNode.svelte +8 -11
  180. package/dist/layout/json-tree/JsonTree.svelte +53 -77
  181. package/dist/layout/json-tree/JsonValue.svelte +7 -15
  182. package/dist/layout/json-tree/utils.js +14 -23
  183. package/dist/math.d.ts +9 -3
  184. package/dist/math.js +37 -21
  185. package/dist/overlays/ContextMenu.svelte +4 -2
  186. package/dist/overlays/CopyButton.svelte +11 -5
  187. package/dist/overlays/DragControlTab.svelte +6 -1
  188. package/dist/overlays/DraggablePane.svelte +81 -26
  189. package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
  190. package/dist/overlays/GlassChip.svelte +30 -0
  191. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  192. package/dist/overlays/InfoPaneCards.svelte +11 -23
  193. package/dist/overlays/index.d.ts +11 -0
  194. package/dist/overlays/index.js +26 -0
  195. package/dist/overlays/portal.d.ts +2 -0
  196. package/dist/overlays/portal.js +14 -0
  197. package/dist/periodic-table/PeriodicTable.svelte +115 -146
  198. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  199. package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
  200. package/dist/periodic-table/TableInset.svelte +9 -4
  201. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
  202. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  203. package/dist/phase-diagram/PhaseDiagramControls.svelte +73 -96
  204. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
  205. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
  206. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
  207. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +49 -134
  208. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
  209. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  210. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  211. package/dist/phase-diagram/build-diagram.js +3 -3
  212. package/dist/phase-diagram/colors.js +1 -1
  213. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  214. package/dist/phase-diagram/parse.d.ts +2 -1
  215. package/dist/phase-diagram/parse.js +15 -15
  216. package/dist/phase-diagram/svg-to-diagram.js +21 -15
  217. package/dist/phase-diagram/utils.js +2 -3
  218. package/dist/plot/bar/BarPlot.svelte +494 -692
  219. package/dist/plot/bar/BarPlot.svelte.d.ts +9 -15
  220. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  221. package/dist/plot/bar/BarPlotControls.svelte.d.ts +5 -7
  222. package/dist/plot/bar/SpacegroupBarPlot.svelte +31 -37
  223. package/dist/plot/bar/data.d.ts +5 -4
  224. package/dist/plot/bar/data.js +2 -1
  225. package/dist/plot/box/BoxPlot.svelte +361 -439
  226. package/dist/plot/box/BoxPlot.svelte.d.ts +6 -3
  227. package/dist/plot/box/BoxPlotControls.svelte.d.ts +1 -1
  228. package/dist/plot/box/Violin.svelte.d.ts +2 -1
  229. package/dist/plot/box/box-plot.d.ts +3 -2
  230. package/dist/plot/box/box-plot.js +6 -3
  231. package/dist/plot/box/kde.d.ts +2 -1
  232. package/dist/plot/box/kde.js +4 -4
  233. package/dist/plot/core/auto-place.d.ts +1 -1
  234. package/dist/plot/core/auto-place.js +5 -2
  235. package/dist/plot/core/axis-utils.d.ts +12 -7
  236. package/dist/plot/core/axis-utils.js +48 -48
  237. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  238. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  239. package/dist/plot/core/components/ColorBar.svelte +106 -111
  240. package/dist/plot/core/components/ColorBar.svelte.d.ts +5 -4
  241. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  242. package/dist/plot/core/components/FillArea.svelte +10 -17
  243. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  244. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  245. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  246. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  247. package/dist/plot/core/components/Line.svelte +21 -11
  248. package/dist/plot/core/components/Line.svelte.d.ts +5 -2
  249. package/dist/plot/core/components/PlotAxis.svelte +42 -18
  250. package/dist/plot/core/components/PlotAxis.svelte.d.ts +2 -1
  251. package/dist/plot/core/components/PlotControls.svelte +65 -41
  252. package/dist/plot/core/components/PlotControls.svelte.d.ts +1 -1
  253. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  254. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  255. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  256. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  257. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  258. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  259. package/dist/plot/core/components/ReferenceLine3D.svelte +56 -59
  260. package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +4 -4
  261. package/dist/plot/core/components/ReferencePlane.svelte +9 -10
  262. package/dist/plot/core/components/ReferencePlane.svelte.d.ts +4 -4
  263. package/dist/plot/core/components/ZeroLines.svelte +4 -8
  264. package/dist/plot/core/components/ZoomRect.svelte +1 -2
  265. package/dist/plot/core/components/index.d.ts +1 -0
  266. package/dist/plot/core/components/index.js +1 -0
  267. package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
  268. package/dist/plot/core/data-cleaning-signal.js +467 -0
  269. package/dist/plot/core/data-cleaning.d.ts +2 -42
  270. package/dist/plot/core/data-cleaning.js +29 -476
  271. package/dist/plot/core/data-transform.js +9 -5
  272. package/dist/plot/core/fill-utils.d.ts +7 -4
  273. package/dist/plot/core/fill-utils.js +34 -9
  274. package/dist/plot/core/index.d.ts +1 -0
  275. package/dist/plot/core/index.js +1 -0
  276. package/dist/plot/core/interactions.d.ts +5 -1
  277. package/dist/plot/core/interactions.js +14 -2
  278. package/dist/plot/core/layout.d.ts +3 -1
  279. package/dist/plot/core/layout.js +22 -13
  280. package/dist/plot/core/marginals.d.ts +170 -0
  281. package/dist/plot/core/marginals.js +436 -0
  282. package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
  283. package/dist/plot/core/pan-zoom.svelte.js +221 -0
  284. package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
  285. package/dist/plot/core/placed-tween.svelte.js +68 -0
  286. package/dist/plot/core/reference-line.d.ts +10 -10
  287. package/dist/plot/core/reference-line.js +7 -7
  288. package/dist/plot/core/scales.d.ts +40 -25
  289. package/dist/plot/core/scales.js +49 -21
  290. package/dist/plot/core/svg.d.ts +2 -1
  291. package/dist/plot/core/types/fills.d.ts +101 -0
  292. package/dist/plot/core/types/fills.js +15 -0
  293. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  294. package/dist/plot/core/types/plot-3d.js +4 -0
  295. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  296. package/dist/plot/core/types/reference-lines.js +9 -0
  297. package/dist/plot/core/types.d.ts +47 -331
  298. package/dist/plot/core/types.js +23 -20
  299. package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
  300. package/dist/plot/core/utils/hierarchy-chart.js +179 -0
  301. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  302. package/dist/plot/core/utils/hierarchy-labels.js +99 -0
  303. package/dist/plot/core/utils/label-placement.d.ts +1 -1
  304. package/dist/plot/core/utils/label-placement.js +5 -5
  305. package/dist/plot/core/utils.d.ts +2 -1
  306. package/dist/plot/histogram/Histogram.svelte +373 -631
  307. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  308. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  309. package/dist/plot/histogram/HistogramControls.svelte.d.ts +1 -1
  310. package/dist/plot/histogram/histogram.d.ts +31 -0
  311. package/dist/plot/histogram/histogram.js +70 -0
  312. package/dist/plot/histogram/index.d.ts +1 -0
  313. package/dist/plot/histogram/index.js +1 -0
  314. package/dist/plot/index.d.ts +1 -0
  315. package/dist/plot/index.js +1 -0
  316. package/dist/plot/sankey/Sankey.svelte +79 -73
  317. package/dist/plot/sankey/Sankey.svelte.d.ts +3 -3
  318. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  319. package/dist/plot/sankey/sankey.js +3 -1
  320. package/dist/plot/scatter/BinnedScatterPlot.svelte +264 -112
  321. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +11 -4
  322. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  323. package/dist/plot/scatter/ScatterPlot.svelte +623 -821
  324. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +9 -15
  325. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  326. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  327. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  328. package/dist/plot/scatter/binned-scatter-types.d.ts +6 -12
  329. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  330. package/dist/plot/scatter/index.d.ts +1 -1
  331. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  332. package/dist/plot/scatter/scatter-data.js +8 -7
  333. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +40 -60
  334. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +6 -14
  335. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +17 -15
  336. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +5 -5
  337. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +232 -234
  338. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +5 -14
  339. package/dist/plot/scatter-3d/Surface3D.svelte +9 -17
  340. package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +4 -3
  341. package/dist/plot/sunburst/Sunburst.svelte +256 -338
  342. package/dist/plot/sunburst/Sunburst.svelte.d.ts +4 -3
  343. package/dist/plot/sunburst/index.d.ts +1 -1
  344. package/dist/plot/sunburst/index.js +2 -1
  345. package/dist/plot/sunburst/render.d.ts +2 -2
  346. package/dist/plot/sunburst/render.js +47 -22
  347. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  348. package/dist/plot/sunburst/sunburst.js +14 -4
  349. package/dist/plot/treemap/Treemap.svelte +907 -0
  350. package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
  351. package/dist/plot/treemap/index.d.ts +3 -0
  352. package/dist/plot/treemap/index.js +4 -0
  353. package/dist/plot/treemap/treemap.d.ts +26 -0
  354. package/dist/plot/treemap/treemap.js +99 -0
  355. package/dist/rdf/RdfPlot.svelte +22 -26
  356. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  357. package/dist/rdf/calc-rdf.js +4 -8
  358. package/dist/sanitize.js +14 -3
  359. package/dist/scene/SceneCamera.svelte +62 -0
  360. package/dist/scene/SceneCamera.svelte.d.ts +19 -0
  361. package/dist/scene/bind-renderer.svelte.d.ts +2 -0
  362. package/dist/scene/bind-renderer.svelte.js +22 -0
  363. package/dist/scene/index.d.ts +4 -0
  364. package/dist/scene/index.js +5 -0
  365. package/dist/scene/props.js +52 -0
  366. package/dist/scene/types.d.ts +26 -0
  367. package/dist/scene/types.js +1 -0
  368. package/dist/settings.d.ts +33 -11
  369. package/dist/settings.js +136 -51
  370. package/dist/spectral/Bands.svelte +231 -237
  371. package/dist/spectral/Bands.svelte.d.ts +3 -2
  372. package/dist/spectral/BandsAndDos.svelte +29 -29
  373. package/dist/spectral/BrillouinBandsDos.svelte +21 -29
  374. package/dist/spectral/Dos.svelte +75 -77
  375. package/dist/spectral/Dos.svelte.d.ts +2 -1
  376. package/dist/spectral/helpers.d.ts +9 -9
  377. package/dist/spectral/helpers.js +66 -70
  378. package/dist/state.svelte.d.ts +0 -7
  379. package/dist/state.svelte.js +5 -24
  380. package/dist/structure/Arrow.svelte +6 -21
  381. package/dist/structure/ArrowInstances.svelte +160 -0
  382. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  383. package/dist/structure/AtomLegend.svelte +115 -75
  384. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  385. package/dist/structure/Bond.svelte +31 -23
  386. package/dist/structure/CanvasTooltip.svelte +16 -3
  387. package/dist/structure/CellSelect.svelte +22 -29
  388. package/dist/structure/CellSelect.svelte.d.ts +2 -1
  389. package/dist/structure/Cylinder.svelte +24 -40
  390. package/dist/structure/InstancedAtoms.svelte +114 -0
  391. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  392. package/dist/structure/Lattice.svelte +85 -149
  393. package/dist/structure/SiteLabels.svelte +122 -0
  394. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  395. package/dist/structure/Structure.svelte +725 -735
  396. package/dist/structure/Structure.svelte.d.ts +8 -16
  397. package/dist/structure/StructureCarousel.svelte +630 -0
  398. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  399. package/dist/structure/StructureControls.svelte +298 -325
  400. package/dist/structure/StructureControls.svelte.d.ts +5 -3
  401. package/dist/structure/StructureExportPane.svelte +62 -168
  402. package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
  403. package/dist/structure/StructureInfoPane.svelte +77 -69
  404. package/dist/structure/StructureInfoPane.svelte.d.ts +6 -6
  405. package/dist/structure/StructureScene.svelte +758 -600
  406. package/dist/structure/StructureScene.svelte.d.ts +24 -20
  407. package/dist/structure/StructureViewport.svelte +386 -0
  408. package/dist/structure/StructureViewport.svelte.d.ts +63 -0
  409. package/dist/structure/atom-label-placement.d.ts +18 -0
  410. package/dist/structure/atom-label-placement.js +115 -0
  411. package/dist/structure/atom-properties.d.ts +3 -1
  412. package/dist/structure/atom-properties.js +115 -54
  413. package/dist/structure/bond-order-perception.js +2 -4
  414. package/dist/structure/bonding.d.ts +12 -2
  415. package/dist/structure/bonding.js +172 -73
  416. package/dist/structure/edit-history.d.ts +6 -0
  417. package/dist/structure/edit-history.js +27 -0
  418. package/dist/structure/export.d.ts +25 -4
  419. package/dist/structure/export.js +103 -153
  420. package/dist/structure/format-detect.d.ts +1 -0
  421. package/dist/structure/format-detect.js +22 -0
  422. package/dist/structure/geometry.d.ts +9 -0
  423. package/dist/structure/geometry.js +27 -0
  424. package/dist/structure/index.d.ts +18 -1
  425. package/dist/structure/index.js +15 -2
  426. package/dist/structure/measure.d.ts +1 -1
  427. package/dist/structure/measure.js +6 -12
  428. package/dist/structure/parse.d.ts +5 -3
  429. package/dist/structure/parse.js +551 -567
  430. package/dist/structure/partial-occupancy.d.ts +0 -1
  431. package/dist/structure/partial-occupancy.js +5 -3
  432. package/dist/structure/pbc.d.ts +1 -1
  433. package/dist/structure/pbc.js +204 -51
  434. package/dist/structure/polyhedra.d.ts +40 -0
  435. package/dist/structure/polyhedra.js +587 -0
  436. package/dist/structure/site.d.ts +4 -0
  437. package/dist/structure/site.js +1 -0
  438. package/dist/structure/supercell.d.ts +1 -2
  439. package/dist/structure/supercell.js +10 -15
  440. package/dist/structure/validation.js +5 -6
  441. package/dist/symmetry/SymmetryElementControls.svelte +69 -0
  442. package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
  443. package/dist/symmetry/SymmetryElements.svelte +350 -0
  444. package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
  445. package/dist/symmetry/SymmetryStats.svelte +142 -49
  446. package/dist/symmetry/WyckoffTable.svelte +58 -16
  447. package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
  448. package/dist/symmetry/cell-transform.js +8 -14
  449. package/dist/symmetry/index.d.ts +15 -4
  450. package/dist/symmetry/index.js +308 -81
  451. package/dist/symmetry/spacegroups.d.ts +5 -1
  452. package/dist/symmetry/spacegroups.js +18 -3
  453. package/dist/symmetry/symmetry-elements.d.ts +33 -0
  454. package/dist/symmetry/symmetry-elements.js +521 -0
  455. package/dist/symmetry/wyckoff-db.d.ts +9 -0
  456. package/dist/symmetry/wyckoff-db.js +87 -0
  457. package/dist/table/HeatmapTable.svelte +1104 -378
  458. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  459. package/dist/table/ToggleMenu.svelte +5 -12
  460. package/dist/table/index.d.ts +21 -6
  461. package/dist/table/index.js +34 -21
  462. package/dist/theme/ThemeControl.svelte +16 -8
  463. package/dist/theme/index.d.ts +1 -5
  464. package/dist/theme/index.js +4 -10
  465. package/dist/theme/themes.mjs +14 -7
  466. package/dist/tooltip/KCoords.svelte +4 -1
  467. package/dist/tooltip/TooltipContent.svelte +2 -5
  468. package/dist/trajectory/Trajectory.svelte +556 -352
  469. package/dist/trajectory/Trajectory.svelte.d.ts +10 -22
  470. package/dist/trajectory/TrajectoryError.svelte +11 -8
  471. package/dist/trajectory/TrajectoryExportPane.svelte +28 -54
  472. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
  473. package/dist/trajectory/TrajectoryInfoPane.svelte +88 -99
  474. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
  475. package/dist/trajectory/constants.js +6 -2
  476. package/dist/trajectory/extract.js +73 -71
  477. package/dist/trajectory/format-detect.d.ts +0 -1
  478. package/dist/trajectory/format-detect.js +13 -17
  479. package/dist/trajectory/frame-reader.d.ts +2 -1
  480. package/dist/trajectory/frame-reader.js +74 -136
  481. package/dist/trajectory/helpers.d.ts +12 -2
  482. package/dist/trajectory/helpers.js +68 -37
  483. package/dist/trajectory/index.d.ts +1 -0
  484. package/dist/trajectory/index.js +3 -0
  485. package/dist/trajectory/parse/ase.d.ts +9 -1
  486. package/dist/trajectory/parse/ase.js +47 -32
  487. package/dist/trajectory/parse/diagnostics.d.ts +3 -0
  488. package/dist/trajectory/parse/diagnostics.js +14 -0
  489. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  490. package/dist/trajectory/parse/h5-utils.js +109 -0
  491. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  492. package/dist/trajectory/parse/hdf5.js +116 -106
  493. package/dist/trajectory/parse/index.d.ts +3 -4
  494. package/dist/trajectory/parse/index.js +68 -119
  495. package/dist/trajectory/parse/lammps.d.ts +0 -2
  496. package/dist/trajectory/parse/lammps.js +14 -16
  497. package/dist/trajectory/parse/pymatgen.d.ts +2 -0
  498. package/dist/trajectory/parse/pymatgen.js +74 -0
  499. package/dist/trajectory/parse/vasp.js +13 -9
  500. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  501. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  502. package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
  503. package/dist/trajectory/parse/vaspout-h5.js +284 -0
  504. package/dist/trajectory/parse/xyz.d.ts +9 -21
  505. package/dist/trajectory/parse/xyz.js +38 -39
  506. package/dist/trajectory/plotting.d.ts +8 -10
  507. package/dist/trajectory/plotting.js +102 -127
  508. package/dist/utils.d.ts +4 -0
  509. package/dist/utils.js +8 -1
  510. package/dist/xrd/XrdPlot.svelte +56 -85
  511. package/dist/xrd/broadening.d.ts +2 -1
  512. package/dist/xrd/broadening.js +2 -1
  513. package/dist/xrd/calc-xrd.js +8 -15
  514. package/dist/xrd/index.d.ts +2 -2
  515. package/dist/xrd/parse.d.ts +0 -1
  516. package/dist/xrd/parse.js +56 -73
  517. package/package.json +77 -36
  518. package/dist/api/mp.d.ts +0 -6
  519. package/dist/api/mp.js +0 -22
  520. package/dist/element/data.json +0 -11864
  521. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  522. package/dist/fermi-surface/marching-cubes.js +0 -2
  523. package/dist/plot/core/hover-lock.svelte.d.ts +0 -14
  524. package/dist/plot/core/hover-lock.svelte.js +0 -45
  525. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
  526. package/dist/structure/label-placement.d.ts +0 -14
  527. package/dist/structure/label-placement.js +0 -72
@@ -7,13 +7,21 @@
7
7
  import Icon from '../Icon.svelte'
8
8
  import { format_num } from '../labels'
9
9
  import { sanitize_html } from '../sanitize'
10
+ import { escape_html } from '../utils'
10
11
  import Histogram from '../plot/histogram/Histogram.svelte'
11
12
  import type { Label, RowData } from '../table'
12
13
  import HeatmapTable from '../table/HeatmapTable.svelte'
13
14
  import type { HTMLAttributes } from 'svelte/elements'
14
- import { SvelteMap, SvelteSet } from 'svelte/reactivity'
15
- import type { ConvexHullEntry, PhaseArityField, PhaseStats } from './types'
16
- import { get_arity, is_on_hull } from './helpers'
15
+ import { SvelteMap } from 'svelte/reactivity'
16
+ import { create_clipboard_feedback } from '../overlays'
17
+ import type {
18
+ ConvexHullEntry,
19
+ EntryCategoryConfig,
20
+ PhaseArityField,
21
+ PhaseStats,
22
+ } from './types'
23
+ import { MAGNETIC_ORDERING_CATEGORY } from './types'
24
+ import { get_arity, is_on_hull, visible_entries as filter_visible } from './helpers'
17
25
 
18
26
  let {
19
27
  phase_stats,
@@ -21,58 +29,54 @@
21
29
  unstable_entries,
22
30
  show_stable = true,
23
31
  show_unstable = true,
32
+ entry_category = MAGNETIC_ORDERING_CATEGORY,
33
+ hidden_categories = [],
24
34
  layout = `toggle`,
25
35
  on_entry_click,
26
36
  highlighted_entry_id,
27
37
  min_n_elements = $bindable(1),
28
38
  entry_href,
29
39
  ...rest
30
- }:
31
- & HTMLAttributes<HTMLDivElement>
32
- & {
33
- phase_stats: PhaseStats | null
34
- stable_entries: ConvexHullEntry[]
35
- unstable_entries: ConvexHullEntry[]
36
- show_stable?: boolean
37
- show_unstable?: boolean
38
- // 'toggle' shows stats/table with toggle buttons (default)
39
- // 'side-by-side' shows both stats and table next to each other without toggle
40
- layout?: `toggle` | `side-by-side`
41
- // Called when a table row is clicked, with the corresponding entry
42
- on_entry_click?: (entry: ConvexHullEntry) => void
43
- // Entry ID to highlight in the table (e.g. current material on detail page)
44
- highlighted_entry_id?: string
45
- // Minimum number of elements filter for table (bindable for URL sync)
46
- min_n_elements?: number
47
- // Generate URL for an entry (makes ID column a clickable link)
48
- entry_href?: (entry: ConvexHullEntry) => string | null
49
- } = $props()
40
+ }: HTMLAttributes<HTMLDivElement> & {
41
+ phase_stats: PhaseStats | null
42
+ stable_entries: ConvexHullEntry[]
43
+ unstable_entries: ConvexHullEntry[]
44
+ show_stable?: boolean
45
+ show_unstable?: boolean
46
+ // Categorical classification + hidden values (excluded from shown counts/table)
47
+ entry_category?: EntryCategoryConfig | null
48
+ hidden_categories?: string[]
49
+ // 'toggle' shows stats/table with toggle buttons (default)
50
+ // 'side-by-side' shows both stats and table next to each other without toggle
51
+ layout?: `toggle` | `side-by-side`
52
+ // Called when a table row is clicked, with the corresponding entry
53
+ on_entry_click?: (entry: ConvexHullEntry) => void
54
+ // Entry ID to highlight in the table (e.g. current material on detail page)
55
+ highlighted_entry_id?: string
56
+ // Minimum number of elements filter for table (bindable for URL sync)
57
+ min_n_elements?: number
58
+ // Generate URL for an entry (makes ID column a clickable link)
59
+ entry_href?: (entry: ConvexHullEntry) => string | null
60
+ } = $props()
50
61
 
51
- let copied_items = new SvelteSet<string>()
62
+ const { copied, copy } = create_clipboard_feedback()
52
63
  let view_mode = $state<`stats` | `table`>(`stats`)
53
64
  // Formula filter: when set, table shows only entries with this reduced formula
54
65
  let formula_filter = $state(``)
55
- let show_export_dropdown = $state(false)
56
- const table_scroll_height =
57
- `var(--hull-stats-table-height, calc(var(--hull-stats-table-row-height, 2.35rem) * 10 + var(--hull-stats-table-header-height, 3.5rem)))`
58
- const table_scroll_style = $derived(layout === `side-by-side`
59
- ? `flex: 1 1 0; height: ${table_scroll_height}; min-height: ${table_scroll_height}; max-width: 100%; overflow: auto`
60
- : `height: ${table_scroll_height}; min-height: ${table_scroll_height}; max-height: var(--hull-stats-max-height, 70vh); max-width: 100%; overflow: auto`
66
+ const table_scroll_height = `var(--hull-stats-table-height, calc(var(--hull-stats-table-row-height, 2.35rem) * 10 + var(--hull-stats-table-header-height, 3.5rem)))`
67
+ const table_scroll_style = $derived(
68
+ layout === `side-by-side`
69
+ ? `flex: 1 1 0; height: ${table_scroll_height}; min-height: ${table_scroll_height}; max-width: 100%; overflow: auto`
70
+ : `height: ${table_scroll_height}; min-height: ${table_scroll_height}; max-height: var(--hull-stats-max-height, 70vh); max-width: 100%; overflow: auto`,
61
71
  )
62
- const table_root_style = $derived(layout === `side-by-side`
63
- ? `flex: 1 1 0; min-height: ${table_scroll_height}; margin-inline: 0`
64
- : `min-width: 0; margin-inline: 0`
72
+ const table_root_style = $derived(
73
+ layout === `side-by-side`
74
+ ? `flex: 1 1 0; min-height: ${table_scroll_height}; margin-inline: 0`
75
+ : `min-width: 0; margin-inline: 0`,
65
76
  )
66
77
 
67
- async function copy_to_clipboard(label: string, value: string, key: string) {
68
- try {
69
- await navigator.clipboard.writeText(`${label}: ${value}`)
70
- copied_items.add(key)
71
- setTimeout(() => copied_items.delete(key), 1000)
72
- } catch (error) {
73
- console.error(`Failed to copy to clipboard:`, error)
74
- }
75
- }
78
+ const copy_to_clipboard = (label: string, value: string, key: string): Promise<void> =>
79
+ copy(`${label}: ${value}`, key)
76
80
  function handle_copy_keydown(
77
81
  event: KeyboardEvent,
78
82
  label: string,
@@ -86,10 +90,17 @@
86
90
 
87
91
  // Shared concatenation of stable + unstable for histograms
88
92
  let all_entries = $derived([...stable_entries, ...unstable_entries])
89
- let shown_entries = $derived([
90
- ...(show_stable ? stable_entries : []),
91
- ...(show_unstable ? unstable_entries : []),
92
- ])
93
+ // show_stable/show_unstable respect the caller's partition; pass show flags as true
94
+ // so filter_visible only applies the category filter on top
95
+ let shown_entries = $derived(
96
+ filter_visible(
97
+ [...(show_stable ? stable_entries : []), ...(show_unstable ? unstable_entries : [])],
98
+ true,
99
+ true,
100
+ entry_category,
101
+ hidden_categories,
102
+ ),
103
+ )
93
104
 
94
105
  // Static arity labels for phase breakdown display
95
106
  const arity_types: [string, PhaseArityField, number][] = [
@@ -110,21 +121,25 @@
110
121
  } as const
111
122
 
112
123
  // Prepare histogram data for formation energies and hull distances
113
- let e_form_data = $derived([{
114
- x: [] as number[],
115
- y: all_entries
116
- .map((entry) => entry.e_form_per_atom ?? entry.energy_per_atom)
117
- .filter((val): val is number => val !== undefined && isFinite(val)),
118
- label: `Formation Energy`,
119
- }])
124
+ let e_form_data = $derived([
125
+ {
126
+ x: [] as number[],
127
+ y: all_entries
128
+ .map((entry) => entry.e_form_per_atom ?? entry.energy_per_atom)
129
+ .filter((val): val is number => val !== undefined && isFinite(val)),
130
+ label: `Formation Energy`,
131
+ },
132
+ ])
120
133
 
121
- let hull_distance_data = $derived([{
122
- x: [] as number[],
123
- y: all_entries
124
- .map((entry) => entry.e_above_hull)
125
- .filter((val): val is number => val !== undefined && isFinite(val)),
126
- label: `E above hull`,
127
- }])
134
+ let hull_distance_data = $derived([
135
+ {
136
+ x: [] as number[],
137
+ y: all_entries
138
+ .map((entry) => entry.e_above_hull)
139
+ .filter((val): val is number => val !== undefined && isFinite(val)),
140
+ label: `E above hull`,
141
+ },
142
+ ])
128
143
 
129
144
  let pane_data = $derived.by(() => {
130
145
  if (!phase_stats) return []
@@ -144,8 +159,8 @@
144
159
  // Only show phase types that exist or are within the max_arity
145
160
  // used when computing stats (respects zeroed-out counts)
146
161
  ...arity_types
147
- .filter(([, field, arity]) =>
148
- phase_stats[field] > 0 || phase_stats.max_arity >= arity
162
+ .filter(
163
+ ([, field, arity]) => phase_stats[field] > 0 || phase_stats.max_arity >= arity,
149
164
  )
150
165
  .map(([display, field]) => ({
151
166
  label: `${display} phases`,
@@ -164,34 +179,38 @@
164
179
  },
165
180
  {
166
181
  label: `Unstable phases`,
167
- value: `${format_num(phase_stats.unstable)} (${
168
- pct(phase_stats.unstable)
169
- })`,
182
+ value: `${format_num(phase_stats.unstable)} (${pct(phase_stats.unstable)})`,
170
183
  key: `unstable-phases`,
171
184
  },
172
185
  ],
173
186
  },
174
187
  {
175
188
  title: `E<sub>form</sub> distribution`,
176
- items: [{
177
- label: `Min / avg / max (eV/atom)`,
178
- value: [
179
- phase_stats.energy_range.min,
180
- phase_stats.energy_range.avg,
181
- phase_stats.energy_range.max,
182
- ]
183
- .map((val) => format_num(val, `.3f`)).join(` / `),
184
- key: `formation-energy`,
185
- }],
189
+ items: [
190
+ {
191
+ label: `Min / avg / max (eV/atom)`,
192
+ value: [
193
+ phase_stats.energy_range.min,
194
+ phase_stats.energy_range.avg,
195
+ phase_stats.energy_range.max,
196
+ ]
197
+ .map((val) => format_num(val, `.3f`))
198
+ .join(` / `),
199
+ key: `formation-energy`,
200
+ },
201
+ ],
186
202
  },
187
203
  {
188
204
  title: `E<sub>above hull</sub> distribution`,
189
- items: [{
190
- label: `Max / avg (eV/atom)`,
191
- value: [phase_stats.hull_distance.max, phase_stats.hull_distance.avg]
192
- .map((val) => format_num(val, `.3f`)).join(` / `),
193
- key: `hull-distance`,
194
- }],
205
+ items: [
206
+ {
207
+ label: `Max / avg (eV/atom)`,
208
+ value: [phase_stats.hull_distance.max, phase_stats.hull_distance.avg]
209
+ .map((val) => format_num(val, `.3f`))
210
+ .join(` / `),
211
+ key: `hull-distance`,
212
+ },
213
+ ],
195
214
  },
196
215
  ]
197
216
  })
@@ -204,9 +223,9 @@
204
223
  // Count entries containing each pair
205
224
  const pair_counts = new SvelteMap<string, number>()
206
225
  for (const entry of all_entries) {
207
- const active =
208
- (Object.keys(entry.composition) as (keyof typeof entry.composition)[])
209
- .filter((el) => (entry.composition[el] ?? 0) > 0)
226
+ const active = (
227
+ Object.keys(entry.composition) as (keyof typeof entry.composition)[]
228
+ ).filter((el) => (entry.composition[el] ?? 0) > 0)
210
229
  // Count all pairs present in this entry
211
230
  for (let idx_a = 0; idx_a < active.length; idx_a++) {
212
231
  for (let idx_b = idx_a + 1; idx_b < active.length; idx_b++) {
@@ -220,12 +239,11 @@
220
239
  elements.slice(idx_a + 1).map((el_b) => {
221
240
  const key = [el_a, el_b].sort().join(`-`)
222
241
  return { pair: key, count: pair_counts.get(key) ?? 0 }
223
- })
242
+ }),
224
243
  )
225
244
  })
226
245
  let subsystem_coverage_summary = $derived(
227
- subsystem_coverage?.map(({ pair, count }) => `${pair}: ${count}`).join(` | `) ??
228
- null,
246
+ subsystem_coverage?.map(({ pair, count }) => `${pair}: ${count}`).join(` | `) ?? null,
229
247
  )
230
248
 
231
249
  // Table view: visible entries filtered by min element count and formula
@@ -235,13 +253,12 @@
235
253
  if (
236
254
  active_formula_filter &&
237
255
  composition_key(entry.composition) !== active_formula_filter
238
- ) return false
256
+ )
257
+ return false
239
258
  return true
240
259
  }),
241
260
  )
242
- let has_raw = $derived(
243
- visible_entries.some((entry) => entry.energy_per_atom !== undefined),
244
- )
261
+ let has_raw = $derived(visible_entries.some((entry) => entry.energy_per_atom !== undefined))
245
262
  let has_ids = $derived(visible_entries.some((entry) => entry.entry_id))
246
263
  let max_n_el = $derived(
247
264
  all_entries.reduce((max, entry) => Math.max(max, get_arity(entry)), 1),
@@ -251,14 +268,6 @@
251
268
  const sort_span = (sort_val: number | string, display: string, attrs = ``) =>
252
269
  `<span data-sort-value="${sort_val}"${attrs ? ` ${attrs}` : ``}>${display}</span>`
253
270
 
254
- // Escape HTML special chars to prevent XSS when rendering user-supplied strings via {@html}
255
- const escape_html = (str: string): string =>
256
- str
257
- .replaceAll('&', `&amp;`)
258
- .replaceAll('<', `&lt;`)
259
- .replaceAll('>', `&gt;`)
260
- .replaceAll('"', `&quot;`)
261
- .replaceAll('\'', `&#39;`)
262
271
  const unescape_html = (str: string, max_rounds = 5): string => {
263
272
  let decoded = str
264
273
  for (let round_idx = 0; round_idx < max_rounds; round_idx++) {
@@ -277,7 +286,7 @@
277
286
  // stoichiometric input before parsing/reordering.
278
287
  const normalize_formula_markup = (formula: string): string =>
279
288
  unescape_html(formula)
280
- .replaceAll(/<sub>\s*([^<]+?)\s*<\/sub>/gi, `$1`)
289
+ .replaceAll(/<sub>\s*(?<content>[^<]+?)\s*<\/sub>/gi, `$1`)
281
290
  .replaceAll(/<[^>]+>/g, ``)
282
291
  .replaceAll(/\s+/g, ``)
283
292
  const sanitize_href = (href: string | null | undefined): string | null => {
@@ -309,9 +318,7 @@
309
318
  let has_polymorphs = $derived(poly_formulas.length > 0)
310
319
  let active_formula_filter = $derived.by(() => {
311
320
  if (!formula_filter || !has_polymorphs) return ``
312
- return poly_formulas.some(([formula]) => formula === formula_filter)
313
- ? formula_filter
314
- : ``
321
+ return poly_formulas.some(([formula]) => formula === formula_filter) ? formula_filter : ``
315
322
  })
316
323
  $effect(() => {
317
324
  if (formula_filter && formula_filter !== active_formula_filter) {
@@ -323,12 +330,11 @@
323
330
  let { table_data, entry_by_row } = $derived.by(() => {
324
331
  const map = new WeakMap<RowData, ConvexHullEntry>()
325
332
  const rows = visible_entries.map((entry, idx) => {
326
- const n_atoms = Object.values(entry.composition).reduce(
327
- (sum, count) => sum + count,
328
- 0,
329
- )
333
+ const n_atoms = Object.values(entry.composition).reduce((sum, count) => sum + count, 0)
330
334
  const on_hull = is_on_hull(entry)
331
- const formula_source = entry.reduced_formula ?? entry.name ??
335
+ const formula_source =
336
+ entry.reduced_formula ??
337
+ entry.name ??
332
338
  get_alphabetical_formula(entry.composition, true, ``)
333
339
  const normalized_formula = normalize_formula_markup(formula_source)
334
340
  const formatted_formula = get_electro_neg_formula(normalized_formula)
@@ -336,11 +342,12 @@
336
342
  // Match by entry_id or common data fields (mat_id, structure_id)
337
343
  // since entry_id may be wrapped in HTML (e.g. <a> tags)
338
344
  const entry_data = entry.data as Record<string, unknown> | undefined
339
- const is_highlighted = Boolean(highlighted_entry_id && (
340
- entry.entry_id === highlighted_entry_id ||
341
- entry_data?.mat_id === highlighted_entry_id ||
342
- entry_data?.structure_id === highlighted_entry_id
343
- ))
345
+ const is_highlighted = Boolean(
346
+ highlighted_entry_id &&
347
+ (entry.entry_id === highlighted_entry_id ||
348
+ entry_data?.mat_id === highlighted_entry_id ||
349
+ entry_data?.structure_id === highlighted_entry_id),
350
+ )
344
351
  const row: RowData = {
345
352
  '#': sort_span(idx + 1, `${idx + 1}`),
346
353
  Formula: on_hull ? `<strong>${formula_html}</strong>` : formula_html,
@@ -351,11 +358,12 @@
351
358
  if (has_ids) {
352
359
  const safe_href = sanitize_href(entry_href?.(entry))
353
360
  const safe_id = entry.entry_id ? escape_html(entry.entry_id) : undefined
354
- row.ID = safe_href && safe_id
355
- ? `<a href="${
356
- escape_html(safe_href)
357
- }" target="_blank" rel="noopener">${safe_id}</a>`
358
- : safe_id
361
+ row.ID =
362
+ safe_href && safe_id
363
+ ? `<a href="${escape_html(
364
+ safe_href,
365
+ )}" target="_blank" rel="noopener">${safe_id}</a>`
366
+ : safe_id
359
367
  }
360
368
  if (has_polymorphs) {
361
369
  const comp_key = composition_key(entry.composition)
@@ -366,8 +374,7 @@
366
374
  row[`N<sub>at</sub>`] = n_atoms
367
375
  // Highlight row for current material
368
376
  if (is_highlighted) {
369
- row.style =
370
- `background: color-mix(in srgb, var(--hull-stable-color, #22c55e) 15%, transparent)`
377
+ row.style = `background: color-mix(in srgb, var(--hull-stable-color, #22c55e) 15%, transparent)`
371
378
  }
372
379
  map.set(row, entry)
373
380
  return row
@@ -380,117 +387,60 @@
380
387
  if (entry) on_entry_click?.(entry)
381
388
  }
382
389
 
383
- let table_columns: Label[] = $derived(
384
- [
385
- { label: `#`, color_scale: null, description: `Row number` },
386
- { label: `Formula`, color_scale: null },
387
- {
388
- label: `E<sub>hull</sub>`,
389
- better: `lower`,
390
- color_scale: `interpolateRdYlGn`,
391
- format: `.4f`,
392
- description: `Energy above convex hull (eV/atom)`,
393
- },
394
- {
395
- label: `E<sub>form</sub>`,
396
- better: `lower`,
397
- color_scale: `interpolateBlues`,
398
- format: `.4f`,
399
- description: `Formation energy (eV/atom)`,
400
- },
401
- ...(has_raw
402
- ? [{
403
- label: `E<sub>raw</sub>`,
404
- color_scale: `interpolateCool` as const,
405
- format: `.4f`,
406
- description: `Raw energy per atom (eV/atom)`,
407
- }]
408
- : []),
409
- ...(has_ids
410
- ? [{ label: `ID`, color_scale: null, description: `Entry identifier` }]
411
- : []),
412
- ...(has_polymorphs
413
- ? [{
414
- label: `Poly`,
415
- color_scale: null,
416
- description: `Number of polymorphs (same reduced formula)`,
417
- }]
418
- : []),
419
- {
420
- label: `N<sub>el</sub>`,
421
- color_scale: null,
422
- description: `Number of elements`,
423
- },
424
- {
425
- label: `N<sub>at</sub>`,
426
- color_scale: null,
427
- format: `d`,
428
- description: `Number of atoms in unit cell`,
429
- },
430
- ] satisfies Label[],
431
- )
390
+ let table_columns: Label[] = $derived([
391
+ { label: `#`, color_scale: null, description: `Row number` },
392
+ { label: `Formula`, color_scale: null },
393
+ {
394
+ label: `E<sub>hull</sub>`,
395
+ better: `lower`,
396
+ color_scale: `interpolateRdYlGn`,
397
+ format: `.4f`,
398
+ description: `Energy above convex hull (eV/atom)`,
399
+ },
400
+ {
401
+ label: `E<sub>form</sub>`,
402
+ better: `lower`,
403
+ color_scale: `interpolateBlues`,
404
+ format: `.4f`,
405
+ description: `Formation energy (eV/atom)`,
406
+ },
407
+ ...(has_raw
408
+ ? [
409
+ {
410
+ label: `E<sub>raw</sub>`,
411
+ color_scale: `interpolateCool` as const,
412
+ format: `.4f`,
413
+ description: `Raw energy per atom (eV/atom)`,
414
+ },
415
+ ]
416
+ : []),
417
+ ...(has_ids ? [{ label: `ID`, color_scale: null, description: `Entry identifier` }] : []),
418
+ ...(has_polymorphs
419
+ ? [
420
+ {
421
+ label: `Poly`,
422
+ color_scale: null,
423
+ description: `Number of polymorphs (same reduced formula)`,
424
+ },
425
+ ]
426
+ : []),
427
+ {
428
+ label: `N<sub>el</sub>`,
429
+ color_scale: null,
430
+ description: `Number of elements`,
431
+ },
432
+ {
433
+ label: `N<sub>at</sub>`,
434
+ color_scale: null,
435
+ format: `d`,
436
+ description: `Number of atoms in unit cell`,
437
+ },
438
+ ] satisfies Label[])
432
439
 
433
- const html_to_text = (val: unknown): string => {
434
- if (val == null) return ``
435
- if (typeof val !== `string`) return String(val)
436
- const temp_el = document.createElement(`div`)
437
- temp_el.innerHTML = val
438
- return temp_el.textContent?.trim() ?? ``
439
- }
440
- const csv_escape = (val: string): string =>
441
- /[",\n]/.test(val) ? `"${val.replaceAll(`"`, `""`)}"` : val
442
- const get_export_filename = (format: `csv` | `json`): string => {
443
- const system = (phase_stats?.chemical_system ?? `convex-hull-stats`)
444
- .toLowerCase()
445
- .replaceAll(/\s+/g, `-`)
446
- return `${system}.${format}`
447
- }
448
- const build_export_rows = () => {
449
- const column_labels = table_columns.map((col) => col.label)
450
- return table_data.map((row) =>
451
- Object.fromEntries(
452
- column_labels.map((label) => [html_to_text(label), html_to_text(row[label])]),
453
- )
454
- )
455
- }
456
- const download_file = (
457
- content: string,
458
- filename: string,
459
- mime_type: string,
460
- ): void => {
461
- const blob = new Blob([content], { type: mime_type })
462
- const object_url = URL.createObjectURL(blob)
463
- const link_el = document.createElement(`a`)
464
- link_el.href = object_url
465
- link_el.download = filename
466
- document.body.append(link_el)
467
- link_el.click()
468
- link_el.remove()
469
- URL.revokeObjectURL(object_url)
470
- }
471
- function export_table(format: `csv` | `json`): void {
472
- const rows = build_export_rows()
473
- if (format === `json`) {
474
- download_file(
475
- JSON.stringify(rows, null, 2),
476
- get_export_filename(`json`),
477
- `application/json;charset=utf-8`,
478
- )
479
- return
480
- }
481
- const headers = rows.length > 0 ? Object.keys(rows[0]) : []
482
- const csv_lines = [
483
- headers.map(csv_escape).join(`,`),
484
- ...rows.map((row) =>
485
- headers.map((header) => csv_escape(row[header] ?? ``)).join(`,`)
486
- ),
487
- ]
488
- download_file(
489
- csv_lines.join(`\n`),
490
- get_export_filename(`csv`),
491
- `text/csv;charset=utf-8`,
492
- )
493
- }
440
+ // Filename for HeatmapTable's built-in CSV/JSON export
441
+ const export_filename = $derived(
442
+ phase_stats?.chemical_system?.toLowerCase().replaceAll(/\s+/g, `-`) ?? `convex-hull-stats`,
443
+ )
494
444
  </script>
495
445
 
496
446
  {#snippet stats_panel()}
@@ -510,16 +460,11 @@
510
460
  role="button"
511
461
  tabindex="0"
512
462
  onkeydown={(event) =>
513
- handle_copy_keydown(
514
- event,
515
- item.label,
516
- String(item.value),
517
- key ?? item.label,
518
- )}
463
+ handle_copy_keydown(event, item.label, String(item.value), key ?? item.label)}
519
464
  >
520
465
  <span>{@html sanitize_html(label)}:</span>
521
466
  <span>{@html sanitize_html(value)}</span>
522
- {#if key && copied_items.has(key)}
467
+ {#if key && copied.has(key)}
523
468
  <Icon
524
469
  icon="Check"
525
470
  style="color: var(--success-color, #10b981); width: 12px; height: 12px"
@@ -535,23 +480,24 @@
535
480
  data-testid="pd-binary-subsystem-coverage"
536
481
  title="Click to copy: Binary subsystem coverage: {subsystem_coverage_summary ?? ``}"
537
482
  onclick={() =>
538
- copy_to_clipboard(
539
- `Binary subsystem coverage`,
540
- subsystem_coverage_summary ?? ``,
541
- `binary-subsystem-coverage`,
542
- )}
483
+ copy_to_clipboard(
484
+ `Binary subsystem coverage`,
485
+ subsystem_coverage_summary ?? ``,
486
+ `binary-subsystem-coverage`,
487
+ )}
543
488
  role="button"
544
489
  tabindex="0"
545
490
  onkeydown={(event) =>
546
- handle_copy_keydown(
547
- event,
548
- `Binary subsystem coverage`,
549
- subsystem_coverage_summary ?? ``,
550
- `binary-subsystem-coverage`,
551
- )}
491
+ handle_copy_keydown(
492
+ event,
493
+ `Binary subsystem coverage`,
494
+ subsystem_coverage_summary ?? ``,
495
+ `binary-subsystem-coverage`,
496
+ )}
552
497
  >
553
498
  <span class="subsystem-label"
554
- >Binary subsystem coverage ({subsystem_coverage.length} pairs)</span>
499
+ >Binary subsystem coverage ({subsystem_coverage.length} pairs)</span
500
+ >
555
501
  <span class="subsystem-chips">
556
502
  {#each subsystem_coverage as { pair, count } (pair)}
557
503
  <span class="subsystem-chip" class:has-entries={count > 0}>
@@ -560,7 +506,7 @@
560
506
  </span>
561
507
  {/each}
562
508
  </span>
563
- {#if copied_items.has(`binary-subsystem-coverage`)}
509
+ {#if copied.has(`binary-subsystem-coverage`)}
564
510
  <Icon
565
511
  icon="Check"
566
512
  style="color: var(--success-color, #10b981); width: 12px; height: 12px"
@@ -570,8 +516,7 @@
570
516
  </div>
571
517
  {/if}
572
518
 
573
- {#if section.title === `E<sub>form</sub> distribution` &&
574
- e_form_data[0].y.length > 0}
519
+ {#if section.title === `E<sub>form</sub> distribution` && e_form_data[0].y.length > 0}
575
520
  <Histogram
576
521
  {...histogram_props}
577
522
  series={e_form_data}
@@ -580,8 +525,7 @@
580
525
  />
581
526
  {/if}
582
527
 
583
- {#if section.title === `E<sub>above hull</sub> distribution` &&
584
- hull_distance_data[0].y.length > 0}
528
+ {#if section.title === `E<sub>above hull</sub> distribution` && hull_distance_data[0].y.length > 0}
585
529
  <Histogram
586
530
  {...histogram_props}
587
531
  series={hull_distance_data}
@@ -617,39 +561,6 @@
617
561
  </label>
618
562
  {/if}
619
563
  <span class="filter-count">{visible_entries.length} entries</span>
620
- <span class="filter-spacer"></span>
621
- <div class="export-actions">
622
- <button
623
- class="icon-btn"
624
- class:active={show_export_dropdown}
625
- title="Export"
626
- onclick={() => show_export_dropdown = !show_export_dropdown}
627
- >
628
- <Icon icon="Export" style="width: 14px" />
629
- </button>
630
- {#if show_export_dropdown}
631
- <div class="export-dropdown">
632
- <button
633
- class="dropdown-option"
634
- onclick={() => {
635
- export_table(`csv`)
636
- show_export_dropdown = false
637
- }}
638
- >
639
- <Icon icon="Download" style="width: 12px" /> CSV
640
- </button>
641
- <button
642
- class="dropdown-option"
643
- onclick={() => {
644
- export_table(`json`)
645
- show_export_dropdown = false
646
- }}
647
- >
648
- <Icon icon="Download" style="width: 12px" /> JSON
649
- </button>
650
- </div>
651
- {/if}
652
- </div>
653
564
  </div>
654
565
  <HeatmapTable
655
566
  data={table_data}
@@ -659,12 +570,12 @@
659
570
  style="width: 100%"
660
571
  root_style={table_root_style}
661
572
  onrowclick={on_entry_click ? handle_row_click : undefined}
662
- export_data={false}
573
+ export_data={{ filename: export_filename }}
663
574
  />
664
575
  {/snippet}
665
576
 
666
577
  {#if layout === `side-by-side`}
667
- <div {...rest} class="convex-hull-stats side-by-side {rest.class ?? ``}">
578
+ <div {...rest} class={[`convex-hull-stats side-by-side`, rest.class]}>
668
579
  <div class="stats-pane">
669
580
  {@render stats_panel()}
670
581
  </div>
@@ -673,12 +584,12 @@
673
584
  </div>
674
585
  </div>
675
586
  {:else}
676
- <div {...rest} class="convex-hull-stats {rest.class ?? ``}">
587
+ <div {...rest} class={[`convex-hull-stats`, rest.class]}>
677
588
  <div class="view-toggle">
678
- <button class:active={view_mode === `stats`} onclick={() => view_mode = `stats`}>
589
+ <button class:active={view_mode === `stats`} onclick={() => (view_mode = `stats`)}>
679
590
  Stats
680
591
  </button>
681
- <button class:active={view_mode === `table`} onclick={() => view_mode = `table`}>
592
+ <button class:active={view_mode === `table`} onclick={() => (view_mode = `table`)}>
682
593
  Table
683
594
  </button>
684
595
  </div>
@@ -716,7 +627,13 @@
716
627
  .table-pane {
717
628
  flex: 1 1 0;
718
629
  max-width: 100%;
719
- min-height: var(--hull-stats-table-height, calc(var(--hull-stats-table-row-height, 2.35rem) * 10 + var(--hull-stats-table-header-height, 3.5rem)));
630
+ min-height: var(
631
+ --hull-stats-table-height,
632
+ calc(
633
+ var(--hull-stats-table-row-height, 2.35rem) * 10 +
634
+ var(--hull-stats-table-header-height, 3.5rem)
635
+ )
636
+ );
720
637
  min-width: 0;
721
638
  overflow: auto;
722
639
  display: flex;
@@ -826,64 +743,6 @@
826
743
  font-size: inherit;
827
744
  }
828
745
  }
829
- .filter-spacer {
830
- flex: 1 1 auto;
831
- }
832
- .export-actions {
833
- position: relative;
834
- .icon-btn {
835
- padding: 2pt 6pt;
836
- border: 1px solid
837
- var(--hull-stats-border-color, color-mix(in srgb, currentColor 20%, transparent));
838
- border-radius: 3pt;
839
- background: transparent;
840
- color: inherit;
841
- cursor: pointer;
842
- display: inline-flex;
843
- align-items: center;
844
- justify-content: center;
845
- }
846
- .icon-btn:hover {
847
- background: color-mix(in srgb, currentColor 8%, transparent);
848
- }
849
- .icon-btn.active {
850
- background: color-mix(in srgb, currentColor 12%, transparent);
851
- }
852
- }
853
- .export-dropdown {
854
- position: absolute;
855
- right: 0;
856
- top: calc(100% + 4px);
857
- display: flex;
858
- flex-direction: column;
859
- min-width: 88px;
860
- padding: 3pt;
861
- border: 1px solid
862
- var(--hull-stats-border-color, color-mix(in srgb, currentColor 20%, transparent));
863
- border-radius: 4pt;
864
- background: var(--page-bg, Canvas);
865
- z-index: 4;
866
- box-shadow: 0 2px 8px color-mix(in srgb, black 20%, transparent);
867
- .dropdown-option {
868
- display: inline-flex;
869
- align-items: center;
870
- gap: 5px;
871
- border: none;
872
- border-radius: 3pt;
873
- background: transparent;
874
- color: inherit;
875
- cursor: pointer;
876
- text-align: left;
877
- padding: 3pt 6pt;
878
- }
879
- .dropdown-option:hover {
880
- background: color-mix(in srgb, currentColor 8%, transparent);
881
- }
882
- }
883
- .table-pane :global(.control-buttons) {
884
- display: none;
885
- margin: 0;
886
- }
887
746
  .filter-count {
888
747
  color: var(--text-color-muted, light-dark(#666, #bbb));
889
748
  font-size: 0.9em;