matterviz 0.3.7 → 0.4.1

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 (486) hide show
  1. package/dist/Icon.svelte +7 -4
  2. package/dist/MillerIndexInput.svelte +1 -1
  3. package/dist/api/optimade.js +32 -26
  4. package/dist/app.css +0 -3
  5. package/dist/brillouin/BrillouinZone.svelte +76 -148
  6. package/dist/brillouin/BrillouinZone.svelte.d.ts +6 -14
  7. package/dist/brillouin/BrillouinZoneExportPane.svelte +43 -96
  8. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneInfoPane.svelte +9 -32
  10. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
  11. package/dist/brillouin/BrillouinZoneScene.svelte +97 -205
  12. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +4 -23
  13. package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
  14. package/dist/brillouin/ReciprocalVectors.svelte +39 -0
  15. package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
  16. package/dist/brillouin/compute.d.ts +2 -0
  17. package/dist/brillouin/compute.js +89 -90
  18. package/dist/brillouin/geometry.d.ts +8 -0
  19. package/dist/brillouin/geometry.js +57 -0
  20. package/dist/brillouin/index.d.ts +2 -0
  21. package/dist/brillouin/index.js +2 -0
  22. package/dist/brillouin/types.d.ts +2 -2
  23. package/dist/chempot-diagram/ChemPotDiagram.svelte +14 -13
  24. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
  25. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +109 -203
  26. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
  27. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +180 -470
  28. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
  29. package/dist/chempot-diagram/async-compute.svelte.js +3 -1
  30. package/dist/chempot-diagram/chempot-worker.js +2 -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 +4 -4
  34. package/dist/chempot-diagram/compute.js +20 -20
  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.js +8 -7
  45. package/dist/composition/FormulaFilter.svelte +18 -11
  46. package/dist/composition/PieChart.svelte +11 -10
  47. package/dist/composition/chem-sys.d.ts +8 -0
  48. package/dist/composition/chem-sys.js +86 -0
  49. package/dist/composition/format.js +7 -4
  50. package/dist/composition/index.d.ts +1 -0
  51. package/dist/composition/index.js +1 -0
  52. package/dist/composition/parse.d.ts +0 -1
  53. package/dist/composition/parse.js +41 -31
  54. package/dist/controls.d.ts +1 -0
  55. package/dist/controls.js +0 -1
  56. package/dist/convex-hull/ConvexHull.svelte +8 -10
  57. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
  58. package/dist/convex-hull/ConvexHull2D.svelte +106 -185
  59. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  60. package/dist/convex-hull/ConvexHull3D.svelte +179 -683
  61. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  62. package/dist/convex-hull/ConvexHull4D.svelte +183 -687
  63. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  64. package/dist/convex-hull/ConvexHullChrome.svelte +268 -0
  65. package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
  66. package/dist/convex-hull/ConvexHullControls.svelte +88 -7
  67. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
  68. package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
  69. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
  70. package/dist/convex-hull/ConvexHullStats.svelte +36 -175
  71. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
  72. package/dist/convex-hull/ConvexHullTooltip.svelte +11 -2
  73. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
  74. package/dist/convex-hull/GasPressureControls.svelte +4 -4
  75. package/dist/convex-hull/TemperatureSlider.svelte +2 -2
  76. package/dist/convex-hull/barycentric-coords.d.ts +2 -4
  77. package/dist/convex-hull/barycentric-coords.js +6 -33
  78. package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
  79. package/dist/convex-hull/canvas-interactions.svelte.js +278 -0
  80. package/dist/convex-hull/demo-temperature.d.ts +1 -1
  81. package/dist/convex-hull/demo-temperature.js +20 -22
  82. package/dist/convex-hull/gas-thermodynamics.d.ts +2 -2
  83. package/dist/convex-hull/gas-thermodynamics.js +22 -30
  84. package/dist/convex-hull/helpers.d.ts +42 -7
  85. package/dist/convex-hull/helpers.js +171 -78
  86. package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
  87. package/dist/convex-hull/hull-state.svelte.js +124 -0
  88. package/dist/convex-hull/index.d.ts +10 -8
  89. package/dist/convex-hull/index.js +7 -2
  90. package/dist/convex-hull/thermodynamics.js +136 -960
  91. package/dist/convex-hull/types.d.ts +13 -5
  92. package/dist/convex-hull/types.js +12 -0
  93. package/dist/coordination/CoordinationBarPlot.svelte +27 -34
  94. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  95. package/dist/element/BohrAtom.svelte +2 -1
  96. package/dist/element/index.d.ts +4 -0
  97. package/dist/element/index.js +18 -0
  98. package/dist/feedback/DragOverlay.svelte +3 -1
  99. package/dist/feedback/DragOverlay.svelte.d.ts +1 -0
  100. package/dist/feedback/StatusMessage.svelte +13 -3
  101. package/dist/fermi-surface/FermiSlice.svelte +13 -5
  102. package/dist/fermi-surface/FermiSurface.svelte +78 -151
  103. package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -14
  104. package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
  105. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  106. package/dist/fermi-surface/FermiSurfaceScene.svelte +72 -221
  107. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
  108. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
  109. package/dist/fermi-surface/compute.js +67 -66
  110. package/dist/fermi-surface/export.js +6 -16
  111. package/dist/fermi-surface/index.d.ts +0 -1
  112. package/dist/fermi-surface/index.js +0 -1
  113. package/dist/fermi-surface/parse.d.ts +1 -1
  114. package/dist/fermi-surface/parse.js +71 -79
  115. package/dist/fermi-surface/types.d.ts +3 -2
  116. package/dist/heatmap-matrix/HeatmapMatrix.svelte +69 -52
  117. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +4 -3
  118. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +3 -2
  119. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
  120. package/dist/heatmap-matrix/index.d.ts +3 -2
  121. package/dist/heatmap-matrix/index.js +1 -1
  122. package/dist/index.d.ts +1 -0
  123. package/dist/index.js +1 -0
  124. package/dist/io/ExportPane.svelte +166 -0
  125. package/dist/io/ExportPane.svelte.d.ts +17 -0
  126. package/dist/io/decompress.js +5 -4
  127. package/dist/io/export.d.ts +9 -5
  128. package/dist/io/export.js +77 -51
  129. package/dist/io/fetch.d.ts +2 -1
  130. package/dist/io/fetch.js +5 -1
  131. package/dist/io/file-drop.d.ts +8 -1
  132. package/dist/io/file-drop.js +48 -36
  133. package/dist/io/index.d.ts +2 -0
  134. package/dist/io/index.js +10 -0
  135. package/dist/io/types.d.ts +13 -0
  136. package/dist/io/url-drop.js +64 -33
  137. package/dist/isosurface/parse.js +52 -51
  138. package/dist/isosurface/slice.js +5 -4
  139. package/dist/isosurface/types.js +1 -1
  140. package/dist/keyboard.d.ts +3 -0
  141. package/dist/keyboard.js +23 -0
  142. package/dist/labels.d.ts +1 -1
  143. package/dist/labels.js +9 -8
  144. package/dist/layout/FullscreenButton.svelte +33 -0
  145. package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
  146. package/dist/layout/FullscreenToggle.svelte +8 -14
  147. package/dist/layout/PropertyFilter.svelte +3 -2
  148. package/dist/layout/SettingsSection.svelte +1 -1
  149. package/dist/layout/ViewerChrome.svelte +116 -0
  150. package/dist/layout/ViewerChrome.svelte.d.ts +17 -0
  151. package/dist/layout/fullscreen.d.ts +4 -0
  152. package/dist/layout/fullscreen.svelte.d.ts +8 -0
  153. package/dist/layout/fullscreen.svelte.js +37 -0
  154. package/dist/layout/index.d.ts +3 -0
  155. package/dist/layout/index.js +3 -0
  156. package/dist/layout/json-tree/JsonNode.svelte +1 -1
  157. package/dist/layout/json-tree/JsonTree.svelte +2 -2
  158. package/dist/layout/json-tree/utils.js +5 -4
  159. package/dist/marching-cubes.js +8 -13
  160. package/dist/math.d.ts +12 -4
  161. package/dist/math.js +42 -30
  162. package/dist/overlays/DraggablePane.svelte +4 -4
  163. package/dist/overlays/index.d.ts +4 -0
  164. package/dist/periodic-table/PeriodicTable.svelte +27 -15
  165. package/dist/periodic-table/PropertySelect.svelte +1 -0
  166. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +9 -3
  167. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  168. package/dist/phase-diagram/PhaseDiagramControls.svelte +3 -2
  169. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
  170. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
  171. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
  172. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +47 -132
  173. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
  174. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
  175. package/dist/phase-diagram/build-diagram.js +2 -2
  176. package/dist/phase-diagram/colors.js +1 -1
  177. package/dist/phase-diagram/parse.d.ts +2 -1
  178. package/dist/phase-diagram/parse.js +6 -5
  179. package/dist/phase-diagram/types.d.ts +1 -1
  180. package/dist/phase-diagram/utils.d.ts +3 -3
  181. package/dist/phase-diagram/utils.js +8 -12
  182. package/dist/plot/{BarPlot.svelte → bar/BarPlot.svelte} +246 -841
  183. package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +8 -16
  184. package/dist/plot/{BarPlotControls.svelte → bar/BarPlotControls.svelte} +6 -5
  185. package/dist/plot/{BarPlotControls.svelte.d.ts → bar/BarPlotControls.svelte.d.ts} +3 -3
  186. package/dist/plot/{SpacegroupBarPlot.svelte → bar/SpacegroupBarPlot.svelte} +8 -7
  187. package/dist/plot/{SpacegroupBarPlot.svelte.d.ts → bar/SpacegroupBarPlot.svelte.d.ts} +1 -1
  188. package/dist/plot/bar/data.d.ts +40 -0
  189. package/dist/plot/bar/data.js +154 -0
  190. package/dist/plot/bar/geometry.d.ts +39 -0
  191. package/dist/plot/bar/geometry.js +60 -0
  192. package/dist/plot/bar/index.d.ts +3 -0
  193. package/dist/plot/bar/index.js +3 -0
  194. package/dist/plot/box/BoxPlot.svelte +1292 -0
  195. package/dist/plot/box/BoxPlot.svelte.d.ts +95 -0
  196. package/dist/plot/box/BoxPlotControls.svelte +109 -0
  197. package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
  198. package/dist/plot/box/Violin.svelte +14 -0
  199. package/dist/plot/box/Violin.svelte.d.ts +70 -0
  200. package/dist/plot/box/box-plot.d.ts +56 -0
  201. package/dist/plot/box/box-plot.js +129 -0
  202. package/dist/plot/box/index.d.ts +5 -0
  203. package/dist/plot/box/index.js +5 -0
  204. package/dist/plot/box/kde.d.ts +17 -0
  205. package/dist/plot/box/kde.js +160 -0
  206. package/dist/plot/box/quantile.d.ts +3 -0
  207. package/dist/plot/box/quantile.js +53 -0
  208. package/dist/plot/{auto-place.d.ts → core/auto-place.d.ts} +1 -1
  209. package/dist/plot/{auto-place.js → core/auto-place.js} +6 -3
  210. package/dist/plot/core/axis-utils.d.ts +46 -0
  211. package/dist/plot/core/axis-utils.js +110 -0
  212. package/dist/plot/{AxisLabel.svelte → core/components/AxisLabel.svelte} +2 -2
  213. package/dist/plot/{AxisLabel.svelte.d.ts → core/components/AxisLabel.svelte.d.ts} +1 -1
  214. package/dist/plot/{ColorBar.svelte → core/components/ColorBar.svelte} +41 -38
  215. package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +7 -6
  216. package/dist/plot/{ColorScaleSelect.svelte → core/components/ColorScaleSelect.svelte} +4 -3
  217. package/dist/plot/{ColorScaleSelect.svelte.d.ts → core/components/ColorScaleSelect.svelte.d.ts} +2 -2
  218. package/dist/plot/core/components/ControlPane.svelte +46 -0
  219. package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
  220. package/dist/plot/{FillArea.svelte → core/components/FillArea.svelte} +17 -6
  221. package/dist/plot/{FillArea.svelte.d.ts → core/components/FillArea.svelte.d.ts} +1 -1
  222. package/dist/plot/{InteractiveAxisLabel.svelte → core/components/InteractiveAxisLabel.svelte} +3 -3
  223. package/dist/plot/{InteractiveAxisLabel.svelte.d.ts → core/components/InteractiveAxisLabel.svelte.d.ts} +2 -2
  224. package/dist/plot/{Line.svelte → core/components/Line.svelte} +33 -15
  225. package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +3 -2
  226. package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +9 -6
  227. package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +5 -3
  228. package/dist/plot/{PlotControls.svelte → core/components/PlotControls.svelte} +17 -29
  229. package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
  230. package/dist/plot/{PlotLegend.svelte → core/components/PlotLegend.svelte} +21 -10
  231. package/dist/plot/{PlotLegend.svelte.d.ts → core/components/PlotLegend.svelte.d.ts} +3 -2
  232. package/dist/plot/{PlotTooltip.svelte → core/components/PlotTooltip.svelte} +17 -1
  233. package/dist/plot/{PlotTooltip.svelte.d.ts → core/components/PlotTooltip.svelte.d.ts} +8 -0
  234. package/dist/plot/{PortalSelect.svelte → core/components/PortalSelect.svelte} +11 -7
  235. package/dist/plot/{ReferenceLine.svelte → core/components/ReferenceLine.svelte} +3 -3
  236. package/dist/plot/{ReferenceLine.svelte.d.ts → core/components/ReferenceLine.svelte.d.ts} +1 -1
  237. package/dist/plot/{ReferenceLine3D.svelte → core/components/ReferenceLine3D.svelte} +5 -5
  238. package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +5 -5
  239. package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +8 -8
  240. package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +5 -5
  241. package/dist/plot/{ZeroLines.svelte → core/components/ZeroLines.svelte} +3 -3
  242. package/dist/plot/{ZeroLines.svelte.d.ts → core/components/ZeroLines.svelte.d.ts} +3 -3
  243. package/dist/plot/{ZoomRect.svelte → core/components/ZoomRect.svelte} +1 -1
  244. package/dist/plot/{ZoomRect.svelte.d.ts → core/components/ZoomRect.svelte.d.ts} +1 -1
  245. package/dist/plot/core/components/index.d.ts +17 -0
  246. package/dist/plot/core/components/index.js +17 -0
  247. package/dist/plot/{data-cleaning.d.ts → core/data-cleaning.d.ts} +71 -1
  248. package/dist/plot/{data-cleaning.js → core/data-cleaning.js} +21 -23
  249. package/dist/plot/{data-transform.d.ts → core/data-transform.d.ts} +2 -2
  250. package/dist/plot/{data-transform.js → core/data-transform.js} +3 -3
  251. package/dist/plot/core/fill-utils.d.ts +34 -0
  252. package/dist/plot/core/fill-utils.js +391 -0
  253. package/dist/plot/core/index.d.ts +10 -0
  254. package/dist/plot/core/index.js +11 -0
  255. package/dist/plot/core/interactions.d.ts +39 -0
  256. package/dist/plot/core/interactions.js +209 -0
  257. package/dist/plot/{layout.d.ts → core/layout.d.ts} +1 -0
  258. package/dist/plot/{layout.js → core/layout.js} +16 -8
  259. package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
  260. package/dist/plot/core/pan-zoom.svelte.js +221 -0
  261. package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
  262. package/dist/plot/core/placed-tween.svelte.js +68 -0
  263. package/dist/plot/{reference-line.d.ts → core/reference-line.d.ts} +11 -11
  264. package/dist/plot/{reference-line.js → core/reference-line.js} +29 -42
  265. package/dist/plot/core/scales.d.ts +40 -0
  266. package/dist/plot/{scales.js → core/scales.js} +94 -93
  267. package/dist/plot/core/svg.d.ts +3 -0
  268. package/dist/plot/core/svg.js +41 -0
  269. package/dist/plot/{types.d.ts → core/types.d.ts} +36 -85
  270. package/dist/plot/{types.js → core/types.js} +1 -1
  271. package/dist/plot/{utils → core/utils}/label-placement.d.ts +3 -3
  272. package/dist/plot/{utils → core/utils}/label-placement.js +3 -3
  273. package/dist/plot/core/utils/series-visibility.d.ts +26 -0
  274. package/dist/plot/{utils → core/utils}/series-visibility.js +29 -2
  275. package/dist/plot/core/utils.d.ts +12 -0
  276. package/dist/plot/core/utils.js +27 -0
  277. package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +174 -551
  278. package/dist/plot/{Histogram.svelte.d.ts → histogram/Histogram.svelte.d.ts} +2 -2
  279. package/dist/plot/{HistogramControls.svelte → histogram/HistogramControls.svelte} +6 -6
  280. package/dist/plot/{HistogramControls.svelte.d.ts → histogram/HistogramControls.svelte.d.ts} +4 -4
  281. package/dist/plot/histogram/index.d.ts +2 -0
  282. package/dist/plot/histogram/index.js +2 -0
  283. package/dist/plot/index.d.ts +8 -41
  284. package/dist/plot/index.js +10 -39
  285. package/dist/plot/sankey/Sankey.svelte +697 -0
  286. package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
  287. package/dist/plot/sankey/SankeyControls.svelte +98 -0
  288. package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
  289. package/dist/plot/sankey/index.d.ts +4 -0
  290. package/dist/plot/sankey/index.js +3 -0
  291. package/dist/plot/sankey/sankey-types.d.ts +42 -0
  292. package/dist/plot/sankey/sankey-types.js +4 -0
  293. package/dist/plot/sankey/sankey.d.ts +52 -0
  294. package/dist/plot/sankey/sankey.js +189 -0
  295. package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +64 -64
  296. package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +6 -6
  297. package/dist/plot/{ElementScatter.svelte → scatter/ElementScatter.svelte} +6 -6
  298. package/dist/plot/{ElementScatter.svelte.d.ts → scatter/ElementScatter.svelte.d.ts} +2 -2
  299. package/dist/plot/{ScatterPlot.svelte → scatter/ScatterPlot.svelte} +297 -1008
  300. package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +10 -18
  301. package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
  302. package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +2 -2
  303. package/dist/plot/{ScatterPoint.svelte → scatter/ScatterPoint.svelte} +7 -7
  304. package/dist/plot/{ScatterPoint.svelte.d.ts → scatter/ScatterPoint.svelte.d.ts} +3 -3
  305. package/dist/plot/{adaptive-density.d.ts → scatter/adaptive-density.d.ts} +14 -4
  306. package/dist/plot/{adaptive-density.js → scatter/adaptive-density.js} +46 -20
  307. package/dist/plot/{binned-scatter-types.d.ts → scatter/binned-scatter-types.d.ts} +5 -12
  308. package/dist/plot/scatter/index.d.ts +7 -0
  309. package/dist/plot/scatter/index.js +5 -0
  310. package/dist/plot/scatter/scatter-data.d.ts +19 -0
  311. package/dist/plot/scatter/scatter-data.js +212 -0
  312. package/dist/plot/{ScatterPlot3D.svelte → scatter-3d/ScatterPlot3D.svelte} +25 -34
  313. package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +9 -17
  314. package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +14 -14
  315. package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +6 -6
  316. package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +129 -128
  317. package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +6 -15
  318. package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +7 -6
  319. package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +5 -4
  320. package/dist/plot/scatter-3d/index.d.ts +4 -0
  321. package/dist/plot/scatter-3d/index.js +4 -0
  322. package/dist/plot/sunburst/Sunburst.svelte +1041 -0
  323. package/dist/plot/sunburst/Sunburst.svelte.d.ts +97 -0
  324. package/dist/plot/sunburst/SunburstControls.svelte +200 -0
  325. package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
  326. package/dist/plot/sunburst/index.d.ts +4 -0
  327. package/dist/plot/sunburst/index.js +4 -0
  328. package/dist/plot/sunburst/render.d.ts +34 -0
  329. package/dist/plot/sunburst/render.js +122 -0
  330. package/dist/plot/sunburst/sunburst.d.ts +62 -0
  331. package/dist/plot/sunburst/sunburst.js +269 -0
  332. package/dist/rdf/RdfPlot.svelte +2 -1
  333. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  334. package/dist/rdf/calc-rdf.js +11 -24
  335. package/dist/sanitize.js +14 -3
  336. package/dist/scene/SceneCamera.svelte +62 -0
  337. package/dist/scene/SceneCamera.svelte.d.ts +19 -0
  338. package/dist/scene/bind-renderer.svelte.d.ts +2 -0
  339. package/dist/scene/bind-renderer.svelte.js +14 -0
  340. package/dist/scene/index.d.ts +4 -0
  341. package/dist/scene/index.js +5 -0
  342. package/dist/scene/props.js +52 -0
  343. package/dist/scene/types.d.ts +26 -0
  344. package/dist/scene/types.js +1 -0
  345. package/dist/settings.d.ts +79 -3
  346. package/dist/settings.js +321 -1
  347. package/dist/spectral/Bands.svelte +47 -36
  348. package/dist/spectral/Bands.svelte.d.ts +6 -6
  349. package/dist/spectral/BandsAndDos.svelte +23 -25
  350. package/dist/spectral/BrillouinBandsDos.svelte +42 -30
  351. package/dist/spectral/Dos.svelte +15 -23
  352. package/dist/spectral/Dos.svelte.d.ts +4 -3
  353. package/dist/spectral/helpers.d.ts +8 -6
  354. package/dist/spectral/helpers.js +137 -65
  355. package/dist/state.svelte.d.ts +0 -7
  356. package/dist/state.svelte.js +0 -6
  357. package/dist/structure/Arrow.svelte +2 -4
  358. package/dist/structure/AtomLegend.svelte +8 -9
  359. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  360. package/dist/structure/CanvasTooltip.svelte +1 -0
  361. package/dist/structure/CellSelect.svelte +12 -5
  362. package/dist/structure/CellSelect.svelte.d.ts +2 -1
  363. package/dist/structure/Cylinder.svelte +12 -8
  364. package/dist/structure/Cylinder.svelte.d.ts +4 -1
  365. package/dist/structure/Lattice.svelte +2 -2
  366. package/dist/structure/Structure.svelte +365 -423
  367. package/dist/structure/Structure.svelte.d.ts +5 -15
  368. package/dist/structure/StructureControls.svelte +217 -2
  369. package/dist/structure/StructureControls.svelte.d.ts +5 -3
  370. package/dist/structure/StructureExportPane.svelte +54 -156
  371. package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
  372. package/dist/structure/StructureInfoPane.svelte +10 -9
  373. package/dist/structure/StructureInfoPane.svelte.d.ts +5 -5
  374. package/dist/structure/StructureScene.svelte +376 -208
  375. package/dist/structure/StructureScene.svelte.d.ts +22 -20
  376. package/dist/structure/{label-placement.d.ts → atom-label-placement.d.ts} +3 -3
  377. package/dist/structure/{label-placement.js → atom-label-placement.js} +15 -5
  378. package/dist/structure/atom-properties.d.ts +1 -1
  379. package/dist/structure/atom-properties.js +17 -22
  380. package/dist/structure/bond-order-perception.js +3 -5
  381. package/dist/structure/bonding.d.ts +4 -0
  382. package/dist/structure/bonding.js +134 -63
  383. package/dist/structure/export.d.ts +24 -4
  384. package/dist/structure/export.js +89 -143
  385. package/dist/structure/index.d.ts +4 -4
  386. package/dist/structure/index.js +3 -3
  387. package/dist/structure/measure.d.ts +3 -2
  388. package/dist/structure/measure.js +6 -5
  389. package/dist/structure/parse.d.ts +3 -2
  390. package/dist/structure/parse.js +419 -438
  391. package/dist/structure/partial-occupancy.d.ts +0 -1
  392. package/dist/structure/partial-occupancy.js +1 -1
  393. package/dist/structure/pbc.d.ts +1 -1
  394. package/dist/structure/pbc.js +190 -13
  395. package/dist/structure/polyhedra.d.ts +41 -0
  396. package/dist/structure/polyhedra.js +602 -0
  397. package/dist/structure/site.d.ts +4 -0
  398. package/dist/structure/site.js +1 -0
  399. package/dist/structure/supercell.js +3 -2
  400. package/dist/structure/validation.js +5 -6
  401. package/dist/symmetry/SymmetryElementControls.svelte +69 -0
  402. package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
  403. package/dist/symmetry/SymmetryElements.svelte +354 -0
  404. package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
  405. package/dist/symmetry/SymmetryStats.svelte +113 -8
  406. package/dist/symmetry/WyckoffTable.svelte +68 -7
  407. package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
  408. package/dist/symmetry/cell-transform.js +7 -14
  409. package/dist/symmetry/index.d.ts +14 -4
  410. package/dist/symmetry/index.js +291 -72
  411. package/dist/symmetry/spacegroups.d.ts +12 -1
  412. package/dist/symmetry/spacegroups.js +63 -14
  413. package/dist/symmetry/symmetry-elements.d.ts +33 -0
  414. package/dist/symmetry/symmetry-elements.js +521 -0
  415. package/dist/symmetry/wyckoff-db.d.ts +9 -0
  416. package/dist/symmetry/wyckoff-db.js +87 -0
  417. package/dist/table/HeatmapTable.svelte +66 -25
  418. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  419. package/dist/table/index.d.ts +1 -3
  420. package/dist/table/index.js +1 -1
  421. package/dist/theme/index.js +8 -8
  422. package/dist/tooltip/KCoords.svelte +45 -0
  423. package/dist/tooltip/KCoords.svelte.d.ts +8 -0
  424. package/dist/tooltip/index.d.ts +1 -0
  425. package/dist/tooltip/index.js +1 -0
  426. package/dist/trajectory/Trajectory.svelte +123 -100
  427. package/dist/trajectory/Trajectory.svelte.d.ts +11 -22
  428. package/dist/trajectory/TrajectoryExportPane.svelte +17 -25
  429. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
  430. package/dist/trajectory/TrajectoryInfoPane.svelte +5 -3
  431. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
  432. package/dist/trajectory/constants.js +6 -2
  433. package/dist/trajectory/extract.js +17 -37
  434. package/dist/trajectory/format-detect.d.ts +1 -1
  435. package/dist/trajectory/format-detect.js +27 -19
  436. package/dist/trajectory/frame-reader.d.ts +0 -1
  437. package/dist/trajectory/frame-reader.js +63 -162
  438. package/dist/trajectory/helpers.d.ts +10 -2
  439. package/dist/trajectory/helpers.js +56 -36
  440. package/dist/trajectory/index.js +1 -1
  441. package/dist/trajectory/parse/ase.d.ts +9 -1
  442. package/dist/trajectory/parse/ase.js +47 -32
  443. package/dist/trajectory/parse/diagnostics.d.ts +3 -0
  444. package/dist/trajectory/parse/diagnostics.js +14 -0
  445. package/dist/trajectory/parse/hdf5.js +1 -1
  446. package/dist/trajectory/parse/index.d.ts +1 -1
  447. package/dist/trajectory/parse/index.js +65 -105
  448. package/dist/trajectory/parse/lammps.d.ts +0 -2
  449. package/dist/trajectory/parse/lammps.js +8 -6
  450. package/dist/trajectory/parse/pymatgen.d.ts +2 -0
  451. package/dist/trajectory/parse/pymatgen.js +74 -0
  452. package/dist/trajectory/parse/vasp.js +38 -18
  453. package/dist/trajectory/parse/xyz.d.ts +13 -1
  454. package/dist/trajectory/parse/xyz.js +102 -94
  455. package/dist/trajectory/plotting.d.ts +1 -2
  456. package/dist/trajectory/plotting.js +16 -113
  457. package/dist/utils.d.ts +2 -0
  458. package/dist/utils.js +7 -5
  459. package/dist/xrd/XrdPlot.svelte +16 -30
  460. package/dist/xrd/broadening.d.ts +2 -1
  461. package/dist/xrd/calc-xrd.js +18 -20
  462. package/dist/xrd/index.d.ts +2 -2
  463. package/dist/xrd/parse.js +2 -2
  464. package/package.json +43 -26
  465. package/dist/element/data.json +0 -11864
  466. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  467. package/dist/fermi-surface/marching-cubes.js +0 -2
  468. package/dist/plot/PlotControls.svelte.d.ts +0 -4
  469. package/dist/plot/axis-utils.d.ts +0 -19
  470. package/dist/plot/axis-utils.js +0 -78
  471. package/dist/plot/defaults.d.ts +0 -19
  472. package/dist/plot/defaults.js +0 -9
  473. package/dist/plot/fill-utils.d.ts +0 -46
  474. package/dist/plot/fill-utils.js +0 -322
  475. package/dist/plot/hover-lock.svelte.d.ts +0 -14
  476. package/dist/plot/hover-lock.svelte.js +0 -46
  477. package/dist/plot/interactions.d.ts +0 -12
  478. package/dist/plot/interactions.js +0 -101
  479. package/dist/plot/scales.d.ts +0 -48
  480. package/dist/plot/svg.d.ts +0 -1
  481. package/dist/plot/svg.js +0 -11
  482. package/dist/plot/utils/series-visibility.d.ts +0 -15
  483. package/dist/plot/utils.d.ts +0 -1
  484. package/dist/plot/utils.js +0 -14
  485. /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
  486. /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
@@ -1,6 +1,7 @@
1
1
  // Helper utilities for band structure and DOS data processing
2
2
  import { SUBSCRIPT_MAP } from '../labels';
3
- import { centered_frac, euclidean_dist } from '../math';
3
+ import { is_plain_object } from '../utils';
4
+ import { euclidean_dist, is_square_matrix } from '../math';
4
5
  const is_subscript_key = (key) => key in SUBSCRIPT_MAP;
5
6
  // Check if range is a valid [min, max] tuple (strict 2-element array of finite numbers)
6
7
  export const is_valid_range = (range) => Array.isArray(range) &&
@@ -22,6 +23,22 @@ export const axis_with_range = (axis, range, label) => ({
22
23
  ...(label !== undefined && { label }),
23
24
  ...(is_valid_range(range) && { range }),
24
25
  });
26
+ // Sync a ScatterPlot's internal y-axis range back onto a parent bindable axis.
27
+ // Returns a new axis when the range changed (or became invalid and must be
28
+ // cleared), otherwise the same reference so callers can skip reassignment and
29
+ // avoid reactive churn (assign only when `result !== axis`).
30
+ export function sync_axis_range(axis, range) {
31
+ if (is_valid_range(range)) {
32
+ if (axis.range?.[0] === range[0] && axis.range?.[1] === range[1])
33
+ return axis;
34
+ return { ...axis, range };
35
+ }
36
+ if (`range` in axis) {
37
+ const { range: _omit, ...rest } = axis;
38
+ return rest;
39
+ }
40
+ return axis;
41
+ }
25
42
  // Detect which plot triggered a zoom change and return the new synced range.
26
43
  // Returns null to reset to shared range, undefined for no change, or Vec2 for new zoom.
27
44
  export function detect_zoom_change(bands_range, dos_range, shared_range, current_synced, dos_enabled = true) {
@@ -70,12 +87,12 @@ export function pretty_sym_point(symbol) {
70
87
  // Handle subscripts: convert S0 to S₀, K1 to K₁, Γ1 to Γ₁, etc.
71
88
  // Use \p{L} to match any Unicode letter (not just ASCII A-Z)
72
89
  return symbol
73
- .replace(/_/g, ``)
74
- .replace(/\\?GAMMA/gi, `Γ`)
75
- .replace(/\\?DELTA/gi, `Δ`)
76
- .replace(/\\?SIGMA/gi, `Σ`)
77
- .replace(/\\?LAMBDA/gi, `Λ`)
78
- .replace(/(\p{L})(\d+)/gu, (_, letter, num) => letter +
90
+ .replaceAll('_', ``)
91
+ .replaceAll(/\\?GAMMA/gi, `Γ`)
92
+ .replaceAll(/\\?DELTA/gi, `Δ`)
93
+ .replaceAll(/\\?SIGMA/gi, `Σ`)
94
+ .replaceAll(/\\?LAMBDA/gi, `Λ`)
95
+ .replaceAll(/(\p{L})(\d+)/gu, (_, letter, num) => letter +
79
96
  num
80
97
  .split(``)
81
98
  .map((digit) => (is_subscript_key(digit) ? SUBSCRIPT_MAP[digit] : digit))
@@ -133,7 +150,7 @@ export function get_ribbon_config(ribbon_config, label) {
133
150
  export function get_band_xaxis_ticks(band_struct, branches = []) {
134
151
  const ticks_x_pos = [];
135
152
  const tick_labels = [];
136
- let prev_label = band_struct.qpoints[0]?.label || null;
153
+ let prev_label = band_struct.qpoints[0]?.label ?? null;
137
154
  let prev_branch = band_struct.branches[0]?.name || null;
138
155
  // Convert branches to Set for consistent handling
139
156
  const branches_set = Array.isArray(branches) ? new Set(branches) : branches;
@@ -148,7 +165,7 @@ export function get_band_xaxis_ticks(band_struct, branches = []) {
148
165
  const this_branch = branch_names[0] || null;
149
166
  if (point.label !== prev_label && prev_branch !== this_branch) {
150
167
  // Branch transition - combine labels
151
- tick_labels[tick_labels.length - 1] = `${prev_label || ``}|${point.label}`;
168
+ tick_labels[tick_labels.length - 1] = `${prev_label ?? ``}|${point.label}`;
152
169
  ticks_x_pos[ticks_x_pos.length - 1] = band_struct.distance[idx];
153
170
  }
154
171
  else if (branches_set.size === 0 || (this_branch && branches_set.has(this_branch))) {
@@ -188,7 +205,7 @@ export function normalize_densities(densities, freqs_or_energies, mode) {
188
205
  return normalized.map((dens) => dens / max_val);
189
206
  }
190
207
  else if (mode === `sum`) {
191
- const sum = normalized.reduce((acc, d) => acc + d, 0);
208
+ const sum = normalized.reduce((acc, dens) => acc + dens, 0);
192
209
  if (sum === 0)
193
210
  return normalized;
194
211
  return normalized.map((dens) => dens / sum);
@@ -199,7 +216,7 @@ export function normalize_densities(densities, freqs_or_energies, mode) {
199
216
  const bin_width = freqs_or_energies[1] - freqs_or_energies[0];
200
217
  if (bin_width === 0)
201
218
  return normalized;
202
- const sum = normalized.reduce((acc, d) => acc + d, 0);
219
+ const sum = normalized.reduce((acc, dens) => acc + dens, 0);
203
220
  if (sum === 0)
204
221
  return normalized;
205
222
  return normalized.map((dens) => dens / (sum * bin_width));
@@ -222,6 +239,7 @@ function fnv1a_hash(arr) {
222
239
  hash ^= int_view[1];
223
240
  hash = Math.imul(hash, 16777619);
224
241
  }
242
+ // oxlint-disable-next-line eslint-plugin-unicorn/prefer-math-trunc -- `>>> 0` is unsigned 32-bit coercion, not truncation
225
243
  return hash >>> 0; // Ensure unsigned
226
244
  }
227
245
  // Generate cache key using FNV-1a hash over full arrays (O(n), low collision risk)
@@ -233,7 +251,7 @@ function generate_smearing_cache_key(freqs_or_energies, densities, sigma) {
233
251
  }
234
252
  // Core Gaussian smearing computation (unmemoized)
235
253
  function apply_gaussian_smearing_core(freqs_or_energies, densities, sigma) {
236
- const orig_sum = densities.reduce((acc, d) => acc + d, 0);
254
+ const orig_sum = densities.reduce((acc, dens) => acc + dens, 0);
237
255
  if (sigma <= 0 || orig_sum === 0)
238
256
  return densities;
239
257
  const smeared = Array(densities.length).fill(0);
@@ -252,7 +270,7 @@ function apply_gaussian_smearing_core(freqs_or_energies, densities, sigma) {
252
270
  }
253
271
  }
254
272
  // Normalize to preserve integral
255
- const smeared_sum = smeared.reduce((acc, d) => acc + d, 0);
273
+ const smeared_sum = smeared.reduce((acc, dens) => acc + dens, 0);
256
274
  if (smeared_sum === 0)
257
275
  return densities;
258
276
  const normalization = orig_sum / smeared_sum;
@@ -291,7 +309,7 @@ export function clear_smearing_cache() {
291
309
  }
292
310
  // Type guards for pymatgen qpoint formats
293
311
  const is_vec3 = (val) => Array.isArray(val) && val.length >= 3 && val.slice(0, 3).every(Number.isFinite);
294
- const is_kpoint = (val) => !!val && typeof val === `object` && `frac_coords` in val && is_vec3(val.frac_coords);
312
+ const is_kpoint = (val) => val !== null && typeof val === `object` && `frac_coords` in val && is_vec3(val.frac_coords);
295
313
  const is_pymatgen_format = (obj) => {
296
314
  // Check for explicit pymatgen markers
297
315
  if (typeof obj[`@class`] === `string` || typeof obj[`@module`] === `string`) {
@@ -313,8 +331,8 @@ const parse_qpoint = (qpt, labels_dict) => {
313
331
  : null;
314
332
  if (!frac_coords)
315
333
  return null;
316
- const label = (is_kpoint(qpt) && typeof qpt.label === `string` && qpt.label) ||
317
- Object.entries(labels_dict ?? {}).find(([, c]) => euclidean_dist(frac_coords, c) < 1e-4)?.[0] ||
334
+ const label = ((is_kpoint(qpt) && typeof qpt.label === `string` && qpt.label) ||
335
+ Object.entries(labels_dict ?? {}).find(([, c]) => euclidean_dist(frac_coords, c) < 1e-4)?.[0]) ??
318
336
  null;
319
337
  return { label, frac_coords };
320
338
  };
@@ -386,13 +404,13 @@ function convert_pymatgen_band_structure(pmg) {
386
404
  const unit = pmg.unit?.toLowerCase() ?? (has_frequencies_cm ? `cm-1` : `thz`);
387
405
  if (!Array.isArray(raw_qpts) ||
388
406
  !Array.isArray(raw_bands) ||
389
- !raw_qpts.length ||
390
- !raw_bands.length)
407
+ raw_qpts.length === 0 ||
408
+ raw_bands.length === 0)
391
409
  return null;
392
410
  const qpoints = raw_qpts
393
411
  .map((qpoint) => parse_qpoint(qpoint, labels_dict))
394
412
  .filter((qpoint) => qpoint !== null);
395
- if (!qpoints.length)
413
+ if (qpoints.length === 0)
396
414
  return null;
397
415
  // Step distances and discontinuity detection (5x median threshold)
398
416
  const steps = qpoints
@@ -439,7 +457,7 @@ function convert_pymatgen_band_structure(pmg) {
439
457
  })
440
458
  .filter((branch) => branch.start_index <= branch.end_index);
441
459
  }
442
- if (!branches.length) {
460
+ if (branches.length === 0) {
443
461
  branches.push({ start_index: 0, end_index: qpoints.length - 1, name: `path` });
444
462
  }
445
463
  // Convert bands to THz based on input unit
@@ -474,10 +492,9 @@ function convert_pymatgen_band_structure(pmg) {
474
492
  },
475
493
  };
476
494
  }
477
- export function normalize_band_structure(bs) {
478
- if (!bs || typeof bs !== `object`)
495
+ export function normalize_band_structure(band_struct) {
496
+ if (!is_plain_object(band_struct))
479
497
  return null;
480
- const band_struct = bs;
481
498
  // Check if this is pymatgen format and convert if so
482
499
  if (is_pymatgen_format(band_struct)) {
483
500
  return convert_pymatgen_band_structure(band_struct);
@@ -499,27 +516,42 @@ export function normalize_band_structure(bs) {
499
516
  branch.end_index >= n_qpts ||
500
517
  branch.start_index > branch.end_index))
501
518
  return null;
502
- return band_struct;
519
+ // Fill required defaults (recip_lattice/labels_dict/nb_bands) not covered above so the cast below is sound
520
+ const recip_lattice = band_struct.recip_lattice;
521
+ const normalized = {
522
+ ...band_struct,
523
+ nb_bands: typeof band_struct.nb_bands === `number` ? band_struct.nb_bands : bands.length,
524
+ labels_dict: band_struct.labels_dict ?? {},
525
+ recip_lattice: is_square_matrix(recip_lattice?.matrix, 3)
526
+ ? recip_lattice
527
+ : {
528
+ matrix: [
529
+ [1, 0, 0],
530
+ [0, 1, 0],
531
+ [0, 0, 1],
532
+ ],
533
+ },
534
+ };
535
+ return normalized;
503
536
  }
504
537
  // Validate and normalize a DOS object.
505
538
  // Supports both matterviz and pymatgen formats.
506
539
  // Also auto-detects and converts cm⁻¹ to THz for legacy data (disable with auto_convert_units: false).
507
540
  export function normalize_dos(dos, options = {}) {
508
541
  const { auto_convert_units = true } = options;
509
- if (!dos || typeof dos !== `object`)
542
+ if (!is_plain_object(dos))
510
543
  return null;
511
- const dos_obj = dos;
512
544
  // Check for pymatgen format (has @class or @module)
513
- const is_pymatgen = typeof dos_obj[`@class`] === `string` || typeof dos_obj[`@module`] === `string`;
514
- const { frequencies, energies, spin_polarized } = dos_obj;
545
+ const is_pymatgen = typeof dos[`@class`] === `string` || typeof dos[`@module`] === `string`;
546
+ const { frequencies, energies, spin_polarized } = dos;
515
547
  // Handle densities as either array or dict with spin keys (pymatgen format)
516
548
  // Pymatgen stores densities as {1: [...], -1: [...]} or {"Spin.up": [...], ...}
517
- const spin_channels = extract_spin_channels(dos_obj.densities);
549
+ const spin_channels = extract_spin_channels(dos.densities);
518
550
  if (!spin_channels)
519
551
  return null;
520
552
  const densities = spin_channels.up;
521
553
  // Use extracted spin-down or fallback to explicit field (for already-normalized DosData)
522
- const spin_down_densities = spin_channels.down ?? dos_obj.spin_down_densities ?? null;
554
+ const spin_down_densities = spin_channels.down ?? dos.spin_down_densities ?? null;
523
555
  if (!Array.isArray(densities))
524
556
  return null;
525
557
  // Phonon DOS: has frequencies
@@ -574,19 +606,44 @@ export function extract_k_path_points(band_struct, recip_lattice_matrix, options
574
606
  throw new Error(`reciprocal_lattice_matrix must be a 3×3 matrix`);
575
607
  const [[m00, m01, m02], [m10, m11, m12], [m20, m21, m22]] = recip_lattice_matrix;
576
608
  return band_struct.qpoints.map((qpoint) => {
577
- let [x, y, z] = qpoint.frac_coords;
578
- // Wrap to first BZ if enabled (handles [0,1] vs [-0.5,0.5] convention difference)
579
- if (wrap_to_bz) {
580
- x = centered_frac(x);
581
- y = centered_frac(y);
582
- z = centered_frac(z);
583
- }
584
- const kx = x * m00 + y * m10 + z * m20;
585
- const ky = x * m01 + y * m11 + z * m21;
586
- const kz = x * m02 + y * m12 + z * m22;
587
- return [kx, ky, kz];
609
+ const [x, y, z] = qpoint.frac_coords;
610
+ const cart = [
611
+ x * m00 + y * m10 + z * m20,
612
+ x * m01 + y * m11 + z * m21,
613
+ x * m02 + y * m12 + z * m22,
614
+ ];
615
+ // Fold into the first (Wigner-Seitz) BZ so points stay inside the rendered zone.
616
+ // Folding in Cartesian space (vs per-axis on fractional coords, which only yields
617
+ // the parallelepiped cell) handles non-orthogonal lattices and preserves path
618
+ // continuity: points already inside the zone are left untouched.
619
+ return wrap_to_bz ? fold_to_first_bz(cart, recip_lattice_matrix) : cart;
588
620
  });
589
621
  }
622
+ // Fold a Cartesian reciprocal-space point into the first (Wigner-Seitz) Brillouin zone
623
+ // by choosing the periodic image with the smallest norm (minimum-image convention).
624
+ // The ±1 search (27 images) suffices for typical reciprocal lattices; extremely skewed
625
+ // cells could in principle need a wider search.
626
+ function fold_to_first_bz(cart, recip) {
627
+ let best = cart;
628
+ let best_norm = cart[0] ** 2 + cart[1] ** 2 + cart[2] ** 2;
629
+ for (let n1 = -1; n1 <= 1; n1++) {
630
+ for (let n2 = -1; n2 <= 1; n2++) {
631
+ for (let n3 = -1; n3 <= 1; n3++) {
632
+ if (n1 === 0 && n2 === 0 && n3 === 0)
633
+ continue;
634
+ const cand = [
635
+ cart[0] + n1 * recip[0][0] + n2 * recip[1][0] + n3 * recip[2][0],
636
+ cart[1] + n1 * recip[0][1] + n2 * recip[1][1] + n3 * recip[2][1],
637
+ cart[2] + n1 * recip[0][2] + n2 * recip[1][2] + n3 * recip[2][2],
638
+ ];
639
+ const norm = cand[0] ** 2 + cand[1] ** 2 + cand[2] ** 2;
640
+ if (norm < best_norm - 1e-9)
641
+ [best, best_norm] = [cand, norm];
642
+ }
643
+ }
644
+ }
645
+ return best;
646
+ }
590
647
  // Find the q-point index closest to a given distance along the band structure path
591
648
  export function find_qpoint_at_distance(band_struct, target) {
592
649
  const { distance } = band_struct;
@@ -594,6 +651,30 @@ export function find_qpoint_at_distance(band_struct, target) {
594
651
  return null;
595
652
  return distance.reduce((closest, dist, idx) => Math.abs(dist - target) < Math.abs(distance[closest] - target) ? idx : closest, 0);
596
653
  }
654
+ // Rescaled x-position of a q-point index along the band plot path. Inverse of
655
+ // find_qpoint_at_rescaled_x, used to highlight a q-point hovered in the Brillouin zone.
656
+ // Returns null if the index doesn't fall on a plotted (non-discontinuity) branch.
657
+ export function qpoint_x_position(band_struct, qpoint_index, x_positions) {
658
+ if (!band_struct?.branches?.length || !x_positions)
659
+ return null;
660
+ for (const branch of band_struct.branches) {
661
+ if (qpoint_index < branch.start_index || qpoint_index > branch.end_index)
662
+ continue;
663
+ const start_label = band_struct.qpoints[branch.start_index]?.label ?? undefined;
664
+ const end_label = band_struct.qpoints[branch.end_index]?.label ?? undefined;
665
+ const range = x_positions[get_segment_key(start_label, end_label)];
666
+ if (!range)
667
+ continue;
668
+ const [x_start, x_end] = range;
669
+ const d_start = band_struct.distance[branch.start_index];
670
+ const d_end = band_struct.distance[branch.end_index];
671
+ if (d_end === d_start)
672
+ return x_start; // discontinuity / zero-length segment
673
+ const ratio = (band_struct.distance[qpoint_index] - d_start) / (d_end - d_start);
674
+ return x_start + ratio * (x_end - x_start);
675
+ }
676
+ return null;
677
+ }
597
678
  // Find q-point index from rescaled x-coordinate (used in band structure plots)
598
679
  // This handles the case where the plot uses custom x-axis scaling per segment
599
680
  export function find_qpoint_at_rescaled_x(band_struct, rescaled_x, x_positions) {
@@ -677,13 +758,12 @@ export function find_qpoint_at_rescaled_x(band_struct, rescaled_x, x_positions)
677
758
  // Returns a dict of label → DosData for each atom or orbital.
678
759
  // filter_keys: optional list of keys to include (e.g., ["Fe", "O"] for atoms or ["s", "p", "d"] for orbitals)
679
760
  export function extract_pdos(dos, pdos_type, filter_keys) {
680
- if (!dos || typeof dos !== `object`)
761
+ if (!is_plain_object(dos))
681
762
  return null;
682
- const dos_obj = dos;
683
763
  // Get the appropriate projected DOS dict
684
764
  const pdos_dict = pdos_type === `atom`
685
- ? dos_obj.atom_dos
686
- : dos_obj.spd_dos;
765
+ ? dos.atom_dos
766
+ : dos.spd_dos;
687
767
  if (!pdos_dict || typeof pdos_dict !== `object`)
688
768
  return null;
689
769
  const result = {};
@@ -786,21 +866,15 @@ export function generate_ribbon_path(x_values, y_values, width_values, x_scale_f
786
866
  // Handles both single objects with an efermi field and dicts of objects.
787
867
  // Returns undefined if no valid efermi is found or if the source is empty.
788
868
  export function extract_efermi(data) {
789
- if (!data || typeof data !== `object`)
869
+ if (!is_plain_object(data))
790
870
  return undefined;
791
- const obj = data;
792
871
  // Direct efermi field on the object
793
- if (`efermi` in obj && typeof obj.efermi === `number`)
794
- return obj.efermi;
872
+ if (typeof data.efermi === `number`)
873
+ return data.efermi;
795
874
  // Dict of objects - try to get efermi from first value
796
- const values = Object.values(obj);
797
- if (values.length === 0)
798
- return undefined;
799
- const first_val = values[0];
800
- if (first_val && typeof first_val === `object`) {
801
- const efermi = first_val.efermi;
802
- if (typeof efermi === `number`)
803
- return efermi;
875
+ const first_val = Object.values(data)[0];
876
+ if (is_plain_object(first_val) && typeof first_val.efermi === `number`) {
877
+ return first_val.efermi;
804
878
  }
805
879
  return undefined;
806
880
  }
@@ -820,18 +894,16 @@ export function negative_fraction(values) {
820
894
  // Check if raw band structure input has electronic markers (efermi, kpoints, or electronic @class).
821
895
  // Must be called on raw input before normalization since these fields aren't preserved.
822
896
  function is_electronic_band_struct(bs) {
823
- if (!bs || typeof bs !== `object`)
897
+ if (!is_plain_object(bs))
824
898
  return false;
825
- const obj = bs;
826
899
  // Electronic band structures have efermi field
827
- if (`efermi` in obj && typeof obj.efermi === `number`)
900
+ if (typeof bs.efermi === `number`)
828
901
  return true;
829
902
  // Pymatgen electronic format uses kpoints (not qpoints)
830
- if (`kpoints` in obj && Array.isArray(obj.kpoints) && obj.kpoints.length > 0) {
903
+ if (Array.isArray(bs.kpoints) && bs.kpoints.length > 0)
831
904
  return true;
832
- }
833
905
  // Pymatgen @class: BandStructure* but not Phonon*
834
- const raw_class = obj[`@class`];
906
+ const raw_class = bs[`@class`];
835
907
  const py_class_name = typeof raw_class === `string` ? raw_class : ``;
836
908
  if (py_class_name.startsWith(`BandStructure`) && !py_class_name.includes(`Phonon`)) {
837
909
  return true;
@@ -934,12 +1006,12 @@ export function format_dos_tooltip(x_formatted, y_formatted, label, is_horizonta
934
1006
  };
935
1007
  const lines = is_horizontal
936
1008
  ? [
937
- format_tooltip_line(y_parsed.name || freq_defaults.name, y_formatted, y_parsed.unit || freq_defaults.unit),
1009
+ format_tooltip_line(y_parsed.name || freq_defaults.name, y_formatted, y_parsed.unit ?? freq_defaults.unit),
938
1010
  format_tooltip_line(x_parsed.name || `Density`, x_formatted),
939
1011
  ]
940
1012
  : [
941
1013
  format_tooltip_line(y_parsed.name || `Density`, y_formatted),
942
- format_tooltip_line(x_parsed.name || freq_defaults.name, x_formatted, x_parsed.unit || freq_defaults.unit),
1014
+ format_tooltip_line(x_parsed.name || freq_defaults.name, x_formatted, x_parsed.unit ?? freq_defaults.unit),
943
1015
  ];
944
1016
  return { title: num_series > 1 && label ? label : undefined, lines };
945
1017
  }
@@ -1,6 +1,5 @@
1
1
  import type { ChemicalElement, ElementCategory } from './element/types';
2
2
  import { DEFAULT_CATEGORY_COLORS, default_element_colors } from './colors';
3
- import type { Tooltip } from './plot';
4
3
  import { type ThemeMode, type ThemeType } from './theme';
5
4
  export declare const selected: {
6
5
  category: ElementCategory | null;
@@ -12,12 +11,6 @@ export declare const colors: {
12
11
  category: typeof DEFAULT_CATEGORY_COLORS;
13
12
  element: typeof default_element_colors;
14
13
  };
15
- export declare const tooltip: Tooltip;
16
- export declare const periodic_table_state: {
17
- show_bonding_info: boolean;
18
- show_oxidation_state: boolean;
19
- highlighted_elements: string[];
20
- };
21
14
  export declare const theme_state: {
22
15
  mode: ThemeMode;
23
16
  system_mode: ThemeType;
@@ -11,12 +11,6 @@ export const colors = $state({
11
11
  category: { ...DEFAULT_CATEGORY_COLORS },
12
12
  element: { ...default_element_colors },
13
13
  });
14
- export const tooltip = $state({ show: false, x: 0, y: 0, title: ``, items: [] });
15
- export const periodic_table_state = $state({
16
- show_bonding_info: false,
17
- show_oxidation_state: false,
18
- highlighted_elements: [],
19
- });
20
14
  // Theme state with safe initialization
21
15
  let initial_theme_mode = AUTO_THEME;
22
16
  let initial_system_mode = COLOR_THEMES.light;
@@ -42,11 +42,9 @@
42
42
  arrow_head_radius < 0 ? shaft_len * -arrow_head_radius : arrow_head_radius,
43
43
  )
44
44
 
45
- const shaft_pos = $derived(
46
- math.add(position, math.scale(dir, shaft_len * 0.5)) as Vec3,
47
- )
45
+ const shaft_pos = $derived(math.add(position, math.scale(dir, shaft_len * 0.5)))
48
46
  const head_pos = $derived(
49
- math.add(position, math.scale(dir, shaft_len + head_len * 0.5)) as Vec3,
47
+ math.add(position, math.scale(dir, shaft_len + head_len * 0.5)),
50
48
  )
51
49
 
52
50
  const rotation = $derived.by((): Vec3 => {
@@ -128,8 +128,8 @@
128
128
  // Use unique_values instead of values to avoid undefined colors from duplicates
129
129
  property_colors?.unique_values?.flatMap((val) => {
130
130
  const idx = property_colors.values.indexOf(val)
131
- return idx >= 0 ? [[val, property_colors.colors[idx]]] : []
132
- }) ?? [],
131
+ return idx !== -1 ? [[val, property_colors.colors[idx]]] : []
132
+ }),
133
133
  ),
134
134
  )
135
135
 
@@ -324,6 +324,7 @@
324
324
 
325
325
  {#if show_element_legend}
326
326
  <div {...rest} class="atom-legend element-legend {rest.class ?? ``}">
327
+ {@render mode_selector_snippet()}
327
328
  {#each sorted_element_entries as [elem, amt], idx (elem)}
328
329
  {@const is_hidden = hidden_elements.has(elem as ElementSymbol)}
329
330
  {@const displayed_elem = element_mapping?.[elem as ElementSymbol] || elem}
@@ -465,7 +466,6 @@
465
466
  </div>
466
467
  {/each}
467
468
  {@render site_radius_control_snippet()}
468
- {@render mode_selector_snippet()}
469
469
  {@render children?.({ mode_menu_open, structure })}
470
470
  </div>
471
471
  {:else if show_property_legend}
@@ -474,6 +474,7 @@
474
474
  class:categorical-legend={atom_color_config.scale_type === `categorical`}
475
475
  {...rest}
476
476
  >
477
+ {@render mode_selector_snippet()}
477
478
  {#if legend_title}
478
479
  <div class="legend-header">
479
480
  <h4>{legend_title}</h4>
@@ -533,7 +534,6 @@
533
534
  {/each}
534
535
  {/if}
535
536
  {@render site_radius_control_snippet()}
536
- {@render mode_selector_snippet()}
537
537
  {@render children?.({ mode_menu_open, structure })}
538
538
  </div>
539
539
  {/if}
@@ -723,7 +723,8 @@
723
723
  position: relative;
724
724
  display: flex;
725
725
  align-items: center;
726
- margin-left: calc(-0.5 * var(--struct-legend-gap, clamp(3pt, 2cqmin, 7pt)));
726
+ /* extra gap toward the color labels so the chevron groups with the cell-select control */
727
+ margin-right: calc(0.25 * var(--struct-legend-gap, clamp(3pt, 2cqmin, 7pt)));
727
728
  }
728
729
  .mode-toggle {
729
730
  background: transparent;
@@ -735,17 +736,15 @@
735
736
  font-size: 0.9em;
736
737
  opacity: 0;
737
738
  pointer-events: none;
739
+ transform: translateY(1px);
738
740
  transition: opacity 0.2s ease;
739
741
  }
740
742
  .mode-toggle :global(svg) {
741
743
  font-size: 1.15em;
742
744
  }
743
745
  .mode-toggle.visible {
744
- opacity: 0.7;
745
- pointer-events: auto;
746
- }
747
- .mode-toggle.visible:hover {
748
746
  opacity: 1;
747
+ pointer-events: auto;
749
748
  }
750
749
  .mode-dropdown {
751
750
  position: absolute;
@@ -30,6 +30,6 @@ type $$ComponentProps = Omit<HTMLAttributes<HTMLDivElement>, `children`> & {
30
30
  structure?: AnyStructure | null;
31
31
  }]>;
32
32
  };
33
- declare const AtomLegend: import("svelte").Component<$$ComponentProps, {}, "labels" | "site_radius_overrides" | "atom_color_config" | "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "element_mapping">;
33
+ declare const AtomLegend: import("svelte").Component<$$ComponentProps, {}, "labels" | "atom_color_config" | "hidden_elements" | "hidden_prop_vals" | "element_mapping" | "element_radius_overrides" | "site_radius_overrides">;
34
34
  type AtomLegend = ReturnType<typeof AtomLegend>;
35
35
  export default AtomLegend;
@@ -19,6 +19,7 @@
19
19
  <style>
20
20
  div {
21
21
  width: max-content;
22
+ max-width: var(--canvas-tooltip-max-width, 16em);
22
23
  box-sizing: border-box;
23
24
  text-align: var(--canvas-tooltip-text-align, left);
24
25
  border-radius: var(--canvas-tooltip-border-radius, var(--border-radius, 3pt));
@@ -14,6 +14,7 @@
14
14
  loading = $bindable(false),
15
15
  direction = `down`,
16
16
  align = `right`,
17
+ suppress_hover = false,
17
18
  }: {
18
19
  supercell_scaling: string
19
20
  cell_type?: CellType
@@ -21,6 +22,7 @@
21
22
  loading?: boolean
22
23
  direction?: `up` | `down`
23
24
  align?: `left` | `right`
25
+ suppress_hover?: boolean // don't auto-open the menu on hover/focus (e.g. while a sibling popover is open)
24
26
  } = $props()
25
27
 
26
28
  let menu_open = $state(false)
@@ -80,20 +82,26 @@
80
82
  input_value = supercell_scaling
81
83
  }
82
84
  })
85
+
86
+ // Close + keep closed while suppressed so the menu can't obscure a sibling popover
87
+ // (e.g. the atom color-mode dropdown) the user is actively interacting with
88
+ $effect(() => {
89
+ if (suppress_hover) menu_open = false
90
+ })
83
91
  </script>
84
92
 
85
93
  <div
86
94
  class="cell-select"
87
95
  role="group"
88
96
  {@attach click_outside({ callback: () => (menu_open = false) })}
89
- onmouseenter={() => (menu_open = true)}
97
+ onmouseenter={() => (menu_open = !suppress_hover)}
90
98
  onmouseleave={() => (menu_open = false)}
91
- onfocusin={() => (menu_open = true)}
99
+ onfocusin={() => (menu_open = !suppress_hover)}
92
100
  onfocusout={handle_focus_out}
93
101
  >
94
102
  <button
95
103
  type="button"
96
- onclick={() => (menu_open = !menu_open)}
104
+ onclick={() => (menu_open = !suppress_hover && !menu_open)}
97
105
  onkeydown={handle_key_down}
98
106
  class="toggle-btn"
99
107
  class:active={menu_open}
@@ -296,8 +304,7 @@
296
304
  gap: 3px;
297
305
  }
298
306
  .preset-btn {
299
- padding: 0 1px;
300
- line-height: 1;
307
+ padding: 1px;
301
308
  background: var(--btn-bg, light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.1)));
302
309
  border: 1px solid var(--border-color);
303
310
  border-radius: var(--border-radius, 3pt);
@@ -7,7 +7,8 @@ type $$ComponentProps = {
7
7
  loading?: boolean;
8
8
  direction?: `up` | `down`;
9
9
  align?: `left` | `right`;
10
+ suppress_hover?: boolean;
10
11
  };
11
- declare const CellSelect: import("svelte").Component<$$ComponentProps, {}, "loading" | "supercell_scaling" | "cell_type">;
12
+ declare const CellSelect: import("svelte").Component<$$ComponentProps, {}, "supercell_scaling" | "cell_type" | "loading">;
12
13
  type CellSelect = ReturnType<typeof CellSelect>;
13
14
  export default CellSelect;
@@ -1,14 +1,18 @@
1
1
  <script lang="ts">
2
2
  import type { Vec3 } from '../math'
3
3
  import { T } from '@threlte/core'
4
+ import type { ComponentProps } from 'svelte'
4
5
  import { Euler, Quaternion, Vector3 } from 'three'
5
6
 
6
- let { from, to, color = `#808080`, thickness = 0.1 }: {
7
- from: Vec3
8
- to: Vec3
9
- color?: string
10
- thickness?: number
11
- } = $props()
7
+ let { from, to, color = `#808080`, thickness = 0.1, opacity = 1, ...rest }:
8
+ & ComponentProps<typeof T.Mesh>
9
+ & {
10
+ from: Vec3
11
+ to: Vec3
12
+ color?: string
13
+ thickness?: number
14
+ opacity?: number // < 1 renders semi/fully transparent (e.g. invisible hover proxies)
15
+ } = $props()
12
16
 
13
17
  let from_vec = $derived(new Vector3(...from))
14
18
  let to_vec = $derived(new Vector3(...to))
@@ -39,7 +43,7 @@
39
43
  }
40
44
  </script>
41
45
 
42
- <T.Mesh {position} {rotation} scale={[thickness, height, thickness]}>
46
+ <T.Mesh {...rest} {position} {rotation} scale={[thickness, height, thickness]}>
43
47
  <T.CylinderGeometry args={[thickness, thickness, 1, 8]} />
44
- <T.MeshStandardMaterial {color} />
48
+ <T.MeshStandardMaterial {color} transparent={opacity < 1} {opacity} depthWrite={opacity >= 1} />
45
49
  </T.Mesh>
@@ -1,9 +1,12 @@
1
1
  import type { Vec3 } from '../math';
2
- type $$ComponentProps = {
2
+ import { T } from '@threlte/core';
3
+ import type { ComponentProps } from 'svelte';
4
+ type $$ComponentProps = ComponentProps<typeof T.Mesh> & {
3
5
  from: Vec3;
4
6
  to: Vec3;
5
7
  color?: string;
6
8
  thickness?: number;
9
+ opacity?: number;
7
10
  };
8
11
  declare const Cylinder: import("svelte").Component<$$ComponentProps, {}, "">;
9
12
  type Cylinder = ReturnType<typeof Cylinder>;
@@ -146,7 +146,7 @@
146
146
  {#each matrix as vec, idx (vec)}
147
147
  {@const shaft_length = Math.hypot(...vec) * 0.85}
148
148
  <!-- Shaft goes to 85% of vector length -->
149
- {@const tip_start_position = math.scale(vec, 0.85) as Vec3}
149
+ {@const tip_start_position = math.scale(vec, 0.85)}
150
150
  <!-- Calculate rotation to align with vector direction -->
151
151
  {@const quaternion = new Quaternion().setFromUnitVectors(
152
152
  new Vector3(0, 1, 0), // Default up direction for cylinder/cone
@@ -157,7 +157,7 @@
157
157
  .toArray()
158
158
  .slice(0, 3) as Vec3}
159
159
  <!-- Arrow shaft - position at center of shaft length -->
160
- {@const shaft_center = math.scale(vec, 0.425) as Vec3}
160
+ {@const shaft_center = math.scale(vec, 0.425)}
161
161
  <!-- Center at 42.5% = half of 85% -->
162
162
  <T.Mesh
163
163
  position={shaft_center}