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
@@ -1,30 +1,115 @@
1
- import { get_d3_interpolator } from '../colors';
1
+ import { add_alpha, get_d3_interpolator } from '../colors';
2
2
  import { ELEM_SYMBOL_TO_NAME } from '../composition';
3
3
  import { format_fractional, format_num, symbol_map } from '../labels';
4
4
  import { scaleSequential } from 'd3-scale';
5
5
  import { symbol } from 'd3-shape';
6
- import { analyze_gas_data as _analyze_gas_data, apply_gas_corrections as _apply_gas_corrections, } from './gas-thermodynamics';
7
- import { DEFAULT_GAS_TEMP } from './types';
8
- export { DEFAULT_GAS_TEMP };
6
+ import { analyze_gas_data, apply_gas_corrections } from './gas-thermodynamics';
7
+ import { MAGNETIC_ORDERING_CATEGORY } from './types';
8
+ export { DEFAULT_GAS_TEMP } from './types';
9
9
  // Tolerance for classifying a phase as on the convex hull (eV/atom)
10
10
  export const HULL_STABILITY_TOL = 1e-6;
11
11
  // Clamp raw hull distance and compute stability for a single entry.
12
12
  // Excluded entries keep their raw (possibly negative) distance and are never stable.
13
13
  export function compute_hull_stability(raw_distance, exclude_from_hull, tol = HULL_STABILITY_TOL) {
14
+ // unknown distance (degenerate hull / point outside hull projection / missing energy):
15
+ // not 0/stable — leave both undefined so it isn't mislabeled on-hull
16
+ if (raw_distance == null || !Number.isFinite(raw_distance)) {
17
+ return { e_above_hull: undefined, is_stable: undefined };
18
+ }
14
19
  if (exclude_from_hull)
15
20
  return { e_above_hull: raw_distance, is_stable: false };
16
21
  const e_above_hull = Math.abs(raw_distance) < tol ? 0 : Math.max(0, raw_distance);
17
22
  return { e_above_hull, is_stable: e_above_hull <= tol };
18
23
  }
24
+ // Look up the original (un-projected) entry by id and return its structure if any.
25
+ // Shared by ConvexHull2D/3D/4D for the click-to-preview structure popup.
26
+ export const extract_structure_from_entry = (entries, entry) => {
27
+ if (!entry.entry_id)
28
+ return null;
29
+ const orig_entry = entries.find((ent) => ent.entry_id === entry.entry_id);
30
+ return orig_entry?.structure || null;
31
+ };
32
+ // Loop-based min/max — Math.min/max(...arr) blows the stack on large (>~100k) arrays
33
+ export const array_min = (values) => values.reduce((min, val) => (val < min ? val : min), Infinity);
34
+ export const array_max = (values) => values.reduce((max, val) => (val > max ? val : max), -Infinity);
35
+ // [min, max] energy above hull across entries, for ColorBar ranges (max floored at 0.1).
36
+ // Filter to finite values: NaN/undefined distances would otherwise produce a broken range.
37
+ export const hull_distance_range = (entries) => {
38
+ const dists = entries
39
+ .map((entry) => entry.e_above_hull)
40
+ .filter((val) => typeof val === `number` && Number.isFinite(val));
41
+ return dists.length > 0 ? [array_min(dists), Math.max(array_max(dists), 0.1)] : [0, 0.1];
42
+ };
19
43
  export const entry_is_stable = (entry, tol = HULL_STABILITY_TOL) => entry.is_stable === true ||
20
44
  (entry.is_stable !== false && Math.abs(entry.e_above_hull ?? Infinity) <= tol);
45
+ // Whether to plot an entry at a given max hull distance: stable, or a finite distance
46
+ // within max_dist. Unknown distance (undefined) is excluded, not treated as 0/stable.
47
+ export const entry_within_hull_dist = (entry, max_dist) => entry_is_stable(entry) ||
48
+ (typeof entry.e_above_hull === `number` && entry.e_above_hull <= max_dist);
21
49
  // Check if entry is on the convex hull (stable or e_above_hull ≈ 0)
22
50
  export const is_on_hull = (entry, tol = HULL_STABILITY_TOL) => !entry.exclude_from_hull && entry_is_stable(entry, tol);
23
51
  export const get_arity = (entry) => Object.values(entry.composition).filter((count) => count > 0).length;
24
52
  export const is_unary_entry = (entry) => get_arity(entry) === 1;
25
53
  export const entry_is_unstable = (entry) => !entry_is_stable(entry);
26
- export const entry_is_visible = (entry, show_stable, show_unstable) => (entry_is_stable(entry) ? show_stable : show_unstable);
27
- export const visible_entries = (entries, show_stable, show_unstable) => entries.filter((entry) => entry_is_visible(entry, show_stable, show_unstable));
54
+ // Normalize a raw value to a canonical category value: case-insensitive match against
55
+ // config.markers keys, then config.aliases. Returns null for unrecognized values.
56
+ function normalize_category_value(raw, config) {
57
+ if (typeof raw !== `string`)
58
+ return null;
59
+ const lower = raw.trim().toLowerCase();
60
+ if (!lower)
61
+ return null;
62
+ const canonical = Object.keys(config.markers).find((value) => value.toLowerCase() === lower);
63
+ if (canonical)
64
+ return canonical;
65
+ const alias = config.aliases?.[lower];
66
+ return alias && alias in config.markers ? alias : null;
67
+ }
68
+ // Resolve an entry's category: first *recognized* value wins. Properties are checked in
69
+ // config order (property-major), each looked up top-level, then in the pymatgen `data`
70
+ // and Materials Project `attributes` dicts — so a `magnetic_ordering` in any source
71
+ // beats a generic `ordering`. Unrecognized values (e.g. MP's ordering='Unknown') fall
72
+ // through; returns null when none resolve.
73
+ export function get_entry_category(entry, config) {
74
+ if (!config)
75
+ return null;
76
+ const props = Array.isArray(config.property) ? config.property : [config.property];
77
+ for (const prop of props) {
78
+ for (const source of [entry, entry.data, entry.attributes]) {
79
+ if (!source)
80
+ continue;
81
+ const value = normalize_category_value(source[prop], config);
82
+ if (value)
83
+ return value;
84
+ }
85
+ }
86
+ return null;
87
+ }
88
+ // Assign default marker shapes by category (per config.markers). Explicit entry.marker
89
+ // values win. Returns the input array unchanged when no marker was assigned (e.g. when
90
+ // config is null or entries lack category data).
91
+ export function apply_category_markers(entries, config) {
92
+ if (!config)
93
+ return entries;
94
+ let any_assigned = false;
95
+ const result = entries.map((entry) => {
96
+ const value = entry.marker ? null : get_entry_category(entry, config);
97
+ if (!value)
98
+ return entry;
99
+ any_assigned = true;
100
+ return { ...entry, marker: config.markers[value] };
101
+ });
102
+ return any_assigned ? result : entries;
103
+ }
104
+ export const entry_is_visible = (entry, show_stable, show_unstable, category = null, hidden_categories = []) => {
105
+ if (!(entry_is_stable(entry) ? show_stable : show_unstable))
106
+ return false;
107
+ if (!category || hidden_categories.length === 0)
108
+ return true;
109
+ const value = get_entry_category(entry, category);
110
+ return value === null || !hidden_categories.includes(value);
111
+ };
112
+ export const visible_entries = (entries, show_stable, show_unstable, category = null, hidden_categories = []) => entries.filter((entry) => entry_is_visible(entry, show_stable, show_unstable, category, hidden_categories));
28
113
  // Energy color scale factory (shared)
29
114
  export function get_energy_color_scale(color_mode, color_scale, plot_entries) {
30
115
  if (color_mode !== `energy` || plot_entries.length === 0)
@@ -95,8 +180,8 @@ export function compute_auto_hull_dist_threshold(n_entries, max_hull_dist_in_dat
95
180
  return max_hull_dist_in_data;
96
181
  if (n_entries >= HIGH)
97
182
  return static_default;
98
- const t = (n_entries - LOW) / (HIGH - LOW);
99
- return max_hull_dist_in_data * (1 - t) + static_default * t;
183
+ const frac = (n_entries - LOW) / (HIGH - LOW);
184
+ return max_hull_dist_in_data * (1 - frac) + static_default * frac;
100
185
  }
101
186
  export function auto_threshold_reset(default_threshold) {
102
187
  let source;
@@ -131,7 +216,7 @@ export function same_entry(a, b) {
131
216
  return a.entry_id != null && a.entry_id === b.entry_id;
132
217
  }
133
218
  // Build a tooltip text for any phase entry (shared)
134
- export function build_entry_tooltip_text(entry) {
219
+ export function build_entry_tooltip_text(entry, category = MAGNETIC_ORDERING_CATEGORY) {
135
220
  const is_element = is_unary_entry(entry);
136
221
  const elem_symbol = is_element ? Object.keys(entry.composition)[0] : ``;
137
222
  const elem_name = is_element ? (ELEM_SYMBOL_TO_NAME[elem_symbol] ?? ``) : ``;
@@ -139,15 +224,9 @@ export function build_entry_tooltip_text(entry) {
139
224
  ? `${elem_symbol}${elem_name ? ` (${elem_name})` : ``}\n`
140
225
  : `${entry.name ?? entry.reduced_formula ?? ``}\n`;
141
226
  if (!is_element) {
142
- const total = Object.values(entry.composition).reduce((sum, amt) => sum + amt, 0);
143
- if (total > 0) {
144
- const fractions = Object.entries(entry.composition)
145
- .filter(([, amt]) => amt > 0)
146
- .map(([el, amt]) => `${el}: ${format_fractional(amt / total)}`);
147
- if (fractions.length > 1) {
148
- text += `Composition: ${fractions.join(`, `)}\n`;
149
- }
150
- }
227
+ const fractions = Object.entries(get_fractional_composition(entry.composition)).map(([elem, frac]) => `${elem}: ${format_fractional(frac)}`);
228
+ if (fractions.length > 1)
229
+ text += `Composition: ${fractions.join(`, `)}\n`;
151
230
  }
152
231
  if (entry.e_above_hull !== undefined) {
153
232
  const e_hull_str = format_num(entry.e_above_hull, `.3~`);
@@ -159,6 +238,9 @@ export function build_entry_tooltip_text(entry) {
159
238
  const e_form_str = format_num(e_form_display, `.3~`);
160
239
  text += `E<sub>form</sub>: ${e_form_str} eV/atom`;
161
240
  }
241
+ const category_value = get_entry_category(entry, category);
242
+ if (category && category_value)
243
+ text += `\n${category.label}: ${category_value}`;
162
244
  if (entry.entry_id)
163
245
  text += `\nID: ${entry.entry_id}`;
164
246
  return text;
@@ -180,6 +262,11 @@ export function find_hull_entry_at_mouse(canvas, event, plot_entries, project_po
180
262
  }
181
263
  return null;
182
264
  }
265
+ // Shared CSS custom-property block for hull wrapper styling (2D/3D/4D)
266
+ export const hull_style_css = (colors) => `--hull-stable-color: ${colors?.stable ?? `#0072B2`};
267
+ --hull-unstable-color: ${colors?.unstable ?? `#E69F00`};
268
+ --hull-edge-color: ${colors?.edge ?? `var(--text-color, #212121)`};
269
+ --hull-text-color: ${colors?.annotation ?? `var(--text-color, #212121)`}`;
183
270
  // Calculate which side of the viewport has more space for modal placement
184
271
  export function calculate_modal_side(wrapper) {
185
272
  if (!wrapper)
@@ -210,21 +297,21 @@ energy_source_mode) {
210
297
  break;
211
298
  }
212
299
  }
213
- const can_compute_hull = can_compute_e_form;
214
300
  // Resolve mode to avoid inconsistent states:
215
301
  // - If full precomputed available, honor user toggle
216
- // - Else if we can compute both, use on-the-fly automatically
302
+ // - Else if we can compute, use on-the-fly automatically
217
303
  // - Else fall back to precomputed (best-effort)
218
304
  const energy_mode = has_precomputed_e_form && has_precomputed_hull
219
305
  ? energy_source_mode
220
- : can_compute_e_form && can_compute_hull
306
+ : can_compute_e_form
221
307
  ? `on-the-fly`
222
308
  : `precomputed`;
223
309
  return {
224
310
  has_precomputed_e_form,
225
311
  has_precomputed_hull,
226
312
  can_compute_e_form,
227
- can_compute_hull,
313
+ // hull needs the same unary references as e_form, so the two always agree
314
+ can_compute_hull: can_compute_e_form,
228
315
  energy_mode,
229
316
  unary_refs,
230
317
  };
@@ -245,8 +332,8 @@ compute_e_form_fn) {
245
332
  });
246
333
  }
247
334
  // Copy text to clipboard with visual feedback
248
- export async function copy_entry_to_clipboard(entry, position, on_feedback) {
249
- const text = build_entry_tooltip_text(entry);
335
+ export async function copy_entry_to_clipboard(entry, position, on_feedback, category = MAGNETIC_ORDERING_CATEGORY) {
336
+ const text = build_entry_tooltip_text(entry, category);
250
337
  await navigator.clipboard.writeText(text);
251
338
  on_feedback(true, position);
252
339
  setTimeout(() => on_feedback(false, position), 1500);
@@ -423,30 +510,6 @@ export function compute_all_polymorph_stats(all_entries) {
423
510
  }
424
511
  return stats_map;
425
512
  }
426
- function apply_alpha_to_color(color, alpha) {
427
- // Handle existing rgba format
428
- if (color.includes(`rgba`))
429
- return color.replace(/[\d.]+\)$/, `${alpha})`);
430
- if (color.includes(`rgb(`)) {
431
- // Convert rgb to rgba
432
- return color.replace(/rgb\(/, `rgba(`).replace(/\)$/, `, ${alpha})`);
433
- }
434
- const hex_match = /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.exec(color); // Convert hex to rgba
435
- if (hex_match) {
436
- let hex = hex_match[1];
437
- // Expand short form (e.g. "03F") to full form (e.g. "0033FF")
438
- if (hex.length === 3)
439
- hex = hex
440
- .split(``)
441
- .map((char) => char + char)
442
- .join(``);
443
- const red = parseInt(hex.slice(0, 2), 16);
444
- const green = parseInt(hex.slice(2, 4), 16);
445
- const blue = parseInt(hex.slice(4, 6), 16);
446
- return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
447
- }
448
- return color; // Return unchanged if format not recognized
449
- }
450
513
  export function draw_highlight_effect(ctx, projected, size, container_scale, pulse_time, style) {
451
514
  const { effect, color: hl_color, size_multiplier, opacity, pulse_speed } = style;
452
515
  if (effect === `pulse`) {
@@ -458,8 +521,8 @@ export function draw_highlight_effect(ctx, projected, size, container_scale, pul
458
521
  ctx.lineWidth = (1.5 + pulse_val) * container_scale;
459
522
  ctx.beginPath();
460
523
  ctx.arc(projected.x, projected.y, hl_size, 0, 2 * Math.PI);
461
- ctx.fillStyle = apply_alpha_to_color(hl_color, hl_opacity * 0.3);
462
- ctx.strokeStyle = apply_alpha_to_color(hl_color, hl_opacity);
524
+ ctx.fillStyle = add_alpha(hl_color, hl_opacity * 0.3);
525
+ ctx.strokeStyle = add_alpha(hl_color, hl_opacity);
463
526
  ctx.fill();
464
527
  ctx.stroke();
465
528
  }
@@ -469,14 +532,14 @@ export function draw_highlight_effect(ctx, projected, size, container_scale, pul
469
532
  // Outer soft glow
470
533
  ctx.beginPath();
471
534
  ctx.arc(projected.x, projected.y, hl_size * 1.3, 0, 2 * Math.PI);
472
- ctx.fillStyle = apply_alpha_to_color(hl_color, opacity * 0.15);
535
+ ctx.fillStyle = add_alpha(hl_color, opacity * 0.15);
473
536
  ctx.fill();
474
537
  // Inner glow with stroke
475
538
  ctx.lineWidth = 1.5 * container_scale;
476
539
  ctx.beginPath();
477
540
  ctx.arc(projected.x, projected.y, hl_size, 0, 2 * Math.PI);
478
- ctx.fillStyle = apply_alpha_to_color(hl_color, opacity * 0.4);
479
- ctx.strokeStyle = apply_alpha_to_color(hl_color, opacity * 0.8);
541
+ ctx.fillStyle = add_alpha(hl_color, opacity * 0.4);
542
+ ctx.strokeStyle = add_alpha(hl_color, opacity * 0.8);
480
543
  ctx.fill();
481
544
  ctx.stroke();
482
545
  }
@@ -494,8 +557,8 @@ export function draw_highlight_effect(ctx, projected, size, container_scale, pul
494
557
  // Draw selection highlight for currently selected entry (with pulsing animation)
495
558
  export function draw_selection_highlight(ctx, projected, base_size, container_scale, pulse_time, pulse_opacity) {
496
559
  const highlight_size = base_size * (1.8 + 0.3 * Math.sin(pulse_time * 4));
497
- ctx.fillStyle = apply_alpha_to_color(`rgba(102, 240, 255, 1)`, pulse_opacity * 0.6);
498
- ctx.strokeStyle = apply_alpha_to_color(`rgba(102, 240, 255, 1)`, pulse_opacity);
560
+ ctx.fillStyle = add_alpha(`rgba(102, 240, 255, 1)`, pulse_opacity * 0.6);
561
+ ctx.strokeStyle = add_alpha(`rgba(102, 240, 255, 1)`, pulse_opacity);
499
562
  ctx.lineWidth = 2 * container_scale;
500
563
  ctx.beginPath();
501
564
  ctx.arc(projected.x, projected.y, highlight_size, 0, 2 * Math.PI);
@@ -514,19 +577,69 @@ export function get_canvas_text_color(dark_mode, element) {
514
577
  // Check for unsupported CSS functions that canvas can't render
515
578
  return css_value && !/light-dark|var\(/i.test(css_value) ? css_value : fallback;
516
579
  }
517
- // Create a Path2D for a marker symbol. Uses d3-shape for consistent rendering with ScatterPlot.
518
- export function create_marker_path(size, marker = `circle`) {
519
- const safe_size = Number.isFinite(size) ? size : 0;
520
- const rounded_size = Math.max(0, Number(safe_size.toFixed(3)));
580
+ // Draw depth-sorted hull points with shadow, selection/highlight effects and marker
581
+ // symbols. Shared by the ConvexHull3D/4D canvas renderers (which differ only in
582
+ // shadow_factor and in how labels are drawn afterwards).
583
+ export function draw_hull_points(ctx, sorted_points, opts) {
584
+ const { scale, shadow_factor, selected_entry, highlight_style, is_highlighted, get_point_color, pulse_time, pulse_opacity, } = opts;
585
+ for (const { entry, projected } of sorted_points) {
586
+ const is_stable = entry_is_stable(entry);
587
+ const entry_highlighted = is_highlighted(entry);
588
+ const color = get_point_color(entry);
589
+ // `||` (not ??) on purpose: size=0 / empty marker fall back to defaults
590
+ // oxlint-disable-next-line typescript/prefer-nullish-coalescing
591
+ const size = (entry.size || (is_stable ? 6 : 4)) * scale;
592
+ // oxlint-disable-next-line typescript/prefer-nullish-coalescing
593
+ const marker = entry.marker || `circle`;
594
+ // Shadow
595
+ const shadow_offset = Math.abs(entry.z) * shadow_factor * scale;
596
+ ctx.fillStyle = `rgba(0, 0, 0, 0.2)`;
597
+ const shadow_path = create_marker_path(size * 0.8, marker);
598
+ ctx.save();
599
+ ctx.translate(projected.x + shadow_offset, projected.y + shadow_offset);
600
+ ctx.fill(shadow_path);
601
+ ctx.restore();
602
+ // Highlights (same_entry, not raw entry_id comparison: undefined === undefined
603
+ // would mark EVERY id-less point as selected)
604
+ if (same_entry(selected_entry, entry)) {
605
+ draw_selection_highlight(ctx, projected, size, scale, pulse_time, pulse_opacity);
606
+ }
607
+ if (entry_highlighted) {
608
+ draw_highlight_effect(ctx, projected, size, scale, pulse_time, highlight_style);
609
+ }
610
+ // Main point with marker symbol
611
+ ctx.fillStyle =
612
+ entry_highlighted && highlight_style.effect === `color` ? highlight_style.color : color;
613
+ ctx.strokeStyle = is_stable ? `#ffffff` : `#000000`;
614
+ ctx.lineWidth = 0.5 * scale;
615
+ const marker_path = create_marker_path(size, marker);
616
+ ctx.save();
617
+ ctx.translate(projected.x, projected.y);
618
+ ctx.fill(marker_path);
619
+ ctx.stroke(marker_path);
620
+ ctx.restore();
621
+ }
622
+ }
623
+ // SVG path data for a marker symbol of given radius, or null for unknown marker names.
624
+ // Uses d3-shape for consistent rendering with ScatterPlot.
625
+ export function marker_path_data(radius, marker) {
521
626
  // Capitalize first letter to get D3 symbol name (e.g. 'circle' -> 'Circle')
522
627
  const d3_name = marker.charAt(0).toUpperCase() + marker.slice(1);
523
628
  const symbol_type = symbol_map[d3_name];
524
- const symbol_area = Math.PI * rounded_size * rounded_size;
525
- const path_data = symbol_type ? symbol().type(symbol_type).size(symbol_area)() : null;
629
+ return symbol_type
630
+ ? symbol()
631
+ .type(symbol_type)
632
+ .size(Math.PI * radius * radius)()
633
+ : null;
634
+ }
635
+ // Create a Path2D for a marker symbol (canvas rendering in ConvexHull3D/4D)
636
+ export function create_marker_path(size, marker = `circle`) {
637
+ const safe_size = Number.isFinite(size) ? size : 0;
638
+ const rounded_size = Math.max(0, Number(safe_size.toFixed(3)));
639
+ const path_data = marker_path_data(rounded_size, marker);
526
640
  const path = new Path2D(path_data ?? undefined);
527
- if (!path_data) {
641
+ if (!path_data)
528
642
  path.arc(0, 0, rounded_size, 0, 2 * Math.PI);
529
- }
530
643
  return path;
531
644
  }
532
645
  // Analyze entries for temperature-dependent free energy data.
@@ -646,60 +759,32 @@ export function filter_entries_at_temperature(entries, T, options = {}) {
646
759
  return [{ ...entry, energy, energy_per_atom: energy }];
647
760
  }
648
761
  }
649
- // Exclude entry (has temp data but can't get energy at T)
650
- return [];
762
+ return []; // Exclude entry (has temp data but can't get energy at T)
651
763
  });
652
764
  }
653
- // Gas-dependent chemical potential helpers
654
- // Analyze entries for gas-dependent elements (safe wrapper with optional config)
655
- // Returns information about which gases are relevant for the chemical system.
656
- export function safe_analyze_gas_data(entries, config) {
657
- if (!config?.enabled_gases?.length) {
658
- return {
659
- has_gas_dependent_elements: false,
660
- gas_elements: [],
661
- relevant_gases: [],
662
- };
663
- }
664
- return _analyze_gas_data(entries, config);
665
- }
666
- // Apply gas chemical potential corrections to entries (safe wrapper with optional config)
667
- // This adjusts formation energies based on gas atmosphere conditions (T, P).
668
- // Should be applied after temperature filtering.
669
- export function safe_apply_gas_corrections(entries, config, T) {
670
- if (!config?.enabled_gases?.length)
671
- return entries;
672
- return _apply_gas_corrections(entries, config, T);
673
- }
674
765
  // Get gas-corrected entries in one call (consolidates analysis + correction)
675
766
  // Merges gas_pressures with config.pressures and applies corrections if the
676
767
  // chemical system contains gas-dependent elements. Returns original entries
677
768
  // if no gas config or no relevant gases.
678
769
  export function get_gas_corrected_entries(entries, gas_config, gas_pressures, temperature) {
679
770
  if (!gas_config?.enabled_gases?.length) {
680
- return {
681
- entries,
682
- analysis: {
683
- has_gas_dependent_elements: false,
684
- gas_elements: [],
685
- relevant_gases: [],
686
- },
687
- merged_config: undefined,
771
+ const analysis = {
772
+ has_gas_dependent_elements: false,
773
+ gas_elements: [],
774
+ relevant_gases: [],
688
775
  };
776
+ return { entries, analysis, merged_config: undefined };
689
777
  }
690
778
  const merged_config = {
691
779
  ...gas_config,
692
780
  pressures: { ...gas_config.pressures, ...gas_pressures },
693
781
  };
694
- const analysis = _analyze_gas_data(entries, merged_config);
782
+ const analysis = analyze_gas_data(entries, merged_config);
695
783
  if (!analysis.has_gas_dependent_elements) {
696
784
  return { entries, analysis, merged_config };
697
785
  }
698
- return {
699
- entries: _apply_gas_corrections(entries, merged_config, temperature),
700
- analysis,
701
- merged_config,
702
- };
786
+ const corr_entries = apply_gas_corrections(entries, merged_config, temperature);
787
+ return { entries: corr_entries, analysis, merged_config };
703
788
  }
704
789
  // Derive a display label for a convex hull entry, falling back to composition
705
790
  // when reduced_formula and name are both missing.
@@ -708,7 +793,7 @@ export function get_entry_label(entry, elements) {
708
793
  return entry.reduced_formula;
709
794
  if (entry.name)
710
795
  return entry.name;
711
- let pairs = Object.entries(entry.composition).filter(([, amt]) => amt > 0);
796
+ let pairs = Object.entries(entry.composition).filter(([, amt]) => (amt ?? 0) > 0);
712
797
  if (elements) {
713
798
  pairs = pairs.sort(([el1], [el2]) => elements.indexOf(el1) - elements.indexOf(el2));
714
799
  }
@@ -0,0 +1,44 @@
1
+ import * as helpers from './helpers';
2
+ import type { EntryCategoryConfig, GasSpecies, GasThermodynamicsConfig, PhaseData } from './types';
3
+ export interface HullDataPipelineInputs<Entry extends PhaseData> {
4
+ dim: 2 | 3 | 4;
5
+ entries: () => PhaseData[];
6
+ temperature: () => number | undefined;
7
+ interpolate_temperature: () => boolean;
8
+ max_interpolation_gap: () => number;
9
+ gas_config: () => GasThermodynamicsConfig | undefined;
10
+ gas_pressures: () => Partial<Record<GasSpecies, number>>;
11
+ energy_source_mode: () => `precomputed` | `on-the-fly`;
12
+ all_enriched_entries: () => Entry[];
13
+ max_hull_dist_show_phases: () => number;
14
+ show_stable: () => boolean;
15
+ show_unstable: () => boolean;
16
+ entry_category: () => EntryCategoryConfig | null;
17
+ hidden_categories: () => readonly string[];
18
+ keep_plot_entry: (entry: Entry, max_hull_dist: number) => boolean;
19
+ set_temperature: (temperature: number) => void;
20
+ set_max_hull_dist_show_phases: (value: number) => void;
21
+ set_stable_entries: (value: Entry[]) => void;
22
+ set_unstable_entries: (value: Entry[]) => void;
23
+ }
24
+ export declare function create_hull_data_pipeline<Entry extends PhaseData>(inputs: HullDataPipelineInputs<Entry>): {
25
+ readonly has_temp_data: boolean;
26
+ readonly available_temperatures: number[];
27
+ readonly gas_analysis: import("./types").GasAnalysis;
28
+ readonly merged_gas_config: GasThermodynamicsConfig | undefined;
29
+ readonly has_precomputed_e_form: boolean;
30
+ readonly has_precomputed_hull: boolean;
31
+ readonly can_compute_e_form: boolean;
32
+ readonly can_compute_hull: boolean;
33
+ readonly energy_mode: "precomputed" | "on-the-fly";
34
+ readonly effective_entries: (PhaseData & {
35
+ marker?: import("./types").MarkerSymbol;
36
+ })[];
37
+ readonly pd_data: import("./types").ProcessedPhaseData;
38
+ readonly polymorph_stats_map: Map<string, helpers.PolymorphStats>;
39
+ readonly elements: ("Ac" | "Ag" | "Al" | "Am" | "Ar" | "As" | "At" | "Au" | "B" | "Ba" | "Be" | "Bh" | "Bi" | "Bk" | "Br" | "C" | "Ca" | "Cd" | "Ce" | "Cf" | "Cl" | "Cm" | "Co" | "Cr" | "Cs" | "Cu" | "Db" | "Dy" | "Er" | "Es" | "Eu" | "F" | "Fe" | "Fm" | "Fr" | "Ga" | "Gd" | "Ge" | "H" | "He" | "Hf" | "Hg" | "Ho" | "Hs" | "I" | "In" | "Ir" | "K" | "Kr" | "La" | "Li" | "Lr" | "Lu" | "Md" | "Mg" | "Mn" | "Mo" | "Mt" | "N" | "Na" | "Nb" | "Nd" | "Ne" | "Ni" | "No" | "Np" | "O" | "Os" | "P" | "Pa" | "Pb" | "Pd" | "Pm" | "Po" | "Pr" | "Pt" | "Pu" | "Ra" | "Rb" | "Re" | "Rf" | "Rh" | "Rn" | "Ru" | "S" | "Sb" | "Sc" | "Se" | "Sg" | "Si" | "Sm" | "Sn" | "Sr" | "Ta" | "Tb" | "Tc" | "Te" | "Th" | "Ti" | "Tl" | "Tm" | "U" | "V" | "W" | "Xe" | "Y" | "Yb" | "Zn" | "Zr" | "Ds" | "Rg" | "Cn" | "Nh" | "Fl" | "Mc" | "Lv" | "Ts" | "Og")[];
40
+ readonly max_hull_dist_in_data: number;
41
+ readonly auto_default_threshold: number;
42
+ readonly plot_entries: Entry[];
43
+ readonly visible_entries: Entry[];
44
+ };
@@ -0,0 +1,124 @@
1
+ // Shared reactive data pipeline (runes-in-closure factory) for ConvexHull2D/3D/4D.
2
+ import { DEFAULTS } from '../settings';
3
+ import * as helpers from './helpers';
4
+ import * as thermo from './thermodynamics';
5
+ const DIM_TO_KIND = { 2: `binary`, 3: `ternary`, 4: `quaternary` };
6
+ export function create_hull_data_pipeline(inputs) {
7
+ const kind = DIM_TO_KIND[inputs.dim];
8
+ const default_threshold = DEFAULTS.convex_hull[kind].max_hull_dist_show_phases;
9
+ // Temperature-dependent free energy support
10
+ const temp_analysis = $derived(helpers.analyze_temperature_data(inputs.entries()));
11
+ // Initialize or reset temperature when it's undefined or no longer valid
12
+ $effect(() => {
13
+ const temperature = inputs.temperature();
14
+ const { has_temp_data, available_temperatures } = temp_analysis;
15
+ if (has_temp_data &&
16
+ available_temperatures.length > 0 &&
17
+ (temperature === undefined || !available_temperatures.includes(temperature)))
18
+ inputs.set_temperature(available_temperatures[0]);
19
+ });
20
+ // Filter entries by temperature when in temperature mode
21
+ const temp_filtered_entries = $derived.by(() => {
22
+ const temperature = inputs.temperature();
23
+ return temp_analysis.has_temp_data && temperature !== undefined
24
+ ? helpers.filter_entries_at_temperature(inputs.entries(), temperature, {
25
+ interpolate: inputs.interpolate_temperature(),
26
+ max_interpolation_gap: inputs.max_interpolation_gap(),
27
+ })
28
+ : inputs.entries();
29
+ });
30
+ // Gas-dependent chemical potential support (corrections based on T, P)
31
+ // defaults to DEFAULT_GAS_TEMP (room temp) when no temperature
32
+ const gas_result = $derived(helpers.get_gas_corrected_entries(temp_filtered_entries, inputs.gas_config(), inputs.gas_pressures(), inputs.temperature() ?? helpers.DEFAULT_GAS_TEMP));
33
+ // Compute energy mode information
34
+ const energy_info = $derived(helpers.compute_energy_mode_info(gas_result.entries, thermo.find_lowest_energy_unary_refs, inputs.energy_source_mode()));
35
+ // Assign category marker shapes (no-op when entries lack category data)
36
+ const effective_entries = $derived(helpers.apply_category_markers(helpers.get_effective_entries(gas_result.entries, energy_info.energy_mode, energy_info.unary_refs, thermo.compute_e_form_per_atom), inputs.entry_category()));
37
+ // Process convex hull data with unified PhaseData interface using effective entries
38
+ const pd_data = $derived(thermo.process_hull_entries(effective_entries));
39
+ // Pre-compute polymorph stats once for O(1) tooltip lookups
40
+ const polymorph_stats_map = $derived(helpers.compute_all_polymorph_stats(effective_entries));
41
+ const elements = $derived.by(() => {
42
+ if (pd_data.elements.length > inputs.dim) {
43
+ console.error(`ConvexHull${inputs.dim}D: Dataset contains ${pd_data.elements.length} elements, but ${kind} diagrams require exactly ${inputs.dim}. Found: [${pd_data.elements.join(`, `)}]`);
44
+ return [];
45
+ }
46
+ return pd_data.elements;
47
+ });
48
+ // Auto threshold: show all for few entries, use default for many, interpolate between
49
+ const max_hull_dist_in_data = $derived(helpers.calc_max_hull_dist_in_data(inputs.all_enriched_entries()));
50
+ const auto_default_threshold = $derived(helpers.compute_auto_hull_dist_threshold(inputs.all_enriched_entries().length, max_hull_dist_in_data, default_threshold));
51
+ const next_auto_threshold = helpers.auto_threshold_reset(default_threshold);
52
+ $effect(() => {
53
+ const current = inputs.max_hull_dist_show_phases();
54
+ // Key the reset on the enriched (post-processing) entries, not raw entries(), so the
55
+ // auto threshold re-derives when temperature/gas/energy-mode change the hull. The
56
+ // user_changed guard inside auto_threshold_reset still preserves manual adjustments.
57
+ inputs.set_max_hull_dist_show_phases(next_auto_threshold(inputs.all_enriched_entries(), current, auto_default_threshold) ??
58
+ current);
59
+ });
60
+ // Filter by threshold; visibility is a view predicate, not entry state.
61
+ const plot_entries = $derived(inputs
62
+ .all_enriched_entries()
63
+ .filter((entry) => inputs.keep_plot_entry(entry, inputs.max_hull_dist_show_phases())));
64
+ const visible_entries = $derived(helpers.visible_entries(plot_entries, inputs.show_stable(), inputs.show_unstable(), inputs.entry_category(), inputs.hidden_categories()));
65
+ // Update bindable stable/unstable entry arrays when plot_entries change
66
+ $effect(() => {
67
+ const is_stable = (entry) => helpers.entry_is_stable(entry);
68
+ inputs.set_stable_entries(plot_entries.filter(is_stable));
69
+ inputs.set_unstable_entries(plot_entries.filter((entry) => !is_stable(entry)));
70
+ });
71
+ return {
72
+ get has_temp_data() {
73
+ return temp_analysis.has_temp_data;
74
+ },
75
+ get available_temperatures() {
76
+ return temp_analysis.available_temperatures;
77
+ },
78
+ get gas_analysis() {
79
+ return gas_result.analysis;
80
+ },
81
+ get merged_gas_config() {
82
+ return gas_result.merged_config;
83
+ },
84
+ get has_precomputed_e_form() {
85
+ return energy_info.has_precomputed_e_form;
86
+ },
87
+ get has_precomputed_hull() {
88
+ return energy_info.has_precomputed_hull;
89
+ },
90
+ get can_compute_e_form() {
91
+ return energy_info.can_compute_e_form;
92
+ },
93
+ get can_compute_hull() {
94
+ return energy_info.can_compute_hull;
95
+ },
96
+ get energy_mode() {
97
+ return energy_info.energy_mode;
98
+ },
99
+ get effective_entries() {
100
+ return effective_entries;
101
+ },
102
+ get pd_data() {
103
+ return pd_data;
104
+ },
105
+ get polymorph_stats_map() {
106
+ return polymorph_stats_map;
107
+ },
108
+ get elements() {
109
+ return elements;
110
+ },
111
+ get max_hull_dist_in_data() {
112
+ return max_hull_dist_in_data;
113
+ },
114
+ get auto_default_threshold() {
115
+ return auto_default_threshold;
116
+ },
117
+ get plot_entries() {
118
+ return plot_entries;
119
+ },
120
+ get visible_entries() {
121
+ return visible_entries;
122
+ },
123
+ };
124
+ }