matterviz 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. package/dist/EmptyState.svelte +10 -2
  2. package/dist/FilePicker.svelte +154 -96
  3. package/dist/Icon.svelte +20 -14
  4. package/dist/MillerIndexInput.svelte +27 -21
  5. package/dist/api/optimade.js +6 -6
  6. package/dist/app.css +216 -178
  7. package/dist/brillouin/BrillouinZone.svelte +299 -198
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +74 -55
  11. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte +277 -165
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  15. package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
  16. package/dist/brillouin/compute.js +11 -6
  17. package/dist/chempot-diagram/ChemPotDiagram.svelte +327 -0
  18. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
  19. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +847 -0
  20. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
  21. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +3194 -0
  22. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
  23. package/dist/chempot-diagram/ChemPotScene3D.svelte +11 -0
  24. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
  25. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  26. package/dist/chempot-diagram/async-compute.svelte.js +77 -0
  27. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  28. package/dist/chempot-diagram/chempot-worker.js +11 -0
  29. package/dist/chempot-diagram/color.d.ts +10 -0
  30. package/dist/chempot-diagram/color.js +32 -0
  31. package/dist/chempot-diagram/compute.d.ts +48 -0
  32. package/dist/chempot-diagram/compute.js +812 -0
  33. package/dist/chempot-diagram/index.d.ts +6 -0
  34. package/dist/chempot-diagram/index.js +6 -0
  35. package/dist/chempot-diagram/pointer.d.ts +16 -0
  36. package/dist/chempot-diagram/pointer.js +40 -0
  37. package/dist/chempot-diagram/temperature.d.ts +15 -0
  38. package/dist/chempot-diagram/temperature.js +36 -0
  39. package/dist/chempot-diagram/types.d.ts +86 -0
  40. package/dist/chempot-diagram/types.js +28 -0
  41. package/dist/colors/index.d.ts +3 -1
  42. package/dist/colors/index.js +9 -3
  43. package/dist/composition/BarChart.svelte +141 -77
  44. package/dist/composition/BubbleChart.svelte +107 -52
  45. package/dist/composition/Composition.svelte +100 -79
  46. package/dist/composition/Formula.svelte +108 -62
  47. package/dist/composition/FormulaFilter.svelte +973 -353
  48. package/dist/composition/FormulaFilter.svelte.d.ts +35 -1
  49. package/dist/composition/PieChart.svelte +199 -99
  50. package/dist/composition/PieChart.svelte.d.ts +1 -1
  51. package/dist/composition/format.d.ts +5 -0
  52. package/dist/composition/format.js +20 -3
  53. package/dist/composition/parse.js +14 -9
  54. package/dist/convex-hull/ConvexHull.svelte +93 -38
  55. package/dist/convex-hull/ConvexHull2D.svelte +551 -393
  56. package/dist/convex-hull/ConvexHull3D.svelte +1303 -825
  57. package/dist/convex-hull/ConvexHull4D.svelte +1012 -686
  58. package/dist/convex-hull/ConvexHullControls.svelte +115 -28
  59. package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
  60. package/dist/convex-hull/ConvexHullStats.svelte +821 -249
  61. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
  62. package/dist/convex-hull/ConvexHullTooltip.svelte +41 -16
  63. package/dist/convex-hull/GasPressureControls.svelte +104 -61
  64. package/dist/convex-hull/StructurePopup.svelte +25 -4
  65. package/dist/convex-hull/TemperatureSlider.svelte +45 -25
  66. package/dist/convex-hull/barycentric-coords.js +13 -7
  67. package/dist/convex-hull/demo-temperature.d.ts +6 -0
  68. package/dist/convex-hull/demo-temperature.js +40 -0
  69. package/dist/convex-hull/gas-thermodynamics.js +17 -12
  70. package/dist/convex-hull/helpers.d.ts +10 -1
  71. package/dist/convex-hull/helpers.js +79 -38
  72. package/dist/convex-hull/index.d.ts +1 -0
  73. package/dist/convex-hull/index.js +1 -0
  74. package/dist/convex-hull/thermodynamics.d.ts +8 -21
  75. package/dist/convex-hull/thermodynamics.js +163 -69
  76. package/dist/convex-hull/types.d.ts +12 -12
  77. package/dist/convex-hull/types.js +0 -12
  78. package/dist/coordination/CoordinationBarPlot.svelte +232 -176
  79. package/dist/element/BohrAtom.svelte +56 -13
  80. package/dist/element/ElementHeading.svelte +7 -2
  81. package/dist/element/ElementPhoto.svelte +15 -9
  82. package/dist/element/ElementStats.svelte +10 -4
  83. package/dist/element/ElementTile.svelte +137 -73
  84. package/dist/element/Nucleus.svelte +39 -11
  85. package/dist/element/data.js +2 -14
  86. package/dist/element/data.json.gz +0 -0
  87. package/dist/element/types.d.ts +1 -0
  88. package/dist/feedback/ClickFeedback.svelte +16 -5
  89. package/dist/feedback/DragOverlay.svelte +10 -2
  90. package/dist/feedback/Spinner.svelte +4 -2
  91. package/dist/feedback/StatusMessage.svelte +8 -2
  92. package/dist/fermi-surface/FermiSlice.svelte +118 -88
  93. package/dist/fermi-surface/FermiSurface.svelte +336 -239
  94. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  95. package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
  96. package/dist/fermi-surface/FermiSurfaceScene.svelte +536 -343
  97. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  98. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
  99. package/dist/fermi-surface/compute.js +16 -20
  100. package/dist/fermi-surface/parse.js +37 -33
  101. package/dist/fermi-surface/symmetry.js +2 -7
  102. package/dist/fermi-surface/types.d.ts +3 -5
  103. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1527 -0
  104. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
  105. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
  106. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +30 -0
  107. package/dist/heatmap-matrix/index.d.ts +53 -0
  108. package/dist/heatmap-matrix/index.js +100 -0
  109. package/dist/heatmap-matrix/shared.d.ts +2 -0
  110. package/dist/heatmap-matrix/shared.js +4 -0
  111. package/dist/icons.d.ts +111 -0
  112. package/dist/icons.js +158 -0
  113. package/dist/index.d.ts +5 -2
  114. package/dist/index.js +5 -2
  115. package/dist/io/decompress.js +1 -1
  116. package/dist/io/export.d.ts +3 -0
  117. package/dist/io/export.js +138 -140
  118. package/dist/io/file-drop.d.ts +7 -0
  119. package/dist/io/file-drop.js +43 -0
  120. package/dist/io/index.d.ts +2 -2
  121. package/dist/io/index.js +2 -112
  122. package/dist/io/is-binary.js +2 -3
  123. package/dist/io/types.d.ts +1 -0
  124. package/dist/io/url-drop.d.ts +2 -0
  125. package/dist/io/url-drop.js +117 -0
  126. package/dist/isosurface/Isosurface.svelte +220 -110
  127. package/dist/isosurface/IsosurfaceControls.svelte +65 -28
  128. package/dist/isosurface/parse.js +104 -56
  129. package/dist/isosurface/slice.d.ts +2 -1
  130. package/dist/isosurface/slice.js +8 -13
  131. package/dist/isosurface/types.d.ts +14 -1
  132. package/dist/isosurface/types.js +152 -5
  133. package/dist/labels.d.ts +2 -1
  134. package/dist/labels.js +12 -8
  135. package/dist/layout/FullscreenToggle.svelte +11 -2
  136. package/dist/layout/InfoCard.svelte +38 -6
  137. package/dist/layout/InfoTag.svelte +125 -94
  138. package/dist/layout/PropertyFilter.svelte +82 -37
  139. package/dist/layout/SettingsSection.svelte +85 -55
  140. package/dist/layout/SubpageGrid.svelte +82 -0
  141. package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
  142. package/dist/layout/index.d.ts +1 -0
  143. package/dist/layout/index.js +1 -0
  144. package/dist/layout/json-tree/JsonNode.svelte +266 -223
  145. package/dist/layout/json-tree/JsonTree.svelte +516 -429
  146. package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
  147. package/dist/layout/json-tree/JsonValue.svelte +281 -173
  148. package/dist/layout/json-tree/types.d.ts +10 -2
  149. package/dist/layout/json-tree/utils.d.ts +2 -0
  150. package/dist/layout/json-tree/utils.js +37 -2
  151. package/dist/marching-cubes.js +25 -2
  152. package/dist/math.d.ts +20 -17
  153. package/dist/math.js +474 -57
  154. package/dist/overlays/ContextMenu.svelte +66 -40
  155. package/dist/overlays/DraggablePane.svelte +331 -154
  156. package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
  157. package/dist/periodic-table/PeriodicTable.svelte +278 -145
  158. package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
  159. package/dist/periodic-table/PropertySelect.svelte +25 -7
  160. package/dist/periodic-table/TableInset.svelte +8 -3
  161. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +559 -267
  162. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
  163. package/dist/phase-diagram/PhaseDiagramControls.svelte +131 -51
  164. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
  165. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
  166. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
  167. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +160 -110
  168. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +8 -1
  169. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +217 -86
  170. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
  171. package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
  172. package/dist/phase-diagram/build-diagram.js +9 -9
  173. package/dist/phase-diagram/colors.js +1 -3
  174. package/dist/phase-diagram/index.d.ts +2 -0
  175. package/dist/phase-diagram/index.js +2 -0
  176. package/dist/phase-diagram/parse.js +10 -9
  177. package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
  178. package/dist/phase-diagram/svg-to-diagram.js +869 -0
  179. package/dist/phase-diagram/types.d.ts +10 -0
  180. package/dist/phase-diagram/utils.d.ts +8 -4
  181. package/dist/phase-diagram/utils.js +219 -74
  182. package/dist/plot/AxisLabel.svelte +51 -0
  183. package/dist/plot/AxisLabel.svelte.d.ts +16 -0
  184. package/dist/plot/BarPlot.svelte +1461 -768
  185. package/dist/plot/BarPlot.svelte.d.ts +3 -3
  186. package/dist/plot/BarPlotControls.svelte +33 -6
  187. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  188. package/dist/plot/ColorBar.svelte +533 -383
  189. package/dist/plot/ColorBar.svelte.d.ts +1 -1
  190. package/dist/plot/ColorScaleSelect.svelte +28 -7
  191. package/dist/plot/ElementScatter.svelte +38 -16
  192. package/dist/plot/FillArea.svelte +152 -92
  193. package/dist/plot/Histogram.svelte +1162 -709
  194. package/dist/plot/Histogram.svelte.d.ts +1 -1
  195. package/dist/plot/HistogramControls.svelte +81 -18
  196. package/dist/plot/HistogramControls.svelte.d.ts +6 -2
  197. package/dist/plot/InteractiveAxisLabel.svelte +34 -11
  198. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  199. package/dist/plot/Line.svelte +63 -28
  200. package/dist/plot/PlotControls.svelte +221 -96
  201. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  202. package/dist/plot/PlotLegend.svelte +174 -91
  203. package/dist/plot/PlotTooltip.svelte +45 -6
  204. package/dist/plot/PortalSelect.svelte +175 -146
  205. package/dist/plot/ReferenceLine.svelte +77 -22
  206. package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
  207. package/dist/plot/ReferenceLine3D.svelte +132 -107
  208. package/dist/plot/ReferencePlane.svelte +146 -123
  209. package/dist/plot/ScatterPlot.svelte +1880 -1156
  210. package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
  211. package/dist/plot/ScatterPlot3D.svelte +256 -131
  212. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  213. package/dist/plot/ScatterPlot3DControls.svelte +300 -297
  214. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
  215. package/dist/plot/ScatterPlot3DScene.svelte +608 -406
  216. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  217. package/dist/plot/ScatterPlotControls.svelte +150 -70
  218. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  219. package/dist/plot/ScatterPoint.svelte +98 -26
  220. package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
  221. package/dist/plot/SpacegroupBarPlot.svelte +142 -85
  222. package/dist/plot/Surface3D.svelte +159 -108
  223. package/dist/plot/ZeroLines.svelte +96 -0
  224. package/dist/plot/ZeroLines.svelte.d.ts +32 -0
  225. package/dist/plot/ZoomRect.svelte +23 -0
  226. package/dist/plot/ZoomRect.svelte.d.ts +8 -0
  227. package/dist/plot/axis-utils.d.ts +1 -1
  228. package/dist/plot/axis-utils.js +1 -3
  229. package/dist/plot/data-cleaning.js +12 -28
  230. package/dist/plot/data-transform.js +2 -1
  231. package/dist/plot/fill-utils.js +2 -0
  232. package/dist/plot/index.d.ts +6 -2
  233. package/dist/plot/index.js +6 -2
  234. package/dist/plot/interactions.d.ts +8 -10
  235. package/dist/plot/interactions.js +2 -3
  236. package/dist/plot/layout.d.ts +11 -2
  237. package/dist/plot/layout.js +44 -17
  238. package/dist/plot/reference-line.d.ts +5 -22
  239. package/dist/plot/reference-line.js +12 -84
  240. package/dist/plot/scales.js +24 -36
  241. package/dist/plot/types.d.ts +53 -40
  242. package/dist/plot/types.js +12 -7
  243. package/dist/plot/utils/label-placement.d.ts +32 -15
  244. package/dist/plot/utils/label-placement.js +227 -63
  245. package/dist/plot/utils/series-visibility.js +2 -3
  246. package/dist/plot/utils.d.ts +1 -0
  247. package/dist/plot/utils.js +14 -0
  248. package/dist/rdf/RdfPlot.svelte +173 -132
  249. package/dist/rdf/calc-rdf.js +4 -5
  250. package/dist/sanitize.d.ts +4 -0
  251. package/dist/sanitize.js +107 -0
  252. package/dist/settings.d.ts +21 -6
  253. package/dist/settings.js +63 -19
  254. package/dist/spectral/Bands.svelte +963 -412
  255. package/dist/spectral/Bands.svelte.d.ts +22 -2
  256. package/dist/spectral/BandsAndDos.svelte +90 -49
  257. package/dist/spectral/BrillouinBandsDos.svelte +151 -93
  258. package/dist/spectral/Dos.svelte +389 -258
  259. package/dist/spectral/helpers.d.ts +23 -1
  260. package/dist/spectral/helpers.js +119 -51
  261. package/dist/spectral/types.d.ts +2 -0
  262. package/dist/state.svelte.d.ts +1 -1
  263. package/dist/state.svelte.js +3 -2
  264. package/dist/structure/Arrow.svelte +59 -20
  265. package/dist/structure/AtomLegend.svelte +231 -129
  266. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  267. package/dist/structure/Bond.svelte +73 -47
  268. package/dist/structure/CanvasTooltip.svelte +10 -2
  269. package/dist/structure/CellSelect.svelte +148 -51
  270. package/dist/structure/Cylinder.svelte +33 -17
  271. package/dist/structure/Lattice.svelte +88 -33
  272. package/dist/structure/Structure.svelte +1077 -821
  273. package/dist/structure/Structure.svelte.d.ts +1 -1
  274. package/dist/structure/StructureControls.svelte +373 -139
  275. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  276. package/dist/structure/StructureExportPane.svelte +124 -89
  277. package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
  278. package/dist/structure/StructureInfoPane.svelte +304 -231
  279. package/dist/structure/StructureScene.svelte +919 -445
  280. package/dist/structure/StructureScene.svelte.d.ts +16 -7
  281. package/dist/structure/atom-properties.d.ts +6 -2
  282. package/dist/structure/atom-properties.js +42 -29
  283. package/dist/structure/bonding.js +6 -7
  284. package/dist/structure/export.js +22 -34
  285. package/dist/structure/ferrox-wasm-types.d.ts +3 -2
  286. package/dist/structure/ferrox-wasm-types.js +0 -3
  287. package/dist/structure/ferrox-wasm.d.ts +3 -2
  288. package/dist/structure/ferrox-wasm.js +2 -3
  289. package/dist/structure/index.d.ts +16 -0
  290. package/dist/structure/index.js +88 -6
  291. package/dist/structure/measure.d.ts +2 -2
  292. package/dist/structure/measure.js +4 -44
  293. package/dist/structure/parse.js +130 -155
  294. package/dist/structure/partial-occupancy.d.ts +25 -0
  295. package/dist/structure/partial-occupancy.js +99 -0
  296. package/dist/structure/pbc.d.ts +1 -0
  297. package/dist/structure/pbc.js +16 -6
  298. package/dist/structure/supercell.d.ts +2 -2
  299. package/dist/structure/supercell.js +12 -22
  300. package/dist/structure/validation.js +5 -3
  301. package/dist/symmetry/SymmetryStats.svelte +94 -37
  302. package/dist/symmetry/WyckoffTable.svelte +42 -14
  303. package/dist/symmetry/cell-transform.js +5 -3
  304. package/dist/symmetry/index.d.ts +7 -4
  305. package/dist/symmetry/index.js +87 -21
  306. package/dist/symmetry/spacegroups.js +148 -148
  307. package/dist/table/HeatmapTable.svelte +1112 -516
  308. package/dist/table/HeatmapTable.svelte.d.ts +12 -1
  309. package/dist/table/ToggleMenu.svelte +125 -90
  310. package/dist/table/index.d.ts +2 -0
  311. package/dist/table/index.js +2 -4
  312. package/dist/theme/ThemeControl.svelte +21 -12
  313. package/dist/time.js +4 -1
  314. package/dist/tooltip/TooltipContent.svelte +33 -8
  315. package/dist/trajectory/Trajectory.svelte +889 -687
  316. package/dist/trajectory/TrajectoryError.svelte +14 -3
  317. package/dist/trajectory/TrajectoryExportPane.svelte +148 -90
  318. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
  319. package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
  320. package/dist/trajectory/constants.d.ts +6 -0
  321. package/dist/trajectory/constants.js +7 -0
  322. package/dist/trajectory/extract.js +13 -31
  323. package/dist/trajectory/format-detect.d.ts +9 -0
  324. package/dist/trajectory/format-detect.js +76 -0
  325. package/dist/trajectory/frame-reader.d.ts +17 -0
  326. package/dist/trajectory/frame-reader.js +332 -0
  327. package/dist/trajectory/helpers.d.ts +14 -0
  328. package/dist/trajectory/helpers.js +172 -0
  329. package/dist/trajectory/index.d.ts +1 -0
  330. package/dist/trajectory/index.js +23 -14
  331. package/dist/trajectory/parse/ase.d.ts +2 -0
  332. package/dist/trajectory/parse/ase.js +77 -0
  333. package/dist/trajectory/parse/hdf5.d.ts +2 -0
  334. package/dist/trajectory/parse/hdf5.js +129 -0
  335. package/dist/trajectory/parse/index.d.ts +12 -0
  336. package/dist/trajectory/parse/index.js +299 -0
  337. package/dist/trajectory/parse/lammps.d.ts +5 -0
  338. package/dist/trajectory/parse/lammps.js +179 -0
  339. package/dist/trajectory/parse/vasp.d.ts +2 -0
  340. package/dist/trajectory/parse/vasp.js +68 -0
  341. package/dist/trajectory/parse/xyz.d.ts +2 -0
  342. package/dist/trajectory/parse/xyz.js +110 -0
  343. package/dist/trajectory/plotting.js +13 -8
  344. package/dist/trajectory/types.d.ts +11 -0
  345. package/dist/trajectory/types.js +1 -0
  346. package/dist/utils.d.ts +3 -0
  347. package/dist/utils.js +17 -0
  348. package/dist/xrd/XrdPlot.svelte +337 -245
  349. package/dist/xrd/broadening.js +14 -9
  350. package/dist/xrd/calc-xrd.js +12 -19
  351. package/dist/xrd/parse.d.ts +1 -1
  352. package/dist/xrd/parse.js +17 -17
  353. package/package.json +103 -101
  354. package/readme.md +4 -4
  355. package/dist/trajectory/parse.d.ts +0 -42
  356. package/dist/trajectory/parse.js +0 -1267
  357. /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
  358. /package/dist/theme/{themes.js → themes.mjs} +0 -0
@@ -4,7 +4,6 @@ import type { RibbonConfig } from './types';
4
4
  export declare const is_valid_range: (range: unknown) => range is Vec2;
5
5
  export declare const ranges_equal: (a: Vec2 | undefined | null, b: Vec2 | undefined | null, tol?: number) => boolean;
6
6
  export declare function detect_zoom_change(bands_range: unknown, dos_range: unknown, shared_range: Vec2, current_synced: Vec2 | null, dos_enabled?: boolean): Vec2 | null | undefined;
7
- export declare const N_ACOUSTIC_MODES = 3;
8
7
  export declare const IMAGINARY_MODE_NOISE_THRESHOLD = 0.005;
9
8
  export declare function pretty_sym_point(symbol: string): string;
10
9
  export declare const get_segment_key: (start_label?: string, end_label?: string) => string;
@@ -92,4 +91,27 @@ export declare const DEFAULT_UNITS: types.FrequencyUnit;
92
91
  export declare function format_sigma(val: number): string;
93
92
  export declare function validate_sigma_range([min, max]: [number, number]): [number, number];
94
93
  export declare function calculate_sigma_step(range: [number, number]): number;
94
+ export interface BandPointMeta extends Record<string, unknown> {
95
+ band_idx: number;
96
+ spin: `up` | `down`;
97
+ is_acoustic: boolean | null;
98
+ nb_bands: number;
99
+ frac_coords: Vec3 | null;
100
+ qpoint_label: string | null;
101
+ band_width: number | null;
102
+ slope: number | null;
103
+ }
104
+ export declare function compute_slope(x_vals: number[], y_vals: number[], idx: number): number | null;
105
+ export declare function find_gamma_indices(bs: types.BaseBandStructure): number[];
106
+ export declare const ACOUSTIC_FREQ_THRESHOLD = 0.5;
107
+ export declare function classify_acoustic(bs: types.BaseBandStructure, band_idx: number, gamma_indices: number[], threshold?: number): boolean | null;
108
+ export declare function build_point_metadata(opts: {
109
+ x_vals: number[];
110
+ y_vals: number[];
111
+ band_idx: number;
112
+ spin: `up` | `down`;
113
+ is_acoustic: boolean | null;
114
+ bs: types.BaseBandStructure;
115
+ start_idx: number;
116
+ }): BandPointMeta[];
95
117
  export {};
@@ -1,6 +1,6 @@
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 { centered_frac, euclidean_dist } from '../math';
4
4
  // Check if range is a valid [min, max] tuple (strict 2-element array of finite numbers)
5
5
  export const is_valid_range = (range) => Array.isArray(range) &&
6
6
  range.length === 2 &&
@@ -52,7 +52,6 @@ const THz_TO_MEV = THz_TO_EV * 1000;
52
52
  const THz_TO_HA = THz_TO_EV / 27.211386245988; // Hartree
53
53
  const THz_TO_CM = THz_TO_HZ / (C_LIGHT * 100); // cm^-1 (c in cm/s)
54
54
  // Band structure constants
55
- export const N_ACOUSTIC_MODES = 3; // Number of acoustic modes in typical 3D crystals
56
55
  export const IMAGINARY_MODE_NOISE_THRESHOLD = 0.005; // Clamp negatives < 0.5% as noise
57
56
  // Convert symmetry point symbols to pretty-printed versions.
58
57
  // Handles Greek letters (both plain and LaTeX backslash-prefixed) and subscripts.
@@ -71,7 +70,10 @@ export function pretty_sym_point(symbol) {
71
70
  .replace(/\\?SIGMA/gi, `Σ`)
72
71
  .replace(/\\?LAMBDA/gi, `Λ`)
73
72
  .replace(/(\p{L})(\d+)/gu, (_, letter, num) => letter +
74
- num.split(``).map((digit) => SUBSCRIPT_MAP[digit] ?? digit).join(``));
73
+ num
74
+ .split(``)
75
+ .map((digit) => SUBSCRIPT_MAP[digit] ?? digit)
76
+ .join(``));
75
77
  }
76
78
  // Create segment key from start and end labels
77
79
  export const get_segment_key = (start_label, end_label) => `${start_label ?? `null`}_${end_label ?? `null`}`;
@@ -149,10 +151,10 @@ export function get_band_xaxis_ticks(band_struct, branches = []) {
149
151
  // Convert frequencies from THz to specified units.
150
152
  export function convert_frequencies(frequencies, unit = `THz`) {
151
153
  const conversion_factors = {
152
- 'THz': 1,
153
- 'eV': THz_TO_EV,
154
- 'meV': THz_TO_MEV,
155
- 'Ha': THz_TO_HA,
154
+ THz: 1,
155
+ eV: THz_TO_EV,
156
+ meV: THz_TO_MEV,
157
+ Ha: THz_TO_HA,
156
158
  'cm-1': THz_TO_CM,
157
159
  };
158
160
  const factor = conversion_factors[unit];
@@ -277,7 +279,9 @@ export function clear_smearing_cache() {
277
279
  }
278
280
  // Type guards for pymatgen qpoint formats
279
281
  const is_vec3 = (val) => Array.isArray(val) && val.length >= 3 && val.slice(0, 3).every(Number.isFinite);
280
- const is_kpoint = (val) => !!val && typeof val === `object` && `frac_coords` in val &&
282
+ const is_kpoint = (val) => !!val &&
283
+ typeof val === `object` &&
284
+ `frac_coords` in val &&
281
285
  is_vec3(val.frac_coords);
282
286
  const is_pymatgen_format = (obj) => {
283
287
  // Check for explicit pymatgen markers
@@ -311,11 +315,6 @@ const CM_TO_THZ = 1 / THz_TO_CM;
311
315
  // Spin key constants for pymatgen spin-polarized data
312
316
  const SPIN_UP_KEYS = [`1`, `Spin.up`];
313
317
  const SPIN_DOWN_KEYS = [`-1`, `Spin.down`];
314
- // Extract first spin channel from pymatgen spin-keyed data.
315
- // Thin wrapper around extract_spin_channels for backwards compatibility.
316
- function extract_first_spin_channel(data) {
317
- return extract_spin_channels(data)?.up ?? null;
318
- }
319
318
  // Extract both spin channels from pymatgen spin-keyed data.
320
319
  // Returns { up: T, down: T | null } where down is null for non-spin-polarized data.
321
320
  export function extract_spin_channels(data) {
@@ -359,7 +358,9 @@ function convert_pymatgen_band_structure(pmg) {
359
358
  // 1. Standard pymatgen: bands as dict with spin keys {1: [[...], ...]}
360
359
  // 2. Custom phonon format: frequencies_cm as 2D array [[...], ...]
361
360
  // 3. Already normalized: bands as 2D array [[...], ...]
362
- let raw_bands = extract_first_spin_channel(pmg.bands);
361
+ const spin_channels = extract_spin_channels(pmg.bands);
362
+ let raw_bands = spin_channels?.up ?? null;
363
+ let raw_spin_down_bands = spin_channels?.down ?? null;
363
364
  const has_frequencies_cm = Array.isArray(pmg.frequencies_cm);
364
365
  if (!raw_bands && has_frequencies_cm) {
365
366
  // Phonon format: frequencies_cm is [n_qpoints x n_branches] - needs transpose
@@ -367,24 +368,30 @@ function convert_pymatgen_band_structure(pmg) {
367
368
  if (freqs.length > 0 && Array.isArray(freqs[0])) {
368
369
  // Transpose: [n_qpoints x n_branches] -> [n_branches x n_qpoints]
369
370
  raw_bands = Array.from({ length: freqs[0].length }, (_, band_idx) => freqs.map((qpt_freqs) => qpt_freqs[band_idx]));
371
+ raw_spin_down_bands = null;
370
372
  }
371
373
  }
372
374
  const labels_dict = pmg.labels_dict;
373
375
  const lattice_rec = pmg.lattice_rec;
374
376
  // Determine unit: cm-1 if frequencies_cm present, else check explicit unit or default to THz
375
- const unit = pmg.unit?.toLowerCase() ??
376
- (has_frequencies_cm ? `cm-1` : `thz`);
377
- if (!Array.isArray(raw_qpts) || !Array.isArray(raw_bands) ||
378
- !raw_qpts.length || !raw_bands.length)
377
+ const unit = pmg.unit?.toLowerCase() ?? (has_frequencies_cm ? `cm-1` : `thz`);
378
+ if (!Array.isArray(raw_qpts) ||
379
+ !Array.isArray(raw_bands) ||
380
+ !raw_qpts.length ||
381
+ !raw_bands.length)
379
382
  return null;
380
- const qpoints = raw_qpts.map((q) => parse_qpoint(q, labels_dict)).filter(Boolean);
383
+ const qpoints = raw_qpts
384
+ .map((q) => parse_qpoint(q, labels_dict))
385
+ .filter((q) => q !== null);
381
386
  if (!qpoints.length)
382
387
  return null;
383
388
  // Step distances and discontinuity detection (5x median threshold)
384
- const steps = qpoints.slice(1).map((q, idx) => euclidean_dist(qpoints[idx].frac_coords, q.frac_coords));
389
+ const steps = qpoints
390
+ .slice(1)
391
+ .map((q, idx) => euclidean_dist(qpoints[idx].frac_coords, q.frac_coords));
385
392
  const sorted = steps.slice().sort((a, b) => a - b);
386
393
  const threshold = (sorted[Math.floor(sorted.length / 2)] ?? 0) * 5;
387
- const disc_set = new Set(steps.map((s, idx) => s > threshold ? idx + 1 : -1).filter((i) => i >= 0));
394
+ const disc_set = new Set(steps.map((s, idx) => (s > threshold ? idx + 1 : -1)).filter((i) => i >= 0));
388
395
  // Cumulative distance (skip discontinuities)
389
396
  const distance = steps.reduce((acc, step, idx) => [...acc, disc_set.has(idx + 1) ? acc[idx] : acc[idx] + step], [0]);
390
397
  // Use pymatgen's branches if available - they correctly handle discontinuities
@@ -401,7 +408,7 @@ function convert_pymatgen_band_structure(pmg) {
401
408
  }
402
409
  // Fallback: infer branches from discontinuities when none provided or all invalid
403
410
  if (branches.length === 0) {
404
- console.info(`Band structure missing 'branches' field - inferring from path discontinuities`);
411
+ console.warn(`Band structure missing 'branches' field - inferring from path discontinuities`);
405
412
  // Discontinuity indices mark points where the path jumps (disc before that index)
406
413
  // Create continuous segments between discontinuities
407
414
  const disc_indices = [...disc_set].sort((a, b) => a - b);
@@ -432,14 +439,28 @@ function convert_pymatgen_band_structure(pmg) {
432
439
  return val * CM_TO_THZ;
433
440
  return val; // THz (default) - no conversion
434
441
  };
442
+ const converted_bands = raw_bands.map((band) => band.map(convert_to_thz));
443
+ const valid_spin_down_bands = Array.isArray(raw_spin_down_bands) &&
444
+ raw_spin_down_bands.length === raw_bands.length &&
445
+ raw_spin_down_bands.every((band, band_idx) => Array.isArray(band) && band.length === raw_bands[band_idx]?.length)
446
+ ? raw_spin_down_bands
447
+ : null;
448
+ const converted_spin_down_bands = valid_spin_down_bands?.map((band) => band.map(convert_to_thz));
435
449
  return {
436
450
  qpoints,
437
451
  branches,
438
452
  distance,
439
- bands: raw_bands.map((band) => band.map(convert_to_thz)),
453
+ bands: converted_bands,
454
+ spin_down_bands: converted_spin_down_bands,
440
455
  nb_bands: raw_bands.length,
441
456
  labels_dict: labels_dict ?? {},
442
- recip_lattice: { matrix: lattice_rec?.matrix ?? [[1, 0, 0], [0, 1, 0], [0, 0, 1]] },
457
+ recip_lattice: {
458
+ matrix: lattice_rec?.matrix ?? [
459
+ [1, 0, 0],
460
+ [0, 1, 0],
461
+ [0, 0, 1],
462
+ ],
463
+ },
443
464
  };
444
465
  }
445
466
  export function normalize_band_structure(bs) {
@@ -478,8 +499,7 @@ export function normalize_dos(dos, options = {}) {
478
499
  return null;
479
500
  const dos_obj = dos;
480
501
  // Check for pymatgen format (has @class or @module)
481
- const is_pymatgen = typeof dos_obj[`@class`] === `string` ||
482
- typeof dos_obj[`@module`] === `string`;
502
+ const is_pymatgen = typeof dos_obj[`@class`] === `string` || typeof dos_obj[`@module`] === `string`;
483
503
  const { frequencies, energies, spin_polarized } = dos_obj;
484
504
  // Handle densities as either array or dict with spin keys (pymatgen format)
485
505
  // Pymatgen stores densities as {1: [...], -1: [...]} or {"Spin.up": [...], ...}
@@ -488,8 +508,7 @@ export function normalize_dos(dos, options = {}) {
488
508
  return null;
489
509
  const densities = spin_channels.up;
490
510
  // Use extracted spin-down or fallback to explicit field (for already-normalized DosData)
491
- const spin_down_densities = spin_channels.down ??
492
- dos_obj.spin_down_densities ?? null;
511
+ const spin_down_densities = spin_channels.down ?? dos_obj.spin_down_densities ?? null;
493
512
  if (!Array.isArray(densities))
494
513
  return null;
495
514
  // Phonon DOS: has frequencies
@@ -504,7 +523,7 @@ export function normalize_dos(dos, options = {}) {
504
523
  if (auto_convert_units && max_freq > 100) {
505
524
  // Likely in cm⁻¹, convert to THz
506
525
  final_frequencies = frequencies.map((f) => f * CM_TO_THZ);
507
- console.info(`Phonon DOS frequencies appear to be in cm⁻¹ (max: ${max_freq.toFixed(1)}). ` +
526
+ console.warn(`Phonon DOS frequencies appear to be in cm⁻¹ (max: ${max_freq.toFixed(1)}). ` +
508
527
  `Converting to THz (max: ${(max_freq * CM_TO_THZ).toFixed(1)} THz).`);
509
528
  }
510
529
  return { type: `phonon`, frequencies: final_frequencies, densities };
@@ -520,9 +539,7 @@ export function normalize_dos(dos, options = {}) {
520
539
  type: `electronic`,
521
540
  energies,
522
541
  densities,
523
- spin_down_densities: is_spin_polarized
524
- ? spin_down_densities ?? undefined
525
- : undefined,
542
+ spin_down_densities: is_spin_polarized ? (spin_down_densities ?? undefined) : undefined,
526
543
  spin_polarized: is_spin_polarized,
527
544
  };
528
545
  }
@@ -553,11 +570,10 @@ export function extract_k_path_points(band_struct, recip_lattice_matrix, options
553
570
  y = centered_frac(y);
554
571
  z = centered_frac(z);
555
572
  }
556
- return [
557
- x * m00 + y * m10 + z * m20,
558
- x * m01 + y * m11 + z * m21,
559
- x * m02 + y * m12 + z * m22,
560
- ];
573
+ const kx = x * m00 + y * m10 + z * m20;
574
+ const ky = x * m01 + y * m11 + z * m21;
575
+ const kz = x * m02 + y * m12 + z * m22;
576
+ return [kx, ky, kz];
561
577
  });
562
578
  }
563
579
  // Find the q-point index closest to a given distance along the band structure path
@@ -633,7 +649,10 @@ export function find_qpoint_at_rescaled_x(band_struct, rescaled_x, x_positions)
633
649
  if (!segment_range)
634
650
  continue;
635
651
  const [x_start, x_end] = segment_range;
636
- for (const [x_pos, idx] of [[x_start, start_idx], [x_end, end_idx]]) {
652
+ for (const [x_pos, idx] of [
653
+ [x_start, start_idx],
654
+ [x_end, end_idx],
655
+ ]) {
637
656
  const dist = Math.abs(rescaled_x - x_pos);
638
657
  if (dist < min_dist) {
639
658
  min_dist = dist;
@@ -670,15 +689,12 @@ export function extract_pdos(dos, pdos_type, filter_keys) {
670
689
  const densities = spin_channels.up;
671
690
  if (!Array.isArray(densities) || energies.length !== densities.length)
672
691
  continue;
673
- const is_spin_polarized = spin_channels.down !== null &&
674
- spin_channels.down.length === densities.length;
692
+ const is_spin_polarized = spin_channels.down !== null && spin_channels.down.length === densities.length;
675
693
  result[key] = {
676
694
  type: `electronic`,
677
695
  energies,
678
696
  densities,
679
- spin_down_densities: is_spin_polarized
680
- ? spin_channels.down ?? undefined
681
- : undefined,
697
+ spin_down_densities: is_spin_polarized ? (spin_channels.down ?? undefined) : undefined,
682
698
  spin_polarized: is_spin_polarized,
683
699
  efermi: nested_dos.efermi,
684
700
  };
@@ -738,9 +754,7 @@ export function generate_ribbon_path(x_values, y_values, width_values, x_scale_f
738
754
  const x_px = x_scale_fn(x_values[idx]);
739
755
  const y_data = y_values[idx];
740
756
  const raw_width = width_values[idx] ?? 0;
741
- const width_normalized = Number.isFinite(raw_width) && raw_width > 0
742
- ? raw_width / max_width_val
743
- : 0;
757
+ const width_normalized = Number.isFinite(raw_width) && raw_width > 0 ? raw_width / max_width_val : 0;
744
758
  const half_width_px = width_normalized * max_width_px * scale;
745
759
  // In SVG, y increases downward, so upper edge has smaller y value
746
760
  const y_upper_px = y_scale_fn(y_data) - half_width_px;
@@ -752,7 +766,7 @@ export function generate_ribbon_path(x_values, y_values, width_values, x_scale_f
752
766
  const path_parts = [
753
767
  `M${upper_points[0]}`,
754
768
  ...upper_points.slice(1).map((pt) => `L${pt}`),
755
- ...lower_points.reverse().map((pt) => `L${pt}`),
769
+ ...lower_points.toReversed().map((pt) => `L${pt}`),
756
770
  `Z`,
757
771
  ];
758
772
  return path_parts.join(` `);
@@ -806,7 +820,8 @@ function is_electronic_band_struct(bs) {
806
820
  return true;
807
821
  }
808
822
  // Pymatgen @class: BandStructure* but not Phonon*
809
- const py_class_name = String(obj[`@class`] ?? ``);
823
+ const raw_class = obj[`@class`];
824
+ const py_class_name = typeof raw_class === `string` ? raw_class : ``;
810
825
  if (py_class_name.startsWith(`BandStructure`) && !py_class_name.includes(`Phonon`)) {
811
826
  return true;
812
827
  }
@@ -820,7 +835,8 @@ export function compute_frequency_range(band_structs, doses, padding_factor = 0.
820
835
  // (normalized structures always have qpoints, so we can't detect from them)
821
836
  let has_electronic_bs = false;
822
837
  // Support both qpoints (phonon) and kpoints (electronic) to detect single vs dict
823
- const is_single_bs = band_structs && typeof band_structs === `object` &&
838
+ const is_single_bs = band_structs &&
839
+ typeof band_structs === `object` &&
824
840
  (`qpoints` in band_structs || `kpoints` in band_structs);
825
841
  if (band_structs && typeof band_structs === `object`) {
826
842
  // Single structure check
@@ -882,7 +898,8 @@ export function compute_frequency_range(band_structs, doses, padding_factor = 0.
882
898
  }
883
899
  if (!Number.isFinite(min_val) || !Number.isFinite(max_val))
884
900
  return undefined;
885
- const clamp_min = is_phonon && min_val < 0 && // clamp phonon noise to 0
901
+ const clamp_min = is_phonon &&
902
+ min_val < 0 && // clamp phonon noise to 0
886
903
  negative_fraction(all_freqs) < IMAGINARY_MODE_NOISE_THRESHOLD;
887
904
  if (clamp_min)
888
905
  min_val = 0;
@@ -892,7 +909,7 @@ export function compute_frequency_range(band_structs, doses, padding_factor = 0.
892
909
  }
893
910
  // Parse axis label: "Frequency (THz)" → { name: "Frequency", unit: "THz" }
894
911
  function parse_axis_label(label) {
895
- const match = label.match(/^(.+?)\s*\(([^)]+)\)$/);
912
+ const match = /^(.+?)\s*\(([^)]+)\)$/.exec(label);
896
913
  return match ? { name: match[1], unit: match[2] } : { name: label };
897
914
  }
898
915
  // Format DOS tooltip content from axis labels and values
@@ -953,3 +970,54 @@ export function calculate_sigma_step(range) {
953
970
  const [min, max] = validate_sigma_range(range);
954
971
  return (max - min) / 100 || 0.01;
955
972
  }
973
+ // Central difference for local slope (dω/dk or dE/dk).
974
+ // Uses forward/backward difference at endpoints, central difference for interior points.
975
+ export function compute_slope(x_vals, y_vals, idx) {
976
+ const len = Math.min(x_vals.length, y_vals.length);
977
+ if (len < 2 || idx < 0 || idx >= len)
978
+ return null;
979
+ const lo = idx === 0 ? 0 : idx - 1;
980
+ const hi = idx >= len - 1 ? len - 1 : idx + 1;
981
+ const dx = x_vals[hi] - x_vals[lo];
982
+ return dx ? (y_vals[hi] - y_vals[lo]) / dx : null;
983
+ }
984
+ // Find Gamma-point indices (q ≈ integer lattice point) in a band structure.
985
+ // Returns indices of q-points whose fractional coordinates are all within 0.01 of integers.
986
+ export function find_gamma_indices(bs) {
987
+ const indices = [];
988
+ for (let q_idx = 0; q_idx < bs.qpoints.length; q_idx++) {
989
+ const coords = bs.qpoints[q_idx]?.frac_coords;
990
+ if (coords?.every((coord) => Math.abs(coord - Math.round(coord)) < 0.01)) {
991
+ indices.push(q_idx);
992
+ }
993
+ }
994
+ return indices;
995
+ }
996
+ // Threshold below which a band's frequency at Gamma is considered acoustic (THz).
997
+ // Assumes bands are stored in THz (normalize_band_structure converts to THz).
998
+ export const ACOUSTIC_FREQ_THRESHOLD = 0.5;
999
+ // Classify a band as acoustic based on near-zero frequency at Gamma points.
1000
+ // Returns true (acoustic), false (optical), or null (no Gamma points → can't determine).
1001
+ export function classify_acoustic(bs, band_idx, gamma_indices, threshold = ACOUSTIC_FREQ_THRESHOLD) {
1002
+ if (gamma_indices.length === 0)
1003
+ return null;
1004
+ return gamma_indices.some((gamma_idx) => Math.abs(bs.bands[band_idx]?.[gamma_idx] ?? Infinity) < threshold);
1005
+ }
1006
+ // Build per-point metadata array for a band series in the tooltip.
1007
+ export function build_point_metadata(opts) {
1008
+ const { x_vals, y_vals, band_idx, spin, is_acoustic, bs, start_idx } = opts;
1009
+ return x_vals.map((_, pt_idx) => {
1010
+ const global_idx = start_idx + pt_idx;
1011
+ const qpoint = bs.qpoints[global_idx];
1012
+ return {
1013
+ band_idx,
1014
+ spin,
1015
+ is_acoustic,
1016
+ nb_bands: bs.nb_bands,
1017
+ frac_coords: qpoint?.frac_coords ?? null,
1018
+ qpoint_label: qpoint?.label ?? null,
1019
+ band_width: bs.band_widths?.[band_idx]?.[global_idx] ?? null,
1020
+ slope: compute_slope(x_vals, y_vals, pt_idx),
1021
+ };
1022
+ });
1023
+ }
@@ -25,6 +25,7 @@ export interface BaseBandStructure {
25
25
  distance: number[];
26
26
  nb_bands: number;
27
27
  bands: number[][];
28
+ spin_down_bands?: number[][];
28
29
  band_widths?: number[][];
29
30
  }
30
31
  export interface RibbonConfig {
@@ -62,6 +63,7 @@ export interface ElectronicDos {
62
63
  dos_at_e_fermi?: number;
63
64
  }
64
65
  export type SpinMode = `mirror` | `overlay` | `up_only` | `down_only` | null;
66
+ export type BandsSpinMode = Exclude<SpinMode, `mirror`>;
65
67
  export type PdosType = `atom` | `orbital`;
66
68
  export interface StackedAreaData {
67
69
  x_values: number[];
@@ -1,7 +1,7 @@
1
1
  import type { ChemicalElement, ElementCategory } from './element/types';
2
2
  import { DEFAULT_CATEGORY_COLORS, default_element_colors } from './colors';
3
3
  import type { Tooltip } from './plot';
4
- import type { ThemeMode, ThemeType } from './theme';
4
+ import { type ThemeMode, type ThemeType } from './theme';
5
5
  export declare const selected: {
6
6
  category: ElementCategory | null;
7
7
  element: ChemicalElement | null;
@@ -1,5 +1,6 @@
1
1
  import { AUTO_THEME, COLOR_THEMES, THEME_TYPE } from './theme/index';
2
2
  import { DEFAULT_CATEGORY_COLORS, default_element_colors } from './colors';
3
+ import { is_valid_theme_mode } from './theme';
3
4
  export const selected = $state({
4
5
  category: null,
5
6
  element: null,
@@ -22,8 +23,8 @@ let initial_system_mode = COLOR_THEMES.light;
22
23
  // Safe theme initialization for test environments
23
24
  try {
24
25
  if (typeof window !== `undefined` && globalThis.localStorage) {
25
- initial_theme_mode = localStorage.getItem(`matterviz-theme`) ||
26
- AUTO_THEME;
26
+ const saved_theme = localStorage.getItem(`matterviz-theme`) ?? ``;
27
+ initial_theme_mode = is_valid_theme_mode(saved_theme) ? saved_theme : AUTO_THEME;
27
28
  }
28
29
  else {
29
30
  initial_theme_mode = AUTO_THEME;
@@ -1,23 +1,62 @@
1
- <script lang="ts">import * as math from '../math';
2
- import { DEFAULTS } from '../settings';
3
- import { T } from '@threlte/core';
4
- import { Euler, Quaternion, Vector3 } from 'three';
5
- let { position, vector, scale = DEFAULTS.structure.force_scale, color = DEFAULTS.structure.force_color, shaft_radius = DEFAULTS.structure.force_shaft_radius, arrow_head_radius = DEFAULTS.structure.force_arrow_head_radius, arrow_head_length = DEFAULTS.structure.force_arrow_head_length, ...rest } = $props();
6
- const mag = $derived(Math.hypot(...vector));
7
- const dir = $derived(mag > math.EPS ? math.scale(vector, 1 / mag) : [0, 1, 0]);
8
- const vec_len = $derived(mag * scale);
9
- const head_len = $derived(arrow_head_length < 0 ? vec_len * -arrow_head_length : arrow_head_length);
10
- const shaft_len = $derived(Math.max(0, vec_len - head_len * 0.5));
11
- const shaft_r = $derived(shaft_radius < 0 ? shaft_len * -shaft_radius : shaft_radius);
12
- const head_r = $derived(arrow_head_radius < 0 ? shaft_len * -arrow_head_radius : arrow_head_radius);
13
- const shaft_pos = $derived(math.add(position, math.scale(dir, shaft_len * 0.5)));
14
- const head_pos = $derived(math.add(position, math.scale(dir, shaft_len + head_len * 0.5)));
15
- const rotation = $derived.by(() => {
16
- if (mag < math.EPS)
17
- return [0, 0, 0];
18
- const quat = new Quaternion().setFromUnitVectors(new Vector3(0, 1, 0), new Vector3(...dir));
19
- return new Euler().setFromQuaternion(quat).toArray().slice(0, 3);
20
- });
1
+ <script lang="ts">
2
+ import type { Vec3 } from '../math'
3
+ import * as math from '../math'
4
+ import { DEFAULTS } from '../settings'
5
+ import { T } from '@threlte/core'
6
+ import type { ComponentProps } from 'svelte'
7
+ import { Euler, Quaternion, Vector3 } from 'three'
8
+
9
+ let {
10
+ position,
11
+ vector,
12
+ scale = DEFAULTS.structure.vector_scale,
13
+ color = DEFAULTS.structure.vector_color,
14
+ shaft_radius = DEFAULTS.structure.vector_shaft_radius,
15
+ arrow_head_radius = DEFAULTS.structure.vector_arrow_head_radius,
16
+ arrow_head_length = DEFAULTS.structure.vector_arrow_head_length,
17
+ ...rest
18
+ }: ComponentProps<typeof T.Mesh> & {
19
+ position: Vec3
20
+ vector: Vec3
21
+ scale?: number
22
+ color?: string
23
+ shaft_radius?: number // negative = relative to length
24
+ arrow_head_radius?: number
25
+ arrow_head_length?: number
26
+ } = $props()
27
+
28
+ const mag = $derived(Math.hypot(...vector))
29
+ const dir = $derived(
30
+ mag > math.EPS ? math.scale(vector, 1 / mag) : ([0, 1, 0] as Vec3),
31
+ )
32
+ const vec_len = $derived(mag * scale)
33
+
34
+ const head_len = $derived(
35
+ arrow_head_length < 0 ? vec_len * -arrow_head_length : arrow_head_length,
36
+ )
37
+ const shaft_len = $derived(Math.max(0, vec_len - head_len * 0.5))
38
+ const shaft_r = $derived(
39
+ shaft_radius < 0 ? shaft_len * -shaft_radius : shaft_radius,
40
+ )
41
+ const head_r = $derived(
42
+ arrow_head_radius < 0 ? shaft_len * -arrow_head_radius : arrow_head_radius,
43
+ )
44
+
45
+ const shaft_pos = $derived(
46
+ math.add(position, math.scale(dir, shaft_len * 0.5)) as Vec3,
47
+ )
48
+ const head_pos = $derived(
49
+ math.add(position, math.scale(dir, shaft_len + head_len * 0.5)) as Vec3,
50
+ )
51
+
52
+ const rotation = $derived.by((): Vec3 => {
53
+ if (mag < math.EPS) return [0, 0, 0]
54
+ const quat = new Quaternion().setFromUnitVectors(
55
+ new Vector3(0, 1, 0),
56
+ new Vector3(...dir),
57
+ )
58
+ return new Euler().setFromQuaternion(quat).toArray().slice(0, 3) as Vec3
59
+ })
21
60
  </script>
22
61
 
23
62
  {#if shaft_len > 0.01}