matterviz 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +12 -14
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/app.css +53 -0
  6. package/dist/brillouin/BrillouinZone.svelte +75 -85
  7. package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
  8. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  9. package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
  10. package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
  11. package/dist/brillouin/BrillouinZoneScene.svelte +26 -39
  12. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  13. package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
  14. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +62 -74
  15. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
  16. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +511 -547
  17. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
  18. package/dist/chempot-diagram/async-compute.svelte.js +1 -1
  19. package/dist/chempot-diagram/controls-state.svelte.js +1 -1
  20. package/dist/colors/index.d.ts +0 -4
  21. package/dist/colors/index.js +19 -20
  22. package/dist/composition/BarChart.svelte +37 -31
  23. package/dist/composition/BubbleChart.svelte +17 -17
  24. package/dist/composition/Composition.svelte +7 -11
  25. package/dist/composition/Formula.svelte +18 -25
  26. package/dist/composition/FormulaFilter.svelte +92 -95
  27. package/dist/composition/PieChart.svelte +55 -41
  28. package/dist/composition/format.js +1 -1
  29. package/dist/composition/index.d.ts +2 -0
  30. package/dist/composition/index.js +14 -0
  31. package/dist/composition/parse.d.ts +2 -2
  32. package/dist/composition/parse.js +11 -10
  33. package/dist/constants.js +11 -9
  34. package/dist/convex-hull/ConvexHull.svelte +12 -15
  35. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  36. package/dist/convex-hull/ConvexHull2D.svelte +93 -92
  37. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  38. package/dist/convex-hull/ConvexHull3D.svelte +109 -140
  39. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  40. package/dist/convex-hull/ConvexHull4D.svelte +75 -94
  41. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  42. package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
  43. package/dist/convex-hull/ConvexHullControls.svelte +46 -48
  44. package/dist/convex-hull/ConvexHullStats.svelte +193 -195
  45. package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
  46. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  47. package/dist/convex-hull/StructurePopup.svelte +17 -21
  48. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  49. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  50. package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
  51. package/dist/convex-hull/helpers.d.ts +8 -10
  52. package/dist/convex-hull/helpers.js +36 -36
  53. package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
  54. package/dist/convex-hull/thermodynamics.js +18 -17
  55. package/dist/coordination/CoordinationBarPlot.svelte +38 -33
  56. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  57. package/dist/coordination/calc-coordination.d.ts +1 -1
  58. package/dist/coordination/calc-coordination.js +28 -25
  59. package/dist/element/BohrAtom.svelte +5 -8
  60. package/dist/element/ElementHeading.svelte +4 -1
  61. package/dist/element/ElementPhoto.svelte +11 -9
  62. package/dist/element/ElementStats.svelte +12 -10
  63. package/dist/element/ElementTile.svelte +24 -29
  64. package/dist/element/Nucleus.svelte +4 -2
  65. package/dist/element/data.d.ts +1 -2
  66. package/dist/element/helpers.d.ts +4 -0
  67. package/dist/element/helpers.js +18 -0
  68. package/dist/element/index.d.ts +1 -4
  69. package/dist/element/index.js +3 -18
  70. package/dist/feedback/DragOverlay.svelte +5 -5
  71. package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
  72. package/dist/feedback/StatusMessage.svelte +7 -4
  73. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  74. package/dist/fermi-surface/FermiSurface.svelte +14 -22
  75. package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -7
  76. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  77. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  78. package/dist/fermi-surface/FermiSurfaceScene.svelte +37 -64
  79. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  80. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  81. package/dist/fermi-surface/compute.js +3 -3
  82. package/dist/fermi-surface/parse.js +22 -24
  83. package/dist/heatmap-matrix/HeatmapMatrix.svelte +109 -148
  84. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
  85. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
  86. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
  87. package/dist/heatmap-matrix/index.d.ts +5 -0
  88. package/dist/icons.d.ts +4 -0
  89. package/dist/icons.js +4 -0
  90. package/dist/io/ExportPane.svelte +10 -6
  91. package/dist/io/decompress.d.ts +2 -1
  92. package/dist/io/decompress.js +22 -35
  93. package/dist/io/export.d.ts +4 -0
  94. package/dist/io/export.js +5 -1
  95. package/dist/io/fetch.d.ts +0 -3
  96. package/dist/io/fetch.js +0 -11
  97. package/dist/io/index.d.ts +0 -1
  98. package/dist/io/index.js +2 -9
  99. package/dist/io/is-binary.d.ts +9 -0
  100. package/dist/io/is-binary.js +45 -1
  101. package/dist/io/url-drop.js +13 -25
  102. package/dist/isosurface/Isosurface.svelte +17 -23
  103. package/dist/isosurface/IsosurfaceControls.svelte +37 -42
  104. package/dist/isosurface/parse-vaspwave.d.ts +3 -0
  105. package/dist/isosurface/parse-vaspwave.js +138 -0
  106. package/dist/isosurface/parse.js +6 -6
  107. package/dist/labels.d.ts +6 -2
  108. package/dist/labels.js +43 -13
  109. package/dist/layout/FullscreenButton.svelte +2 -1
  110. package/dist/layout/FullscreenToggle.svelte +10 -4
  111. package/dist/layout/InfoCard.svelte +7 -18
  112. package/dist/layout/InfoTag.svelte +1 -3
  113. package/dist/layout/NumberRangeInput.svelte +46 -0
  114. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  115. package/dist/layout/PropertyFilter.svelte +2 -6
  116. package/dist/layout/SettingsSection.svelte +21 -17
  117. package/dist/layout/SubpageGrid.svelte +3 -1
  118. package/dist/layout/ViewerChrome.svelte +9 -10
  119. package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
  120. package/dist/layout/fullscreen.js +3 -5
  121. package/dist/layout/fullscreen.svelte.js +1 -2
  122. package/dist/layout/index.d.ts +1 -0
  123. package/dist/layout/index.js +1 -0
  124. package/dist/layout/json-tree/JsonNode.svelte +8 -11
  125. package/dist/layout/json-tree/JsonTree.svelte +53 -77
  126. package/dist/layout/json-tree/JsonValue.svelte +7 -15
  127. package/dist/layout/json-tree/utils.js +14 -23
  128. package/dist/math.d.ts +2 -0
  129. package/dist/math.js +19 -0
  130. package/dist/overlays/ContextMenu.svelte +4 -2
  131. package/dist/overlays/CopyButton.svelte +11 -5
  132. package/dist/overlays/DragControlTab.svelte +6 -1
  133. package/dist/overlays/DraggablePane.svelte +81 -26
  134. package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
  135. package/dist/overlays/GlassChip.svelte +30 -0
  136. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  137. package/dist/overlays/InfoPaneCards.svelte +11 -23
  138. package/dist/overlays/index.d.ts +7 -0
  139. package/dist/overlays/index.js +26 -0
  140. package/dist/overlays/portal.d.ts +2 -0
  141. package/dist/overlays/portal.js +14 -0
  142. package/dist/periodic-table/PeriodicTable.svelte +113 -145
  143. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  144. package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
  145. package/dist/periodic-table/TableInset.svelte +9 -4
  146. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
  147. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  148. package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
  149. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  150. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
  151. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
  152. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  153. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  154. package/dist/phase-diagram/build-diagram.js +3 -3
  155. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  156. package/dist/phase-diagram/parse.js +15 -15
  157. package/dist/phase-diagram/svg-to-diagram.js +21 -15
  158. package/dist/phase-diagram/utils.js +2 -3
  159. package/dist/plot/bar/BarPlot.svelte +430 -391
  160. package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
  161. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  162. package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
  163. package/dist/plot/bar/SpacegroupBarPlot.svelte +29 -36
  164. package/dist/plot/bar/data.d.ts +5 -4
  165. package/dist/plot/bar/data.js +2 -1
  166. package/dist/plot/box/BoxPlot.svelte +301 -209
  167. package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
  168. package/dist/plot/box/Violin.svelte.d.ts +1 -0
  169. package/dist/plot/box/box-plot.js +1 -1
  170. package/dist/plot/core/auto-place.js +1 -1
  171. package/dist/plot/core/axis-utils.d.ts +12 -7
  172. package/dist/plot/core/axis-utils.js +48 -48
  173. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  174. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  175. package/dist/plot/core/components/ColorBar.svelte +101 -106
  176. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  177. package/dist/plot/core/components/FillArea.svelte +10 -17
  178. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  179. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  180. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  181. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  182. package/dist/plot/core/components/Line.svelte +18 -9
  183. package/dist/plot/core/components/Line.svelte.d.ts +2 -0
  184. package/dist/plot/core/components/PlotAxis.svelte +40 -17
  185. package/dist/plot/core/components/PlotControls.svelte +65 -41
  186. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  187. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  188. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  189. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  190. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  191. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  192. package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
  193. package/dist/plot/core/components/ReferencePlane.svelte +7 -8
  194. package/dist/plot/core/components/ZeroLines.svelte +4 -8
  195. package/dist/plot/core/components/ZoomRect.svelte +1 -2
  196. package/dist/plot/core/components/index.d.ts +1 -0
  197. package/dist/plot/core/components/index.js +1 -0
  198. package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
  199. package/dist/plot/core/data-cleaning-signal.js +467 -0
  200. package/dist/plot/core/data-cleaning.d.ts +2 -42
  201. package/dist/plot/core/data-cleaning.js +27 -474
  202. package/dist/plot/core/data-transform.js +9 -5
  203. package/dist/plot/core/fill-utils.d.ts +3 -1
  204. package/dist/plot/core/fill-utils.js +28 -6
  205. package/dist/plot/core/index.d.ts +1 -0
  206. package/dist/plot/core/index.js +1 -0
  207. package/dist/plot/core/interactions.js +0 -2
  208. package/dist/plot/core/layout.d.ts +3 -1
  209. package/dist/plot/core/layout.js +22 -13
  210. package/dist/plot/core/marginals.d.ts +170 -0
  211. package/dist/plot/core/marginals.js +436 -0
  212. package/dist/plot/core/reference-line.js +1 -1
  213. package/dist/plot/core/scales.d.ts +23 -0
  214. package/dist/plot/core/scales.js +39 -13
  215. package/dist/plot/core/types/fills.d.ts +101 -0
  216. package/dist/plot/core/types/fills.js +15 -0
  217. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  218. package/dist/plot/core/types/plot-3d.js +4 -0
  219. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  220. package/dist/plot/core/types/reference-lines.js +9 -0
  221. package/dist/plot/core/types.d.ts +29 -324
  222. package/dist/plot/core/types.js +23 -20
  223. package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
  224. package/dist/plot/core/utils/hierarchy-chart.js +179 -0
  225. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  226. package/dist/plot/core/utils/hierarchy-labels.js +99 -0
  227. package/dist/plot/core/utils/label-placement.js +2 -2
  228. package/dist/plot/histogram/Histogram.svelte +304 -325
  229. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  230. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  231. package/dist/plot/histogram/histogram.d.ts +31 -0
  232. package/dist/plot/histogram/histogram.js +70 -0
  233. package/dist/plot/histogram/index.d.ts +1 -0
  234. package/dist/plot/histogram/index.js +1 -0
  235. package/dist/plot/index.d.ts +1 -0
  236. package/dist/plot/index.js +1 -0
  237. package/dist/plot/sankey/Sankey.svelte +78 -69
  238. package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
  239. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  240. package/dist/plot/scatter/BinnedScatterPlot.svelte +263 -109
  241. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
  242. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  243. package/dist/plot/scatter/ScatterPlot.svelte +477 -385
  244. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
  245. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  246. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  247. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  248. package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
  249. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  250. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  251. package/dist/plot/scatter/scatter-data.js +8 -7
  252. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
  253. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
  254. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
  255. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
  256. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
  257. package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
  258. package/dist/plot/sunburst/Sunburst.svelte +251 -329
  259. package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
  260. package/dist/plot/sunburst/index.d.ts +1 -1
  261. package/dist/plot/sunburst/index.js +2 -1
  262. package/dist/plot/sunburst/render.d.ts +2 -2
  263. package/dist/plot/sunburst/render.js +47 -22
  264. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  265. package/dist/plot/sunburst/sunburst.js +10 -3
  266. package/dist/plot/treemap/Treemap.svelte +907 -0
  267. package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
  268. package/dist/plot/treemap/index.d.ts +3 -0
  269. package/dist/plot/treemap/index.js +4 -0
  270. package/dist/plot/treemap/treemap.d.ts +26 -0
  271. package/dist/plot/treemap/treemap.js +99 -0
  272. package/dist/rdf/RdfPlot.svelte +22 -26
  273. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  274. package/dist/rdf/calc-rdf.js +4 -8
  275. package/dist/sanitize.js +1 -1
  276. package/dist/scene/bind-renderer.svelte.js +14 -6
  277. package/dist/settings.d.ts +19 -9
  278. package/dist/settings.js +77 -50
  279. package/dist/spectral/Bands.svelte +223 -230
  280. package/dist/spectral/BandsAndDos.svelte +11 -9
  281. package/dist/spectral/BrillouinBandsDos.svelte +19 -27
  282. package/dist/spectral/Dos.svelte +70 -73
  283. package/dist/spectral/helpers.d.ts +3 -3
  284. package/dist/spectral/helpers.js +25 -35
  285. package/dist/state.svelte.js +5 -18
  286. package/dist/structure/Arrow.svelte +5 -18
  287. package/dist/structure/ArrowInstances.svelte +160 -0
  288. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  289. package/dist/structure/AtomLegend.svelte +115 -75
  290. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  291. package/dist/structure/Bond.svelte +31 -23
  292. package/dist/structure/CanvasTooltip.svelte +15 -3
  293. package/dist/structure/CellSelect.svelte +11 -26
  294. package/dist/structure/Cylinder.svelte +24 -40
  295. package/dist/structure/InstancedAtoms.svelte +114 -0
  296. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  297. package/dist/structure/Lattice.svelte +85 -149
  298. package/dist/structure/SiteLabels.svelte +122 -0
  299. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  300. package/dist/structure/Structure.svelte +473 -419
  301. package/dist/structure/Structure.svelte.d.ts +4 -2
  302. package/dist/structure/StructureCarousel.svelte +630 -0
  303. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  304. package/dist/structure/StructureControls.svelte +157 -399
  305. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  306. package/dist/structure/StructureExportPane.svelte +17 -21
  307. package/dist/structure/StructureInfoPane.svelte +72 -66
  308. package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
  309. package/dist/structure/StructureScene.svelte +467 -476
  310. package/dist/structure/StructureScene.svelte.d.ts +3 -1
  311. package/dist/structure/StructureViewport.svelte +386 -0
  312. package/dist/structure/StructureViewport.svelte.d.ts +63 -0
  313. package/dist/structure/atom-label-placement.d.ts +16 -12
  314. package/dist/structure/atom-label-placement.js +70 -37
  315. package/dist/structure/atom-properties.d.ts +2 -0
  316. package/dist/structure/atom-properties.js +104 -38
  317. package/dist/structure/bonding.d.ts +10 -3
  318. package/dist/structure/bonding.js +84 -28
  319. package/dist/structure/edit-history.d.ts +6 -0
  320. package/dist/structure/edit-history.js +27 -0
  321. package/dist/structure/export.d.ts +1 -0
  322. package/dist/structure/export.js +39 -31
  323. package/dist/structure/format-detect.d.ts +1 -0
  324. package/dist/structure/format-detect.js +22 -0
  325. package/dist/structure/geometry.d.ts +9 -0
  326. package/dist/structure/geometry.js +27 -0
  327. package/dist/structure/index.d.ts +16 -1
  328. package/dist/structure/index.js +13 -2
  329. package/dist/structure/measure.d.ts +1 -1
  330. package/dist/structure/measure.js +6 -12
  331. package/dist/structure/parse.d.ts +2 -1
  332. package/dist/structure/parse.js +243 -222
  333. package/dist/structure/partial-occupancy.js +4 -2
  334. package/dist/structure/pbc.js +78 -98
  335. package/dist/structure/polyhedra.d.ts +0 -1
  336. package/dist/structure/polyhedra.js +3 -18
  337. package/dist/structure/supercell.d.ts +1 -2
  338. package/dist/structure/supercell.js +7 -13
  339. package/dist/symmetry/SymmetryElements.svelte +11 -15
  340. package/dist/symmetry/SymmetryStats.svelte +56 -68
  341. package/dist/symmetry/WyckoffTable.svelte +5 -24
  342. package/dist/symmetry/cell-transform.js +1 -0
  343. package/dist/symmetry/index.d.ts +1 -0
  344. package/dist/symmetry/index.js +8 -2
  345. package/dist/symmetry/spacegroups.js +3 -2
  346. package/dist/table/HeatmapTable.svelte +1102 -365
  347. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  348. package/dist/table/ToggleMenu.svelte +5 -12
  349. package/dist/table/index.d.ts +21 -6
  350. package/dist/table/index.js +34 -21
  351. package/dist/theme/ThemeControl.svelte +16 -8
  352. package/dist/theme/index.d.ts +1 -5
  353. package/dist/theme/index.js +4 -10
  354. package/dist/theme/themes.mjs +14 -7
  355. package/dist/tooltip/KCoords.svelte +4 -1
  356. package/dist/tooltip/TooltipContent.svelte +2 -5
  357. package/dist/trajectory/Trajectory.svelte +515 -308
  358. package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
  359. package/dist/trajectory/TrajectoryError.svelte +11 -8
  360. package/dist/trajectory/TrajectoryExportPane.svelte +14 -31
  361. package/dist/trajectory/TrajectoryInfoPane.svelte +85 -97
  362. package/dist/trajectory/extract.js +56 -34
  363. package/dist/trajectory/format-detect.js +11 -9
  364. package/dist/trajectory/frame-reader.d.ts +2 -0
  365. package/dist/trajectory/frame-reader.js +33 -29
  366. package/dist/trajectory/helpers.d.ts +2 -0
  367. package/dist/trajectory/helpers.js +18 -7
  368. package/dist/trajectory/index.d.ts +1 -0
  369. package/dist/trajectory/index.js +3 -0
  370. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  371. package/dist/trajectory/parse/h5-utils.js +109 -0
  372. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  373. package/dist/trajectory/parse/hdf5.js +116 -106
  374. package/dist/trajectory/parse/index.d.ts +2 -3
  375. package/dist/trajectory/parse/index.js +17 -20
  376. package/dist/trajectory/parse/lammps.js +8 -12
  377. package/dist/trajectory/parse/vasp.js +10 -7
  378. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  379. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  380. package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
  381. package/dist/trajectory/parse/vaspout-h5.js +284 -0
  382. package/dist/trajectory/parse/xyz.js +11 -7
  383. package/dist/trajectory/plotting.d.ts +8 -9
  384. package/dist/trajectory/plotting.js +99 -27
  385. package/dist/utils.d.ts +3 -0
  386. package/dist/utils.js +7 -0
  387. package/dist/xrd/XrdPlot.svelte +47 -61
  388. package/dist/xrd/broadening.js +2 -1
  389. package/dist/xrd/calc-xrd.js +2 -4
  390. package/dist/xrd/parse.d.ts +0 -1
  391. package/dist/xrd/parse.js +56 -73
  392. package/package.json +61 -33
  393. package/dist/api/mp.d.ts +0 -6
  394. package/dist/api/mp.js +0 -22
  395. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
@@ -0,0 +1,138 @@
1
+ // Parser for VASP vaspwave.h5 charge density: charge/charge on charge/grid
2
+ // plus the embedded structure under structure/positions (dataset paths follow
3
+ // ferrox's VASPWAVE_* constants / py4vasp's VASP 6.x schema). Full files are
4
+ // hundreds of MB, so embedding hosts are expected to prune them server-side
5
+ // first; this parser sees only charge/{charge,grid} + structure/positions.
6
+ //
7
+ // Prototype scope: charge (+ magnetization) isosurfaces only — wavefunctions
8
+ // are out of scope. The "charge density RMS per SCF step" convergence signal
9
+ // is already covered by OSZICAR's rms(c) column in the vaspout.h5 parser
10
+ // (scf_charge_rms frame metadata); diffing charge grids between live reloads
11
+ // is explicitly out of scope here.
12
+ import { calc_lattice_params, create_frac_to_cart } from '../math';
13
+ import { wrap_to_unit_cell } from '../structure/pbc';
14
+ import { make_site } from '../structure/site';
15
+ import { validate_3x3_matrix } from '../trajectory/helpers';
16
+ import { expand_ion_types, is_hdf5_dataset, read_dataset, scale_matrix, to_number_array, to_scalar_number, to_string_array, with_h5_file, } from '../trajectory/parse/h5-utils';
17
+ import { grid_data_range } from './types';
18
+ const CHARGE_PATH = `charge/charge`;
19
+ const CHARGE_GRID_PATH = `charge/grid`;
20
+ const STRUCTURE_PREFIX = `structure/positions`;
21
+ // vaspwave carries charge density/wavefunctions, never a trajectory — used by
22
+ // file-open routing to divert from the HDF5 trajectory dispatcher.
23
+ export const is_vaspwave_filename = (filename) => {
24
+ const basename = filename.split(`/`).pop() ?? filename;
25
+ return /vaspwave.*\.(?:h5|hdf5)$/i.test(basename);
26
+ };
27
+ const dataset_shape = (h5_file, path) => {
28
+ const entity = h5_file.get(path);
29
+ return is_hdf5_dataset(entity) ? (entity.shape ?? null) : null;
30
+ };
31
+ const read_embedded_structure = (h5_file) => {
32
+ const lattice_data = read_dataset(h5_file, `${STRUCTURE_PREFIX}/lattice_vectors`);
33
+ if (!lattice_data) {
34
+ throw new Error(`vaspwave.h5 has no embedded structure (${STRUCTURE_PREFIX}/lattice_vectors) — ` +
35
+ `cannot place the charge grid in a lattice`);
36
+ }
37
+ const scale = to_scalar_number(read_dataset(h5_file, `${STRUCTURE_PREFIX}/scale`)) ?? 1;
38
+ const lattice = scale_matrix(validate_3x3_matrix(lattice_data), scale);
39
+ // Sites are optional for rendering (the isosurface needs only the lattice),
40
+ // so a pruned/torn file missing ion data still opens with an empty cell.
41
+ const sites = [];
42
+ const ion_types = to_string_array(read_dataset(h5_file, `${STRUCTURE_PREFIX}/ion_types`));
43
+ const ion_counts = to_number_array(read_dataset(h5_file, `${STRUCTURE_PREFIX}/number_ion_types`));
44
+ const frac_positions = read_dataset(h5_file, `${STRUCTURE_PREFIX}/position_ions`);
45
+ if (ion_types && ion_counts && frac_positions && ion_types.length === ion_counts.length) {
46
+ const elements = expand_ion_types(ion_types, ion_counts);
47
+ const frac_to_cart = create_frac_to_cart(lattice);
48
+ for (const [site_idx, element] of elements.entries()) {
49
+ const frac = frac_positions[site_idx];
50
+ if (!Array.isArray(frac) || frac.length < 3)
51
+ break; // torn positions: keep what parsed
52
+ const abc = wrap_to_unit_cell(frac.slice(0, 3));
53
+ sites.push(make_site(element, abc, frac_to_cart(abc), `${element}${site_idx + 1}`));
54
+ }
55
+ }
56
+ return {
57
+ sites,
58
+ lattice: { matrix: lattice, pbc: [true, true, true], ...calc_lattice_params(lattice) },
59
+ };
60
+ };
61
+ // VASP writes volumetric data C-order [components, nz, ny, nx]; the grid
62
+ // dataset [nx, ny, nz] disambiguates (same logic as ferrox's
63
+ // volumetric_grid_shape_and_order — when nx == nz both layouts match, so
64
+ // default to the canonical zyx order).
65
+ const charge_axis_order = (spatial_shape, grid_dims) => {
66
+ const [nx, ny, nz] = grid_dims;
67
+ const matches = (dims) => dims.every((dim, idx) => dim === spatial_shape[idx]);
68
+ if (matches([nz, ny, nx]))
69
+ return `zyx`;
70
+ if (matches([nx, ny, nz]))
71
+ return `xyz`;
72
+ throw new Error(`vaspwave.h5 ${CHARGE_GRID_PATH} [${grid_dims}] is incompatible with ` +
73
+ `${CHARGE_PATH} spatial shape [${spatial_shape}]`);
74
+ };
75
+ function parse_vaspwave_charge_file(h5_file) {
76
+ const shape = dataset_shape(h5_file, CHARGE_PATH);
77
+ if (!shape) {
78
+ throw new Error(`vaspwave.h5 file has no charge density (missing ${CHARGE_PATH})`);
79
+ }
80
+ // Only the dimension count is checked here — the spatial axis order (zyx vs
81
+ // xyz) is disambiguated later by charge_axis_order against CHARGE_GRID_PATH.
82
+ if (shape.length !== 4) {
83
+ throw new Error(`${CHARGE_PATH} must have 4 dimensions, got [${shape}]`);
84
+ }
85
+ const n_components = shape[0];
86
+ if (n_components < 1 || n_components > 2) {
87
+ throw new Error(`${CHARGE_PATH} has unsupported component count ${n_components}; expected 1 ` +
88
+ `(non-spin-polarized) or 2 (total + magnetization)`);
89
+ }
90
+ const grid_dims = to_number_array(read_dataset(h5_file, CHARGE_GRID_PATH));
91
+ if (grid_dims?.length !== 3) {
92
+ throw new Error(`vaspwave.h5 is missing ${CHARGE_GRID_PATH}; cannot determine the axis order of ${CHARGE_PATH}`);
93
+ }
94
+ const axis_order = charge_axis_order(shape.slice(1), grid_dims);
95
+ const [nx, ny, nz] = grid_dims;
96
+ const structure = read_embedded_structure(h5_file);
97
+ const lattice = structure.lattice.matrix;
98
+ const charge_data = read_dataset(h5_file, CHARGE_PATH);
99
+ if (!charge_data)
100
+ throw new Error(`Failed to read ${CHARGE_PATH} data`);
101
+ // Metadata shape and decoded data can disagree in torn/corrupt files — fail
102
+ // loudly instead of silently rendering fewer components than the file claims
103
+ if (charge_data.length !== n_components) {
104
+ throw new Error(`${CHARGE_PATH} decoded ${charge_data.length} components but its shape claims ${n_components}`);
105
+ }
106
+ const component_labels = [`charge density`, `magnetization density`];
107
+ const volumes = charge_data.map((component, component_idx) => {
108
+ const grid = Array(nx);
109
+ for (let x_idx = 0; x_idx < nx; x_idx++) {
110
+ const plane = Array(ny);
111
+ for (let y_idx = 0; y_idx < ny; y_idx++) {
112
+ const row = Array(nz);
113
+ for (let z_idx = 0; z_idx < nz; z_idx++) {
114
+ row[z_idx] =
115
+ axis_order === `zyx`
116
+ ? component[z_idx][y_idx][x_idx]
117
+ : component[x_idx][y_idx][z_idx];
118
+ }
119
+ plane[y_idx] = row;
120
+ }
121
+ grid[x_idx] = plane;
122
+ }
123
+ return {
124
+ grid,
125
+ grid_dims: [nx, ny, nz],
126
+ lattice,
127
+ origin: [0, 0, 0],
128
+ data_range: grid_data_range(grid),
129
+ data_order: `x_fastest`,
130
+ periodic: true,
131
+ label: component_labels[component_idx],
132
+ };
133
+ });
134
+ return { structure, volumes };
135
+ }
136
+ export async function parse_vaspwave_charge(buffer, filename) {
137
+ return with_h5_file(buffer, filename, parse_vaspwave_charge_file);
138
+ }
@@ -1,11 +1,12 @@
1
1
  // Parsers for volumetric data file formats (VASP CHGCAR, Gaussian .cube)
2
2
  import { ATOMIC_NUMBER_TO_SYMBOL } from '../composition/parse';
3
3
  import { VASP_VOLUMETRIC_REGEX } from '../constants';
4
- import { coerce_elem_symbol, FALLBACK_ELEMENTS } from '../element';
5
- import { strip_compression_extensions } from '../io';
4
+ import { coerce_elem_symbol, FALLBACK_ELEMENTS } from '../element/helpers';
5
+ import { strip_compression_extensions } from '../io/decompress';
6
6
  import * as math from '../math';
7
7
  import { wrap_to_unit_cell } from '../structure/pbc';
8
8
  import { make_site } from '../structure/site';
9
+ import { parse_leading_num } from '../utils';
9
10
  // Bohr radius in Angstroms (for Gaussian .cube unit conversion)
10
11
  const BOHR_TO_ANGSTROM = 0.529177249;
11
12
  // === Parse error contract ===
@@ -188,7 +189,7 @@ export function parse_chgcar(content) {
188
189
  pos = cur.next;
189
190
  // Line 1: scale factor
190
191
  cur = read_line(content, pos);
191
- const scale_factor = parseFloat(cur.line);
192
+ const scale_factor = parse_leading_num(cur.line);
192
193
  if (isNaN(scale_factor)) {
193
194
  vol_error(`Invalid scaling factor in CHGCAR`);
194
195
  return null;
@@ -212,8 +213,7 @@ export function parse_chgcar(content) {
212
213
  return null;
213
214
  }
214
215
  // Detect VASP 5+ format (has element symbols before counts)
215
- const first_token = cur.line.trim().split(/\s+/)[0];
216
- const has_element_symbols = isNaN(parseInt(first_token, 10));
216
+ const has_element_symbols = isNaN(parse_leading_num(cur.line));
217
217
  if (has_element_symbols) {
218
218
  element_symbols = cur.line.trim().split(/\s+/);
219
219
  pos = cur.next;
@@ -536,7 +536,7 @@ export function parse_volumetric_file(content, filename) {
536
536
  // CHGCAR detection: requires POSCAR-like header (scale factor on line 2) AND
537
537
  // a grid dimensions line (3 integers) somewhere after the header. This distinguishes
538
538
  // CHGCAR from plain POSCAR/CONTCAR files which share the same header format.
539
- if (lines.length > 2 && !isNaN(parseFloat(lines[1].trim()))) {
539
+ if (lines.length > 2 && !isNaN(parse_leading_num(lines[1]))) {
540
540
  // Scan for grid dimensions line (3 integers) starting from ~line 7
541
541
  let scan_pos = find_line_offset(content, 7);
542
542
  // Only scan a limited window, not the entire file
package/dist/labels.d.ts CHANGED
@@ -12,6 +12,7 @@ export declare const ELEM_HEATMAP_KEYS: (keyof ChemicalElement)[];
12
12
  export declare const ELEM_HEATMAP_LABELS: Partial<Record<string, keyof ChemicalElement>>;
13
13
  export declare const DEFAULT_FMT: [string, string];
14
14
  export declare const FRACTION_GLYPHS: readonly (readonly [number, string])[];
15
+ export declare const format_value_or_num: (value: number, fmt?: string) => string;
15
16
  export declare const format_num: (num: number, fmt?: string | number) => string;
16
17
  export declare const format_vec3: (vec: Readonly<Vec3>, fmt_spec?: string) => string;
17
18
  export declare const format_bytes: (bytes?: number) => string;
@@ -47,7 +48,10 @@ export declare const SUBSCRIPT_MAP: {
47
48
  readonly '9': "₉";
48
49
  };
49
50
  export declare const superscript_digits: (input: string) => string;
50
- export declare const trajectory_property_config: Record<string, {
51
+ export declare const SCF_AXIS_GROUP = "eV (SCF)";
52
+ export interface TrajPropertyConfig {
51
53
  label: string;
52
54
  unit: string;
53
- }>;
55
+ axis_group?: string;
56
+ }
57
+ export declare const trajectory_property_config: Record<string, TrajPropertyConfig>;
package/dist/labels.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { normalize_unicode_minus } from './utils';
1
2
  import { format } from 'd3-format';
2
3
  import * as d3_symbols from 'd3-shape';
3
4
  import { timeFormat } from 'd3-time-format';
@@ -33,12 +34,11 @@ export function format_value(value, formatter) {
33
34
  return `Infinity`;
34
35
  if (Number.isNaN(value))
35
36
  return `NaN`;
36
- // Format and normalize unicode minus
37
- const formatted = format(formatter)(value).replaceAll('−', `-`);
37
+ const formatted = normalize_unicode_minus(format(formatter)(value));
38
38
  // Handle percentage formatting - remove trailing zeros
39
39
  if (formatter.includes(`%`)) {
40
40
  return formatted.includes(`.`)
41
- ? formatted.replace(/(\.\d*?)0+%$/, `$1%`).replace(/\.%$/, `%`)
41
+ ? formatted.replace(/(?<decimals>\.\d*?)0+%$/, `$1%`).replace(/\.%$/, `%`)
42
42
  : formatted;
43
43
  }
44
44
  // Handle currency formatting - preserve precision if specified
@@ -47,26 +47,44 @@ export function format_value(value, formatter) {
47
47
  }
48
48
  // Remove trailing zeros after decimal point
49
49
  const out = formatted.includes(`.`)
50
- ? formatted.replace(/(\.\d*?)0+$/, `$1`).replace(/\.$/, ``)
50
+ ? formatted.replace(/(?<decimals>\.\d*?)0+$/, `$1`).replace(/\.$/, ``)
51
51
  : formatted;
52
52
  return out === `-0` ? `0` : out;
53
53
  }
54
- // TODO add labels and units for all elemental properties
54
+ // Human-readable label + unit (null when dimensionless) for displayable element
55
+ // properties. Omitted: Record-valued (ionic_radii, shannon_radii), assets
56
+ // (cpk-hex, spectral_img), heading/summary fields (name, symbol, category,
57
+ // discoverer, year, summary) and electronegativity_pauling (identical to
58
+ // electronegativity).
55
59
  export const ELEM_PROPERTY_LABELS = {
60
+ appearance: [`Appearance`, null],
56
61
  atomic_mass: [`Atomic Mass`, `u`],
57
62
  atomic_radius: [`Atomic Radius`, `Å`],
58
63
  boiling_point: [`Boiling Point`, `K`],
64
+ column: [`Group`, null],
65
+ common_oxidation_states: [`Common Oxidation States`, null],
59
66
  covalent_radius: [`Covalent Radius`, `Å`],
60
67
  density: [`Density`, `g/cm³`],
61
- electron_affinity: [`Electron Affinity`, null],
68
+ electron_affinity: [`Electron Affinity`, `kJ/mol`],
69
+ electron_configuration: [`Electron Configuration`, null],
70
+ electron_configuration_semantic: [`Electron Configuration (semantic)`, null],
62
71
  electronegativity: [`Electronegativity`, null],
72
+ electrons: [`Electrons`, null],
63
73
  first_ionization: [`First Ionization Energy`, `eV`],
74
+ icsd_oxidation_states: [`ICSD Oxidation States`, null],
75
+ ionization_energies: [`Ionization Energies`, `kJ/mol`],
64
76
  melting_point: [`Melting Point`, `K`],
65
77
  mendeleev_number: [`Mendeleev Number`, null],
66
- // molar_heat: [`Molar Heat`, `J/(mol·K)`],
78
+ molar_heat: [`Molar Heat`, `J/(mol·K)`],
67
79
  n_shells: [`Number of Shells`, null],
68
80
  n_valence: [`Electron Valency`, null],
81
+ neutrons: [`Neutrons`, null],
69
82
  number: [`Atomic Number`, null],
83
+ number_of_isotopes: [`Number of Isotopes`, null],
84
+ oxidation_states: [`Oxidation States`, null],
85
+ period: [`Period`, null],
86
+ phase: [`Phase`, null],
87
+ protons: [`Protons`, null],
70
88
  shells: [`Electron Shell Occupations`, null],
71
89
  specific_heat: [`Specific Heat`, `J/(g K)`],
72
90
  };
@@ -108,6 +126,10 @@ export const FRACTION_GLYPHS = [
108
126
  [7 / 8, `⁷⁄₈`],
109
127
  [11 / 12, `¹¹⁄₁₂`],
110
128
  ];
129
+ // format_value when an explicit format is given, else format_num's adaptive
130
+ // default: SI prefixes for |value| >= 1 (4500 -> 4.5k) but plain decimals
131
+ // below 1 (0.2 stays 0.2, never the SI milli form "200m")
132
+ export const format_value_or_num = (value, fmt) => fmt ? format_value(value, fmt) : format_num(value);
111
133
  // fmt as number only allowed to support [].map(format_num) without type error
112
134
  export const format_num = (num, fmt) => {
113
135
  if (num === null)
@@ -157,10 +179,10 @@ export function parse_si_float(value) {
157
179
  if (typeof value !== `string`)
158
180
  return value;
159
181
  // Remove whitespace and commas
160
- const cleaned = value.trim().replaceAll(/(\d),(\d)/g, `$1$2`);
182
+ const cleaned = value.trim().replaceAll(/(?<before>\d),(?<after>\d)/g, `$1$2`);
161
183
  // SI-formatted number (e.g. "1.23k", "789µ"). Suffixes are case-sensitive (m=milli vs
162
184
  // M=mega), so no `i` flag: mismatched-case suffixes return the string as-is.
163
- const match = /^([-+]?\d*\.?\d+)\s*([yzafpnµmkMGTPEZY])?$/.exec(cleaned);
185
+ const match = /^(?<num_part>[-+]?\d*\.?\d+)\s*(?<suffix>[yzafpnµmkMGTPEZY])?$/.exec(cleaned);
164
186
  if (match) {
165
187
  const [, num_part, suffix] = match;
166
188
  let multiplier = 1;
@@ -171,11 +193,12 @@ export function parse_si_float(value) {
171
193
  multiplier = 1000 ** (index - 8);
172
194
  }
173
195
  }
174
- return parseFloat(num_part) * multiplier;
196
+ return Number(num_part) * multiplier;
175
197
  }
176
- // If it's a number without SI suffix, try parsing it
198
+ // If it's a number without SI suffix, try parsing it (dropping stray commas
199
+ // not already stripped above, e.g. trailing ones)
177
200
  if (/^[-+]?[\d,]+\.?\d*$/.test(cleaned))
178
- return parseFloat(cleaned);
201
+ return Number(cleaned.replaceAll(`,`, ``));
179
202
  // If the value is not a formatted number, return as is
180
203
  return value;
181
204
  }
@@ -234,7 +257,9 @@ export const SUBSCRIPT_MAP = {
234
257
  };
235
258
  // replaces all signs and digits with their unicode superscript equivalent
236
259
  export const superscript_digits = (input) => input.replaceAll(/[\d+-]/g, (match) => is_superscript_key(match) ? SUPERSCRIPT_MAP[match] : match);
237
- // Trajectory property configuration: clean labels and units as structured data
260
+ // Axis-group key for SCF convergence series: shared between the property config
261
+ // below and the log-scale detection in trajectory/plotting.ts so the two can't drift
262
+ export const SCF_AXIS_GROUP = `eV (SCF)`;
238
263
  export const trajectory_property_config = {
239
264
  // Energy properties
240
265
  energy: { label: `Energy`, unit: `eV` },
@@ -275,4 +300,9 @@ export const trajectory_property_config = {
275
300
  Pressure: { label: `Pressure`, unit: `GPa` },
276
301
  stress_max: { label: `σ<sub>max</sub>`, unit: `GPa` },
277
302
  stress_frobenius: { label: `σ<sub>F</sub>`, unit: `GPa` },
303
+ // SCF/electronic convergence properties (e.g. from VASP vaspout.h5 OSZICAR data)
304
+ n_scf_steps: { label: `SCF steps`, unit: `steps` },
305
+ scf_energy_delta: { label: `|ΔE<sub>SCF</sub>|`, unit: `eV`, axis_group: SCF_AXIS_GROUP },
306
+ scf_rms: { label: `ρ residual (rms)`, unit: `a.u.` },
307
+ scf_charge_rms: { label: `ρ<sub>c</sub> residual (rms(c))`, unit: `a.u.` },
278
308
  };
@@ -21,9 +21,10 @@
21
21
  type="button"
22
22
  onclick={() => toggle_fullscreen(wrapper)}
23
23
  title="{fullscreen ? `Exit` : `Enter`} fullscreen"
24
+ aria-label="{fullscreen ? `Exit` : `Enter`} fullscreen"
24
25
  aria-pressed={fullscreen}
25
26
  {...rest}
26
- class="fullscreen-btn {rest.class ?? ``}"
27
+ class={[`fullscreen-btn`, rest.class]}
27
28
  >
28
29
  {#if typeof toggle === `function`}
29
30
  {@render toggle({ fullscreen })}
@@ -4,14 +4,17 @@
4
4
  import Icon from '../Icon.svelte'
5
5
  import type { HTMLButtonAttributes } from 'svelte/elements'
6
6
 
7
- let { fullscreen = $bindable(false), ...rest }: HTMLButtonAttributes & {
7
+ let {
8
+ fullscreen = $bindable(false),
9
+ ...rest
10
+ }: HTMLButtonAttributes & {
8
11
  fullscreen?: boolean
9
12
  } = $props()
10
13
  </script>
11
14
 
12
15
  <button
13
16
  {...rest}
14
- class="fullscreen-toggle {rest.class ?? ``}"
17
+ class={[`fullscreen-toggle`, rest.class]}
15
18
  onclick={() => (fullscreen = !fullscreen)}
16
19
  aria-label={fullscreen ? `Exit fullscreen` : `Enter fullscreen`}
17
20
  type="button"
@@ -33,9 +36,12 @@
33
36
  background-color: transparent;
34
37
  cursor: pointer;
35
38
  opacity: 0;
36
- transition: opacity 0.2s, background-color 0.2s;
39
+ transition:
40
+ opacity 0.2s,
41
+ background-color 0.2s;
37
42
  }
38
- .fullscreen-toggle:hover, .fullscreen-toggle:focus {
43
+ .fullscreen-toggle:hover,
44
+ .fullscreen-toggle:focus {
39
45
  background-color: color-mix(in srgb, currentColor 8%, transparent);
40
46
  opacity: var(--fullscreen-btn-hover-opacity, 1);
41
47
  }
@@ -4,8 +4,9 @@
4
4
  import type { Snippet } from 'svelte'
5
5
  import type { HTMLAttributes } from 'svelte/elements'
6
6
 
7
- interface Props<T extends keyof HTMLElementTagNameMap = `section`>
8
- extends HTMLAttributes<HTMLElementTagNameMap[T]> {
7
+ interface Props<T extends keyof HTMLElementTagNameMap = `section`> extends HTMLAttributes<
8
+ HTMLElementTagNameMap[T]
9
+ > {
9
10
  data?: {
10
11
  title: string
11
12
  value?: string | number | number[] | null
@@ -35,7 +36,7 @@
35
36
  let default_fmt = $derived(fmt) // rename fmt to default_fmt for internal use
36
37
  </script>
37
38
 
38
- <svelte:element this={as} {...rest} class="info-card {rest.class ?? ``}">
39
+ <svelte:element this={as} {...rest} class={[`info-card`, rest.class]}>
39
40
  {#if title || title_snippet}
40
41
  <h2>
41
42
  {#if title_snippet}{@render title_snippet()}{:else}
@@ -43,13 +44,7 @@
43
44
  {/if}
44
45
  </h2>
45
46
  {/if}
46
- {#each data.filter((itm) =>
47
- (!(`condition` in itm) || itm?.condition) && itm.value !== undefined &&
48
- itm.value !== null
49
- ) as
50
- { title, value, unit, fmt = default_fmt, tooltip }
51
- (title + value + unit + fmt)
52
- }
47
+ {#each data.filter((itm) => (!(`condition` in itm) || itm?.condition) && itm.value !== undefined && itm.value !== null) as { title, value, unit, fmt = default_fmt, tooltip } (title + value + unit + fmt)}
53
48
  <div>
54
49
  <span class="title" {title}>
55
50
  {@html sanitize_html(title)}
@@ -77,10 +72,7 @@
77
72
  padding: var(--ic-padding, 10pt 12pt);
78
73
  margin: var(--ic-margin, 1em 0);
79
74
  gap: var(--ic-gap, 10pt 5%);
80
- background-color: var(
81
- --ic-bg,
82
- light-dark(rgba(0, 0, 0, 0.05), rgba(255, 255, 255, 0.1))
83
- );
75
+ background-color: var(--ic-bg, light-dark(rgba(0, 0, 0, 0.05), rgba(255, 255, 255, 0.1)));
84
76
  font-size: var(--ic-font-size);
85
77
  width: var(--ic-width);
86
78
  }
@@ -88,10 +80,7 @@
88
80
  grid-column: 1 / -1;
89
81
  margin: 0;
90
82
  border-bottom: 1px solid
91
- var(
92
- --ic-title-border-color,
93
- light-dark(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.3))
94
- );
83
+ var(--ic-title-border-color, light-dark(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.3)));
95
84
  }
96
85
  div {
97
86
  display: flex;
@@ -49,9 +49,7 @@
49
49
  else void copy_to_clipboard()
50
50
  }
51
51
 
52
- function handle_keydown(
53
- event: KeyboardEvent & { currentTarget: HTMLElement },
54
- ): void {
52
+ function handle_keydown(event: KeyboardEvent & { currentTarget: HTMLElement }): void {
55
53
  if (disabled || (event.key !== `Enter` && event.key !== ` `)) return
56
54
  event.preventDefault()
57
55
  event.currentTarget.click()
@@ -0,0 +1,46 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte'
3
+ import type { HTMLAttributes } from 'svelte/elements'
4
+ import { tooltip } from 'svelte-multiselect/attachments'
5
+
6
+ // Paired number + range input bound to the same value, wrapped in a flex <label>.
7
+ // The label text/markup is passed as children (supports inline units like <small>Å</small>).
8
+ // Pass a `title` (via rest) to show a tooltip; wrapping <label> only names the number input
9
+ // so range slider reuses that `title` as its accessible name.
10
+ let {
11
+ value = $bindable(),
12
+ min,
13
+ max,
14
+ step,
15
+ children,
16
+ ...rest
17
+ }: {
18
+ value: number | undefined
19
+ min: number | string
20
+ max: number | string
21
+ step: number | string
22
+ children?: Snippet
23
+ } & HTMLAttributes<HTMLLabelElement> = $props()
24
+ </script>
25
+
26
+ <label {@attach tooltip()} {...rest}>
27
+ {@render children?.()}
28
+ <input type="number" {min} {max} {step} bind:value />
29
+ <input type="range" {min} {max} {step} bind:value aria-label={rest.title} />
30
+ </label>
31
+
32
+ <style>
33
+ label {
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 10pt;
37
+ }
38
+ input {
39
+ font-size: inherit;
40
+ font-family: inherit;
41
+ }
42
+ input[type='range'] {
43
+ flex: 1;
44
+ min-width: 40px;
45
+ }
46
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = {
4
+ value: number | undefined;
5
+ min: number | string;
6
+ max: number | string;
7
+ step: number | string;
8
+ children?: Snippet;
9
+ } & HTMLAttributes<HTMLLabelElement>;
10
+ declare const NumberRangeInput: import("svelte").Component<$$ComponentProps, {}, "value">;
11
+ type NumberRangeInput = ReturnType<typeof NumberRangeInput>;
12
+ export default NumberRangeInput;
@@ -40,9 +40,7 @@
40
40
  onclear?: () => void // Callback when clear button is clicked (fires before onchange)
41
41
  } & HTMLAttributes<HTMLDivElement> = $props()
42
42
 
43
- let show_histogram = $derived(
44
- histogram_position !== `none` && histogram_data?.length,
45
- )
43
+ let show_histogram = $derived(histogram_position !== `none` && histogram_data?.length)
46
44
 
47
45
  // Active when either bound is set (undefined = unbounded)
48
46
  let active = $derived(min_value !== undefined || max_value !== undefined)
@@ -56,9 +54,7 @@
56
54
  return histogram_data.filter((val) => val >= min && val <= max)
57
55
  })
58
56
 
59
- function onkeydown(
60
- event: KeyboardEvent & { currentTarget: HTMLInputElement },
61
- ): void {
57
+ function onkeydown(event: KeyboardEvent & { currentTarget: HTMLInputElement }): void {
62
58
  if (event.key === `Enter`) {
63
59
  event.preventDefault()
64
60
  event.currentTarget.blur()
@@ -14,11 +14,13 @@
14
14
  title: string
15
15
  current_values: Record<string, unknown>
16
16
  children: Snippet<
17
- [{
18
- current_values: Record<string, unknown>
19
- has_changes: boolean
20
- reference_values: Record<string, unknown>
21
- }]
17
+ [
18
+ {
19
+ current_values: Record<string, unknown>
20
+ has_changes: boolean
21
+ reference_values: Record<string, unknown>
22
+ },
23
+ ]
22
24
  >
23
25
  on_reset?: () => void
24
26
  } = $props()
@@ -30,23 +32,22 @@
30
32
  if (obj instanceof RegExp) return new RegExp(obj)
31
33
  if (Array.isArray(obj)) {
32
34
  return obj.map((item) =>
33
- typeof item === `object` && item !== null ? deep_copy(item) : item
35
+ typeof item === `object` && item !== null ? deep_copy(item) : item,
34
36
  )
35
37
  }
36
38
 
37
39
  const copy: Record<string, unknown> = {}
38
40
  for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {
39
- copy[key] = typeof value === `object` && value !== null
40
- ? deep_copy(value)
41
- : value
41
+ copy[key] = typeof value === `object` && value !== null ? deep_copy(value) : value
42
42
  }
43
43
  return copy
44
44
  }
45
45
 
46
46
  // Capture initial values once at mount - must NOT be $derived or it tracks changes
47
- const reference_values = untrack(() =>
48
- deep_copy(current_values) as Record<string, unknown>
49
- )
47
+ const reference_values = untrack(() => deep_copy(current_values) as Record<string, unknown>)
48
+
49
+ // unique per-instance id so aria-labelledby stays valid with multiple sections on a page
50
+ const title_id = `settings-section-title-${crypto.randomUUID()}`
50
51
 
51
52
  // Check if any values have changed from reference values
52
53
  let has_changes = $derived.by(() => {
@@ -61,9 +62,12 @@
61
62
  const curr_val = current_value[idx]
62
63
  // Handle nested objects/arrays in arrays
63
64
  if (
64
- typeof val === `object` && val !== null &&
65
- typeof curr_val === `object` && curr_val !== null
66
- ) return JSON.stringify(val) !== JSON.stringify(curr_val) // Quick deep comparison fallback
65
+ typeof val === `object` &&
66
+ val !== null &&
67
+ typeof curr_val === `object` &&
68
+ curr_val !== null
69
+ )
70
+ return JSON.stringify(val) !== JSON.stringify(curr_val) // Quick deep comparison fallback
67
71
  return val !== curr_val
68
72
  })
69
73
  ) {
@@ -91,7 +95,7 @@
91
95
  }
92
96
  </script>
93
97
 
94
- <h4 id="settings-section-title">
98
+ <h4 id={title_id}>
95
99
  {title}
96
100
 
97
101
  {#if has_changes}
@@ -106,7 +110,7 @@
106
110
  </button>
107
111
  {/if}
108
112
  </h4>
109
- <section {...rest} aria-labelledby="settings-section-title">
113
+ <section {...rest} aria-labelledby={title_id}>
110
114
  {@render children?.({ current_values, has_changes, reference_values })}
111
115
  </section>
112
116
 
@@ -52,7 +52,9 @@
52
52
  border: 1px solid color-mix(in srgb, currentColor 15%, transparent);
53
53
  text-decoration: none;
54
54
  color: inherit;
55
- transition: border-color 0.15s, box-shadow 0.15s;
55
+ transition:
56
+ border-color 0.15s,
57
+ box-shadow 0.15s;
56
58
  &:hover {
57
59
  border-color: color-mix(in srgb, currentColor 35%, transparent);
58
60
  box-shadow: 0 2px 12px color-mix(in srgb, currentColor 8%, transparent);