matterviz 0.4.1 → 0.4.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 (499) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +48 -60
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/api/optimade.js +10 -7
  6. package/dist/app.css +68 -0
  7. package/dist/brillouin/BrillouinZone.svelte +90 -91
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
  9. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
  11. package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
  12. package/dist/brillouin/BrillouinZoneScene.svelte +46 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  14. package/dist/brillouin/compute.js +10 -16
  15. package/dist/brillouin/geometry.js +2 -2
  16. package/dist/chempot-diagram/ChemPotDiagram.svelte +48 -50
  17. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +61 -169
  18. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
  19. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +559 -755
  20. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
  21. package/dist/chempot-diagram/async-compute.svelte.js +13 -14
  22. package/dist/chempot-diagram/color.d.ts +21 -1
  23. package/dist/chempot-diagram/color.js +70 -1
  24. package/dist/chempot-diagram/compute.d.ts +7 -0
  25. package/dist/chempot-diagram/compute.js +85 -26
  26. package/dist/chempot-diagram/controls-state.svelte.js +1 -1
  27. package/dist/chempot-diagram/export.js +1 -6
  28. package/dist/chempot-diagram/temperature.js +9 -10
  29. package/dist/colors/index.d.ts +0 -4
  30. package/dist/colors/index.js +19 -20
  31. package/dist/composition/BarChart.svelte +30 -26
  32. package/dist/composition/BubbleChart.svelte +17 -17
  33. package/dist/composition/Composition.svelte +10 -19
  34. package/dist/composition/Formula.svelte +20 -27
  35. package/dist/composition/FormulaFilter.svelte +115 -184
  36. package/dist/composition/PieChart.svelte +55 -41
  37. package/dist/composition/format.js +7 -9
  38. package/dist/composition/index.d.ts +2 -0
  39. package/dist/composition/index.js +14 -0
  40. package/dist/composition/parse.d.ts +2 -2
  41. package/dist/composition/parse.js +61 -115
  42. package/dist/constants.d.ts +0 -1
  43. package/dist/constants.js +17 -26
  44. package/dist/convex-hull/ConvexHull.svelte +12 -15
  45. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  46. package/dist/convex-hull/ConvexHull2D.svelte +93 -94
  47. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  48. package/dist/convex-hull/ConvexHull3D.svelte +127 -186
  49. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  50. package/dist/convex-hull/ConvexHull4D.svelte +131 -180
  51. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  52. package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
  53. package/dist/convex-hull/ConvexHullControls.svelte +46 -48
  54. package/dist/convex-hull/ConvexHullStats.svelte +193 -195
  55. package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
  56. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  57. package/dist/convex-hull/StructurePopup.svelte +18 -22
  58. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  59. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  60. package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
  61. package/dist/convex-hull/gas-thermodynamics.js +21 -53
  62. package/dist/convex-hull/helpers.d.ts +8 -10
  63. package/dist/convex-hull/helpers.js +37 -43
  64. package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
  65. package/dist/convex-hull/thermodynamics.js +37 -44
  66. package/dist/coordination/CoordinationBarPlot.svelte +49 -53
  67. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  68. package/dist/coordination/calc-coordination.d.ts +1 -1
  69. package/dist/coordination/calc-coordination.js +28 -25
  70. package/dist/element/BohrAtom.svelte +5 -9
  71. package/dist/element/ElementHeading.svelte +4 -1
  72. package/dist/element/ElementPhoto.svelte +11 -9
  73. package/dist/element/ElementStats.svelte +12 -10
  74. package/dist/element/ElementTile.svelte +44 -67
  75. package/dist/element/Nucleus.svelte +4 -2
  76. package/dist/element/data.d.ts +3 -2
  77. package/dist/element/data.js +5 -1
  78. package/dist/element/helpers.d.ts +4 -0
  79. package/dist/element/helpers.js +18 -0
  80. package/dist/element/index.d.ts +2 -5
  81. package/dist/element/index.js +4 -19
  82. package/dist/feedback/DragOverlay.svelte +5 -5
  83. package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
  84. package/dist/feedback/StatusMessage.svelte +7 -4
  85. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  86. package/dist/fermi-surface/FermiSurface.svelte +35 -44
  87. package/dist/fermi-surface/FermiSurface.svelte.d.ts +7 -13
  88. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  89. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  90. package/dist/fermi-surface/FermiSurfaceScene.svelte +64 -136
  91. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  92. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  93. package/dist/fermi-surface/compute.js +25 -58
  94. package/dist/fermi-surface/parse.js +54 -88
  95. package/dist/file-viewer/JsonBrowser.svelte +1043 -0
  96. package/dist/file-viewer/JsonBrowser.svelte.d.ts +9 -0
  97. package/dist/file-viewer/PlotPanel.svelte +350 -0
  98. package/dist/file-viewer/PlotPanel.svelte.d.ts +9 -0
  99. package/dist/file-viewer/TrajectoryWithDos.svelte +30 -0
  100. package/dist/file-viewer/TrajectoryWithDos.svelte.d.ts +10 -0
  101. package/dist/file-viewer/detect.d.ts +11 -0
  102. package/dist/file-viewer/detect.js +381 -0
  103. package/dist/file-viewer/eligibility.d.ts +4 -0
  104. package/dist/file-viewer/eligibility.js +53 -0
  105. package/dist/file-viewer/host-protocol.d.ts +50 -0
  106. package/dist/file-viewer/host-transfer.d.ts +25 -0
  107. package/dist/file-viewer/host-transfer.js +42 -0
  108. package/dist/file-viewer/index.d.ts +5 -0
  109. package/dist/file-viewer/index.js +5 -0
  110. package/dist/file-viewer/main.d.ts +44 -0
  111. package/dist/file-viewer/main.js +535 -0
  112. package/dist/file-viewer/parse.d.ts +9 -0
  113. package/dist/file-viewer/parse.js +170 -0
  114. package/dist/file-viewer/plot-utils.d.ts +24 -0
  115. package/dist/file-viewer/plot-utils.js +191 -0
  116. package/dist/file-viewer/types.d.ts +4 -0
  117. package/dist/file-viewer/types.js +5 -0
  118. package/dist/heatmap-matrix/HeatmapMatrix.svelte +153 -219
  119. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
  120. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
  121. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
  122. package/dist/heatmap-matrix/index.d.ts +5 -0
  123. package/dist/icons.d.ts +4 -0
  124. package/dist/icons.js +4 -0
  125. package/dist/index.d.ts +2 -2
  126. package/dist/index.js +1 -1
  127. package/dist/io/ExportPane.svelte +11 -7
  128. package/dist/io/decompress.d.ts +4 -1
  129. package/dist/io/decompress.js +24 -36
  130. package/dist/io/export.d.ts +11 -4
  131. package/dist/io/export.js +75 -19
  132. package/dist/io/fetch.d.ts +0 -3
  133. package/dist/io/fetch.js +0 -11
  134. package/dist/io/file-drop.js +60 -35
  135. package/dist/io/index.d.ts +0 -1
  136. package/dist/io/index.js +2 -9
  137. package/dist/io/is-binary.d.ts +9 -0
  138. package/dist/io/is-binary.js +45 -1
  139. package/dist/io/url-drop.d.ts +2 -0
  140. package/dist/io/url-drop.js +40 -40
  141. package/dist/isosurface/Isosurface.svelte +700 -215
  142. package/dist/isosurface/Isosurface.svelte.d.ts +7 -1
  143. package/dist/isosurface/IsosurfaceControls.svelte +590 -116
  144. package/dist/isosurface/IsosurfaceControls.svelte.d.ts +1 -1
  145. package/dist/isosurface/VolumeSlice.svelte +224 -0
  146. package/dist/isosurface/VolumeSlice.svelte.d.ts +28 -0
  147. package/dist/isosurface/coloring.d.ts +20 -0
  148. package/dist/isosurface/coloring.js +118 -0
  149. package/dist/isosurface/geometry-worker-types.d.ts +38 -0
  150. package/dist/isosurface/geometry.worker.d.ts +1 -0
  151. package/dist/isosurface/geometry.worker.js +59 -0
  152. package/dist/isosurface/grid.d.ts +10 -0
  153. package/dist/isosurface/grid.js +31 -0
  154. package/dist/isosurface/index.d.ts +4 -0
  155. package/dist/isosurface/index.js +4 -0
  156. package/dist/isosurface/parse-vaspwave.d.ts +3 -0
  157. package/dist/isosurface/parse-vaspwave.js +138 -0
  158. package/dist/isosurface/parse.js +6 -6
  159. package/dist/isosurface/profile.d.ts +12 -0
  160. package/dist/isosurface/profile.js +19 -0
  161. package/dist/isosurface/sampling.d.ts +34 -0
  162. package/dist/isosurface/sampling.js +408 -0
  163. package/dist/isosurface/slice-rendering.d.ts +13 -0
  164. package/dist/isosurface/slice-rendering.js +79 -0
  165. package/dist/isosurface/slice.d.ts +22 -2
  166. package/dist/isosurface/slice.js +200 -116
  167. package/dist/isosurface/types.d.ts +24 -1
  168. package/dist/isosurface/types.js +120 -8
  169. package/dist/json-path.d.ts +4 -0
  170. package/dist/json-path.js +89 -0
  171. package/dist/labels.d.ts +6 -2
  172. package/dist/labels.js +44 -14
  173. package/dist/layout/FullscreenButton.svelte +2 -1
  174. package/dist/layout/FullscreenToggle.svelte +10 -4
  175. package/dist/layout/InfoCard.svelte +8 -21
  176. package/dist/layout/InfoTag.svelte +1 -3
  177. package/dist/layout/NumberRangeInput.svelte +46 -0
  178. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  179. package/dist/layout/PropertyFilter.svelte +2 -6
  180. package/dist/layout/SettingsSection.svelte +57 -62
  181. package/dist/layout/SettingsSection.svelte.d.ts +6 -7
  182. package/dist/layout/SubpageGrid.svelte +3 -1
  183. package/dist/layout/ViewerChrome.svelte +16 -11
  184. package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
  185. package/dist/layout/fullscreen.js +3 -5
  186. package/dist/layout/fullscreen.svelte.js +1 -2
  187. package/dist/layout/index.d.ts +1 -0
  188. package/dist/layout/index.js +1 -0
  189. package/dist/layout/json-tree/JsonNode.svelte +22 -59
  190. package/dist/layout/json-tree/JsonTree.svelte +101 -172
  191. package/dist/layout/json-tree/JsonValue.svelte +9 -32
  192. package/dist/layout/json-tree/utils.d.ts +0 -3
  193. package/dist/layout/json-tree/utils.js +50 -188
  194. package/dist/marching-cubes.d.ts +8 -1
  195. package/dist/marching-cubes.js +115 -48
  196. package/dist/math.d.ts +5 -2
  197. package/dist/math.js +48 -38
  198. package/dist/overlays/ContextMenu.svelte +19 -34
  199. package/dist/overlays/CopyButton.svelte +11 -5
  200. package/dist/overlays/DragControlTab.svelte +6 -1
  201. package/dist/overlays/DraggablePane.svelte +110 -74
  202. package/dist/overlays/DraggablePane.svelte.d.ts +2 -1
  203. package/dist/overlays/GlassChip.svelte +32 -0
  204. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  205. package/dist/overlays/InfoPaneCards.svelte +11 -23
  206. package/dist/overlays/index.d.ts +7 -0
  207. package/dist/overlays/index.js +26 -0
  208. package/dist/overlays/portal.d.ts +2 -0
  209. package/dist/overlays/portal.js +14 -0
  210. package/dist/periodic-table/PeriodicTable.svelte +113 -145
  211. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  212. package/dist/periodic-table/PeriodicTableControls.svelte +37 -115
  213. package/dist/periodic-table/TableInset.svelte +9 -4
  214. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +68 -105
  215. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  216. package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
  217. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  218. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
  219. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
  220. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  221. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  222. package/dist/phase-diagram/build-diagram.js +4 -9
  223. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  224. package/dist/phase-diagram/parse.js +15 -15
  225. package/dist/phase-diagram/svg-to-diagram.js +28 -27
  226. package/dist/phase-diagram/utils.js +2 -3
  227. package/dist/plot/bar/BarPlot.svelte +461 -426
  228. package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
  229. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  230. package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
  231. package/dist/plot/bar/SpacegroupBarPlot.svelte +46 -77
  232. package/dist/plot/bar/data.d.ts +5 -4
  233. package/dist/plot/bar/data.js +2 -1
  234. package/dist/plot/box/BoxPlot.svelte +322 -226
  235. package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
  236. package/dist/plot/box/Violin.svelte.d.ts +1 -0
  237. package/dist/plot/box/box-plot.js +1 -1
  238. package/dist/plot/core/auto-place.d.ts +1 -1
  239. package/dist/plot/core/auto-place.js +2 -2
  240. package/dist/plot/core/axis-utils.d.ts +12 -7
  241. package/dist/plot/core/axis-utils.js +48 -48
  242. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  243. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  244. package/dist/plot/core/components/ColorBar.svelte +101 -106
  245. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  246. package/dist/plot/core/components/FillArea.svelte +10 -17
  247. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  248. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  249. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  250. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  251. package/dist/plot/core/components/Line.svelte +18 -9
  252. package/dist/plot/core/components/Line.svelte.d.ts +2 -0
  253. package/dist/plot/core/components/PlotAxis.svelte +40 -17
  254. package/dist/plot/core/components/PlotControls.svelte +65 -41
  255. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  256. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  257. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  258. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  259. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  260. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  261. package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
  262. package/dist/plot/core/components/ReferencePlane.svelte +7 -8
  263. package/dist/plot/core/components/ZeroLines.svelte +4 -8
  264. package/dist/plot/core/components/ZoomRect.svelte +1 -2
  265. package/dist/plot/core/components/index.d.ts +1 -0
  266. package/dist/plot/core/components/index.js +1 -0
  267. package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
  268. package/dist/plot/core/data-cleaning-signal.js +467 -0
  269. package/dist/plot/core/data-cleaning.d.ts +2 -42
  270. package/dist/plot/core/data-cleaning.js +27 -474
  271. package/dist/plot/core/data-transform.d.ts +1 -2
  272. package/dist/plot/core/data-transform.js +9 -15
  273. package/dist/plot/core/fill-utils.d.ts +3 -1
  274. package/dist/plot/core/fill-utils.js +28 -6
  275. package/dist/plot/core/index.d.ts +1 -0
  276. package/dist/plot/core/index.js +1 -0
  277. package/dist/plot/core/interactions.js +0 -2
  278. package/dist/plot/core/layout.d.ts +15 -6
  279. package/dist/plot/core/layout.js +57 -38
  280. package/dist/plot/core/marginals.d.ts +170 -0
  281. package/dist/plot/core/marginals.js +436 -0
  282. package/dist/plot/core/pan-zoom.svelte.d.ts +2 -4
  283. package/dist/plot/core/pan-zoom.svelte.js +34 -17
  284. package/dist/plot/core/placed-tween.svelte.d.ts +3 -0
  285. package/dist/plot/core/placed-tween.svelte.js +68 -21
  286. package/dist/plot/core/reference-line.js +1 -1
  287. package/dist/plot/core/scales.d.ts +23 -0
  288. package/dist/plot/core/scales.js +39 -13
  289. package/dist/plot/core/svg.js +0 -1
  290. package/dist/plot/core/types/fills.d.ts +101 -0
  291. package/dist/plot/core/types/fills.js +15 -0
  292. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  293. package/dist/plot/core/types/plot-3d.js +4 -0
  294. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  295. package/dist/plot/core/types/reference-lines.js +9 -0
  296. package/dist/plot/core/types.d.ts +29 -324
  297. package/dist/plot/core/types.js +23 -20
  298. package/dist/plot/core/utils/hierarchy-chart.d.ts +52 -0
  299. package/dist/plot/core/utils/hierarchy-chart.js +191 -0
  300. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  301. package/dist/plot/core/utils/hierarchy-labels.js +100 -0
  302. package/dist/plot/core/utils/label-placement.js +2 -2
  303. package/dist/plot/histogram/Histogram.svelte +314 -340
  304. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  305. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  306. package/dist/plot/histogram/histogram.d.ts +31 -0
  307. package/dist/plot/histogram/histogram.js +70 -0
  308. package/dist/plot/histogram/index.d.ts +1 -0
  309. package/dist/plot/histogram/index.js +1 -0
  310. package/dist/plot/index.d.ts +1 -0
  311. package/dist/plot/index.js +1 -0
  312. package/dist/plot/sankey/Sankey.svelte +78 -69
  313. package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
  314. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  315. package/dist/plot/sankey/sankey.js +13 -9
  316. package/dist/plot/scatter/BinnedScatterPlot.svelte +311 -141
  317. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
  318. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  319. package/dist/plot/scatter/ScatterPlot.svelte +517 -410
  320. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
  321. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  322. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  323. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  324. package/dist/plot/scatter/adaptive-density.d.ts +1 -1
  325. package/dist/plot/scatter/adaptive-density.js +36 -20
  326. package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
  327. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  328. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  329. package/dist/plot/scatter/scatter-data.js +8 -7
  330. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
  331. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
  332. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
  333. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
  334. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
  335. package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
  336. package/dist/plot/sunburst/Sunburst.svelte +269 -347
  337. package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
  338. package/dist/plot/sunburst/index.d.ts +1 -1
  339. package/dist/plot/sunburst/index.js +2 -1
  340. package/dist/plot/sunburst/render.d.ts +2 -2
  341. package/dist/plot/sunburst/render.js +47 -22
  342. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  343. package/dist/plot/sunburst/sunburst.js +10 -3
  344. package/dist/plot/treemap/Treemap.svelte +1022 -0
  345. package/dist/plot/treemap/Treemap.svelte.d.ts +90 -0
  346. package/dist/plot/treemap/index.d.ts +4 -0
  347. package/dist/plot/treemap/index.js +4 -0
  348. package/dist/plot/treemap/labels.d.ts +38 -0
  349. package/dist/plot/treemap/labels.js +80 -0
  350. package/dist/plot/treemap/treemap.d.ts +28 -0
  351. package/dist/plot/treemap/treemap.js +102 -0
  352. package/dist/rdf/RdfPlot.svelte +37 -59
  353. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  354. package/dist/rdf/calc-rdf.js +63 -52
  355. package/dist/rdf/index.d.ts +0 -1
  356. package/dist/sanitize.js +85 -27
  357. package/dist/scene/SceneCamera.svelte +1 -1
  358. package/dist/scene/SceneCamera.svelte.d.ts +1 -1
  359. package/dist/scene/bind-renderer.svelte.js +14 -6
  360. package/dist/scene/index.d.ts +1 -2
  361. package/dist/scene/index.js +1 -1
  362. package/dist/scene/{props.js → props.svelte.js} +15 -1
  363. package/dist/settings.d.ts +19 -9
  364. package/dist/settings.js +229 -525
  365. package/dist/spectral/Bands.svelte +207 -221
  366. package/dist/spectral/BandsAndDos.svelte +11 -9
  367. package/dist/spectral/BrillouinBandsDos.svelte +19 -42
  368. package/dist/spectral/Dos.svelte +92 -93
  369. package/dist/spectral/helpers.d.ts +3 -3
  370. package/dist/spectral/helpers.js +65 -140
  371. package/dist/state.svelte.js +5 -18
  372. package/dist/structure/Arrow.svelte +5 -18
  373. package/dist/structure/ArrowInstances.svelte +160 -0
  374. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  375. package/dist/structure/AtomLegend.svelte +120 -85
  376. package/dist/structure/AtomLegend.svelte.d.ts +2 -3
  377. package/dist/structure/Bond.svelte +31 -23
  378. package/dist/structure/CanvasTooltip.svelte +15 -3
  379. package/dist/structure/CellSelect.svelte +45 -35
  380. package/dist/structure/Cylinder.svelte +24 -40
  381. package/dist/structure/InstancedAtoms.svelte +114 -0
  382. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  383. package/dist/structure/Lattice.svelte +85 -149
  384. package/dist/structure/SiteLabels.svelte +122 -0
  385. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  386. package/dist/structure/Structure.svelte +636 -504
  387. package/dist/structure/Structure.svelte.d.ts +4 -2
  388. package/dist/structure/StructureCarousel.svelte +637 -0
  389. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  390. package/dist/structure/StructureControls.svelte +165 -425
  391. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  392. package/dist/structure/StructureExportPane.svelte +17 -21
  393. package/dist/structure/StructureInfoPane.svelte +128 -133
  394. package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
  395. package/dist/structure/StructureScene.svelte +535 -578
  396. package/dist/structure/StructureScene.svelte.d.ts +6 -2
  397. package/dist/structure/StructureViewport.svelte +451 -0
  398. package/dist/structure/StructureViewport.svelte.d.ts +65 -0
  399. package/dist/structure/atom-label-placement.d.ts +16 -12
  400. package/dist/structure/atom-label-placement.js +70 -37
  401. package/dist/structure/atom-properties.d.ts +2 -0
  402. package/dist/structure/atom-properties.js +105 -38
  403. package/dist/structure/bond-order-perception.js +3 -8
  404. package/dist/structure/bonding.d.ts +9 -3
  405. package/dist/structure/bonding.js +95 -46
  406. package/dist/structure/edit-history.d.ts +6 -0
  407. package/dist/structure/edit-history.js +27 -0
  408. package/dist/structure/export.d.ts +1 -0
  409. package/dist/structure/export.js +89 -105
  410. package/dist/structure/format-detect.d.ts +1 -0
  411. package/dist/structure/format-detect.js +20 -0
  412. package/dist/structure/geometry.d.ts +9 -0
  413. package/dist/structure/geometry.js +27 -0
  414. package/dist/structure/index.d.ts +16 -1
  415. package/dist/structure/index.js +15 -10
  416. package/dist/structure/measure.d.ts +1 -1
  417. package/dist/structure/measure.js +6 -12
  418. package/dist/structure/parse.d.ts +2 -1
  419. package/dist/structure/parse.js +272 -313
  420. package/dist/structure/partial-occupancy.js +10 -5
  421. package/dist/structure/pbc.js +85 -107
  422. package/dist/structure/polyhedra.d.ts +0 -1
  423. package/dist/structure/polyhedra.js +7 -21
  424. package/dist/structure/prop-groups.d.ts +85 -0
  425. package/dist/structure/prop-groups.js +18 -0
  426. package/dist/structure/supercell.d.ts +1 -2
  427. package/dist/structure/supercell.js +7 -13
  428. package/dist/symmetry/SymmetryElements.svelte +11 -15
  429. package/dist/symmetry/SymmetryStats.svelte +55 -71
  430. package/dist/symmetry/WyckoffTable.svelte +10 -28
  431. package/dist/symmetry/cell-transform.js +6 -14
  432. package/dist/symmetry/index.d.ts +1 -0
  433. package/dist/symmetry/index.js +13 -10
  434. package/dist/symmetry/spacegroups.js +3 -2
  435. package/dist/table/HeatmapTable.svelte +1142 -447
  436. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  437. package/dist/table/ToggleMenu.svelte +168 -53
  438. package/dist/table/ToggleMenu.svelte.d.ts +1 -1
  439. package/dist/table/index.d.ts +21 -6
  440. package/dist/table/index.js +34 -21
  441. package/dist/theme/ThemeControl.svelte +16 -8
  442. package/dist/theme/embedded.d.ts +18 -0
  443. package/dist/theme/embedded.js +206 -0
  444. package/dist/theme/index.d.ts +5 -5
  445. package/dist/theme/index.js +5 -12
  446. package/dist/theme/themes.mjs +44 -66
  447. package/dist/tooltip/KCoords.svelte +4 -1
  448. package/dist/tooltip/TooltipContent.svelte +3 -6
  449. package/dist/tooltip/TooltipContent.svelte.d.ts +1 -1
  450. package/dist/tooltip/index.d.ts +8 -1
  451. package/dist/trajectory/Trajectory.svelte +613 -386
  452. package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
  453. package/dist/trajectory/TrajectoryError.svelte +12 -74
  454. package/dist/trajectory/TrajectoryExportPane.svelte +14 -32
  455. package/dist/trajectory/TrajectoryInfoPane.svelte +127 -164
  456. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +2 -1
  457. package/dist/trajectory/extract.js +61 -49
  458. package/dist/trajectory/format-detect.d.ts +2 -0
  459. package/dist/trajectory/format-detect.js +17 -13
  460. package/dist/trajectory/frame-reader.d.ts +2 -0
  461. package/dist/trajectory/frame-reader.js +35 -32
  462. package/dist/trajectory/helpers.d.ts +2 -0
  463. package/dist/trajectory/helpers.js +34 -56
  464. package/dist/trajectory/index.d.ts +1 -0
  465. package/dist/trajectory/index.js +5 -8
  466. package/dist/trajectory/parse/ase.js +1 -1
  467. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  468. package/dist/trajectory/parse/h5-utils.js +109 -0
  469. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  470. package/dist/trajectory/parse/hdf5.js +116 -106
  471. package/dist/trajectory/parse/index.d.ts +6 -6
  472. package/dist/trajectory/parse/index.js +25 -33
  473. package/dist/trajectory/parse/lammps.js +8 -12
  474. package/dist/trajectory/parse/vasp.js +10 -7
  475. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  476. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  477. package/dist/trajectory/parse/vaspout-h5.d.ts +4 -0
  478. package/dist/trajectory/parse/vaspout-h5.js +281 -0
  479. package/dist/trajectory/parse/xyz.js +59 -9
  480. package/dist/trajectory/plotting.d.ts +8 -9
  481. package/dist/trajectory/plotting.js +113 -64
  482. package/dist/utils.d.ts +3 -0
  483. package/dist/utils.js +7 -0
  484. package/dist/xrd/XrdPlot.svelte +79 -118
  485. package/dist/xrd/broadening.js +2 -1
  486. package/dist/xrd/calc-xrd.js +24 -62
  487. package/dist/xrd/parse.d.ts +0 -1
  488. package/dist/xrd/parse.js +69 -95
  489. package/package.json +94 -34
  490. package/readme.md +6 -5
  491. package/dist/api/mp.d.ts +0 -6
  492. package/dist/api/mp.js +0 -22
  493. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
  494. package/dist/scene/types.d.ts +0 -26
  495. package/dist/tooltip/types.d.ts +0 -8
  496. package/dist/trajectory/constants.d.ts +0 -6
  497. package/dist/trajectory/constants.js +0 -11
  498. /package/dist/{scene/types.js → file-viewer/host-protocol.js} +0 -0
  499. /package/dist/{tooltip/types.js → isosurface/geometry-worker-types.js} +0 -0
@@ -2,7 +2,11 @@
2
2
  import type { Snippet } from 'svelte'
3
3
  import type { HTMLAttributes } from 'svelte/elements'
4
4
 
5
- let { message, children, ...rest }: {
5
+ let {
6
+ message,
7
+ children,
8
+ ...rest
9
+ }: {
6
10
  // Simple text message to display. Ignored if children snippet is provided.
7
11
  message?: string
8
12
  // Custom content to render. Takes precedence over message prop.
@@ -10,7 +14,7 @@
10
14
  } & HTMLAttributes<HTMLDivElement> = $props()
11
15
  </script>
12
16
 
13
- <div {...rest} class="empty-state {rest.class ?? ``}">
17
+ <div {...rest} class={[`empty-state`, rest.class]}>
14
18
  {#if children}
15
19
  {@render children()}
16
20
  {:else if message}
@@ -34,10 +38,12 @@
34
38
  .empty-state :global(.status-message) {
35
39
  --status-message-border: none; /* Remove inner border from StatusMessage */
36
40
  }
37
- .empty-state > :global(:is(p, h3, ul, strong)), .empty-state > .message {
41
+ .empty-state > :global(:is(p, h3, ul, strong)),
42
+ .empty-state > .message {
38
43
  max-width: var(--empty-state-max-width, 500px);
39
44
  }
40
- .empty-state :global(p), .empty-state > .message {
45
+ .empty-state :global(p),
46
+ .empty-state > .message {
41
47
  color: var(--text-color-muted);
42
48
  margin: 0;
43
49
  }
@@ -56,12 +56,23 @@
56
56
  // Timer for distinguishing click from double-click (per-component state)
57
57
  let click_timer: ReturnType<typeof setTimeout> | null = null
58
58
  let click_timer_file: string | null = null
59
+ const file_key = (file: FileInfo): string => file.url || file.name
59
60
 
60
61
  const clear_click_timer = () => {
61
- if (click_timer) clearTimeout(click_timer)
62
+ if (click_timer !== null) clearTimeout(click_timer)
62
63
  click_timer = null
63
64
  click_timer_file = null
64
65
  }
66
+ const is_activation_key = (event: KeyboardEvent): boolean =>
67
+ event.key === `Enter` || event.key === ` `
68
+
69
+ const schedule_single_click = (file: FileInfo, event: MouseEvent) => {
70
+ click_timer_file = file_key(file)
71
+ click_timer = setTimeout(() => {
72
+ clear_click_timer()
73
+ on_click?.(file, event)
74
+ }, CLICK_DELAY)
75
+ }
65
76
 
66
77
  // Helper function to get the base file type (removing .gz extension)
67
78
  const get_base_file_type = (file: FileInfo): string => {
@@ -94,38 +105,29 @@
94
105
  )
95
106
 
96
107
  const toggle_filter = (kind: FilterKind, filter: string) => {
97
- if (kind === `category`) {
98
- active_category_filter = active_category_filter === filter ? null : filter
99
- active_type_filter = null
100
- } else {
101
- active_type_filter = active_type_filter === filter ? null : filter
102
- active_category_filter = null
103
- }
108
+ const active_filter = kind === `category` ? active_category_filter : active_type_filter
109
+ active_category_filter = kind === `category` && active_filter !== filter ? filter : null
110
+ active_type_filter = kind === `type` && active_filter !== filter ? filter : null
104
111
  }
105
112
 
106
113
  const handle_drag_start = (file: FileInfo) => (event: DragEvent) => {
107
- const file_url = file.url || file.name // Get the URL to drag (falling back to name)
108
-
109
- const payload = JSON.stringify({
110
- name: file.name,
111
- url: file_url,
112
- type: file.type || get_base_file_type(file),
113
- category: file.category,
114
- })
115
- // Set file data as JSON for applications that can handle it
116
- event.dataTransfer?.setData(`application/json`, payload)
117
-
118
- // Also set plain text as fallback for external applications
119
- event.dataTransfer?.setData(`text/plain`, file_url)
120
-
114
+ const url = file_key(file)
115
+ event.dataTransfer?.setData(
116
+ `application/json`,
117
+ JSON.stringify({
118
+ name: file.name,
119
+ url,
120
+ type: file.type || get_base_file_type(file),
121
+ category: file.category,
122
+ }),
123
+ )
124
+ event.dataTransfer?.setData(`text/plain`, url)
121
125
  on_drag_start?.(file, event)
122
126
  }
123
127
 
124
128
  // Get unique file types/categories for format/category filters
125
129
  let uniq_formats = $derived([...new Set(files.map(get_base_file_type))].sort())
126
- let uniq_categories = $derived(
127
- [...new Set(files.map(get_category_id))].filter(Boolean).sort(),
128
- )
130
+ let uniq_categories = $derived([...new Set(files.map(get_category_id))].sort())
129
131
  </script>
130
132
 
131
133
  <div class="file-picker" class:vertical={layout === `vertical`} {...rest}>
@@ -135,11 +137,8 @@
135
137
  <span
136
138
  class="legend-item"
137
139
  class:active={is_active}
138
- onclick={() => category && toggle_filter(`category`, category)}
139
- onkeydown={(evt) =>
140
- (evt.key === `Enter` || evt.key === ` `) &&
141
- category &&
142
- toggle_filter(`category`, category)}
140
+ onclick={() => toggle_filter(`category`, category)}
141
+ onkeydown={(event) => is_activation_key(event) && toggle_filter(`category`, category)}
143
142
  role="button"
144
143
  tabindex="0"
145
144
  aria-pressed={is_active}
@@ -148,8 +147,7 @@
148
147
  {category}
149
148
  </span>
150
149
  {/each}
151
- {#if show_category_filters && uniq_categories.length > 0 &&
152
- uniq_formats.length > 0}
150
+ {#if show_category_filters && uniq_categories.length > 0 && uniq_formats.length > 0}
153
151
  <span class="divider"></span>
154
152
  {/if}
155
153
 
@@ -159,16 +157,13 @@
159
157
  class="legend-item format-item"
160
158
  class:active={is_active}
161
159
  onclick={() => toggle_filter(`type`, format)}
162
- onkeydown={(evt) =>
163
- (evt.key === `Enter` || evt.key === ` `) && toggle_filter(`type`, format)}
160
+ onkeydown={(event) => is_activation_key(event) && toggle_filter(`type`, format)}
164
161
  role="button"
165
162
  tabindex="0"
166
163
  {@attach tooltip({ content: `Filter to show only ${format.toUpperCase()} files` })}
167
164
  >
168
- <span
169
- class="format-circle"
170
- style:background-color={file_type_colors[format]}
171
- ></span> {format.toUpperCase()}
165
+ <span class="format-circle" style:background-color={file_type_colors[format]}></span>
166
+ {format.toUpperCase()}
172
167
  </span>
173
168
  {/each}
174
169
 
@@ -176,7 +171,7 @@
176
171
  <button
177
172
  {@attach tooltip({ content: `Clear all filters` })}
178
173
  class="clear-filter"
179
- onclick={() => [active_category_filter, active_type_filter] = [null, null]}
174
+ onclick={() => ([active_category_filter, active_type_filter] = [null, null])}
180
175
  >
181
176
 
182
177
  </button>
@@ -194,26 +189,17 @@
194
189
  ondragend={() => on_drag_end?.()}
195
190
  onclick={(event) => {
196
191
  clear_click_timer()
197
- if (on_dblclick) {
198
- // Delay click to allow double-click to cancel it
199
- const target_file = file.name
200
- click_timer_file = target_file
201
- click_timer = setTimeout(() => {
202
- if (click_timer_file === target_file) {
203
- clear_click_timer()
204
- on_click?.(file, event)
205
- }
206
- }, CLICK_DELAY)
207
- } else {
208
- on_click?.(file, event)
209
- }
192
+ if (on_dblclick) schedule_single_click(file, event)
193
+ else on_click?.(file, event)
210
194
  }}
211
195
  ondblclick={(event) => {
196
+ const pending = click_timer_file
212
197
  clear_click_timer()
213
- on_dblclick?.(file, event)
198
+ if (pending !== null && pending === file_key(file)) on_dblclick?.(file, event)
199
+ else schedule_single_click(file, event)
214
200
  }}
215
201
  onkeydown={(event) => {
216
- if ([`Enter`, ` `].includes(event.key)) {
202
+ if (is_activation_key(event)) {
217
203
  event.preventDefault()
218
204
  clear_click_timer()
219
205
  on_click?.(file, event)
@@ -222,17 +208,19 @@
222
208
  role="button"
223
209
  tabindex="0"
224
210
  title={on_click
225
- ? `Click to load or drag this ${base_type.toUpperCase()} file`
226
- : `Drag this ${base_type.toUpperCase()} file`}
211
+ ? `Click to load or drag this ${base_type.toUpperCase()} file`
212
+ : `Drag this ${base_type.toUpperCase()} file`}
227
213
  >
228
214
  {#if file.label}
229
215
  <span
230
216
  class="file-type-badge"
231
217
  style:background-color={file_type_colors[base_type] ?? `rgba(128,128,128,0.8)`}
232
- >{base_type.toUpperCase()}</span>
218
+ >{base_type.toUpperCase()}</span
219
+ >
233
220
  {/if}
234
221
  <div class="file-name">
235
- {file.category ? `${file.category_icon} ` : ``}{file.label ?? file.name}
222
+ {file.category && file.category_icon ? `${file.category_icon} ` : ``}{file.label ??
223
+ file.name}
236
224
  </div>
237
225
  </div>
238
226
  {/each}
@@ -318,9 +306,9 @@
318
306
  .file-item {
319
307
  display: flex;
320
308
  align-items: center;
321
- padding: 4pt 8pt;
309
+ padding: 2pt 8pt;
322
310
  border: 1px solid light-dark(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.2));
323
- border-radius: 20px;
311
+ border-radius: 9px;
324
312
  cursor: grab;
325
313
  background: light-dark(rgba(0, 0, 0, 0.02), rgba(255, 255, 255, 0.1));
326
314
  transition: all 0.2s ease;
package/dist/Icon.svelte CHANGED
@@ -3,10 +3,13 @@
3
3
  import { ICON_DATA, type IconName } from './icons'
4
4
 
5
5
  type IconData = { path: string; viewBox: string; stroke?: string }
6
- let { icon, path, viewBox = `0 0 24 24`, stroke, ...rest }:
7
- & { icon?: IconName }
8
- & Partial<IconData>
9
- & SVGAttributes<SVGSVGElement> = $props()
6
+ let {
7
+ icon,
8
+ path,
9
+ viewBox = `0 0 24 24`,
10
+ stroke,
11
+ ...rest
12
+ }: { icon?: IconName } & Partial<IconData> & SVGAttributes<SVGSVGElement> = $props()
10
13
 
11
14
  const data: IconData = $derived.by(() => {
12
15
  if (path) return { path, viewBox, stroke }
@@ -20,7 +20,7 @@
20
20
  }
21
21
  // Fall back to compact single-digit format: "001", "-101"
22
22
  const compact = input.replaceAll(/\s+/g, ``)
23
- const match = compact.match(/^(-?\d)(-?\d)(-?\d)$/)
23
+ const match = compact.match(/^(?<h>-?\d)(?<k>-?\d)(?<l>-?\d)$/)
24
24
  if (match) return [Number(match[1]), Number(match[2]), Number(match[3])] as Vec3
25
25
  return null
26
26
  }
@@ -53,7 +53,7 @@
53
53
  font-size: 0.85em;
54
54
  }
55
55
  input {
56
- width: 4em;
56
+ width: 5.5em;
57
57
  padding: 0.15em 0.3em;
58
58
  border: 1px solid var(--border-color, #ccc);
59
59
  border-radius: 4px;
@@ -110,12 +110,16 @@ export function detect_provider_from_slug(slug, providers) {
110
110
  const prefix = decoded_slug.split(`-`)[0].toLowerCase();
111
111
  return providers.find((provider) => provider.id === prefix)?.id ?? ``;
112
112
  }
113
- export async function fetch_optimade_structure(structure_id, provider, providers) {
113
+ // Resolve a provider id to its versioned API base URL (throws on unknown provider)
114
+ async function get_api_base(provider, providers) {
114
115
  const provider_config = providers.find((entry) => entry.id === provider);
115
116
  if (!provider_config)
116
117
  throw new Error(`Unknown provider: ${provider}`);
117
118
  const base_url = await resolve_provider_url(provider_config.attributes.base_url);
118
- const api_base = base_url.endsWith(`/v1`) ? base_url : `${base_url}/v1`;
119
+ return base_url.endsWith(`/v1`) ? base_url : `${base_url}/v1`;
120
+ }
121
+ export async function fetch_optimade_structure(structure_id, provider, providers) {
122
+ const api_base = await get_api_base(provider, providers);
119
123
  const encoded_id = encode_structure_id(structure_id);
120
124
  const response = await fetch_with_cors_proxy(`${api_base}/structures/${encoded_id}`);
121
125
  const data = await response.json();
@@ -124,12 +128,11 @@ export async function fetch_optimade_structure(structure_id, provider, providers
124
128
  return Array.isArray(data.data) ? data.data[0] : data.data;
125
129
  }
126
130
  export async function fetch_suggested_structures(provider, providers, limit = 12) {
127
- const provider_config = providers.find((entry) => entry.id === provider);
128
- if (!provider_config)
129
- throw new Error(`Unknown provider: ${provider}`);
130
131
  try {
131
- const base_url = await resolve_provider_url(provider_config.attributes.base_url);
132
- const api_base = base_url.endsWith(`/v1`) ? base_url : `${base_url}/v1`;
132
+ // Keep get_api_base inside try: suggestions are optional, so unknown providers and
133
+ // URL-resolution failures both soft-fail to []. Note: unknown provider threw
134
+ // pre-cleanup, which left the sole caller's loading state stuck on rejection.
135
+ const api_base = await get_api_base(provider, providers);
133
136
  const response = await fetch_with_cors_proxy(`${api_base}/structures?page_limit=${limit}&page_offset=0`);
134
137
  const data = await response.json();
135
138
  return Array.isArray(data.data) ? data.data : [];
package/dist/app.css CHANGED
@@ -18,6 +18,28 @@
18
18
  --sms-selected-bg: light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.15));
19
19
  --border-radius: 3pt;
20
20
 
21
+ /* Single source of truth for viewer control-button icon size, shared by all viewer chromes
22
+ (Structure/Brillouin/Fermi/ConvexHull/Trajectory). Scales with the container but is capped so
23
+ toolbar icons don't grow oversized in fullscreen. Uses rem (not em) so the size is consistent
24
+ across viewers regardless of their local font-size (e.g. Trajectory's controls run at 0.85em).
25
+ Override per viewer by setting this on its wrapper. */
26
+ --ctrl-btn-icon-size: clamp(0.7rem, 2cqmin, 0.85rem);
27
+
28
+ /* In-viewer overlay stack (inside one viewer container, above its WebGL
29
+ canvas): 1 viewport labels · 2 glass chips · 4–6 carousel chrome
30
+ (legend/resize-handle/pager) · 10 draggable panes · 100 dropdowns +
31
+ toasts · 1000 canvas tooltips + error banners. Components fall back to
32
+ these tiers; override per instance via their dedicated --*-z-index vars.
33
+ NOTE (WKWebView/Tauri): overlays that can overlap a WebGL canvas also
34
+ need their own compositing layer (will-change: transform) — after hiding
35
+ and re-showing the window, WebKit reattaches canvas layers above
36
+ non-composited overlays regardless of z-index. */
37
+ --z-index-viewer-label: 1;
38
+ --z-index-viewer-chip: 2;
39
+ --z-index-viewer-pane: 10;
40
+ --z-index-viewer-dropdown: 100;
41
+ --z-index-viewer-tooltip: 1000;
42
+
21
43
  /* App-wide overlay stack: controls < fullscreen/nav < dialogs < floating options.
22
44
  These must exceed Threlte HTML overlays, which use very high z-index values. */
23
45
  --z-index-overlay-controls: 100000000;
@@ -204,6 +226,52 @@
204
226
  input:is([type='checkbox'], [type='radio'], [type='range'], [type='color']) {
205
227
  border: none;
206
228
  }
229
+ input[type='range'] {
230
+ --range-track-bg: var(--range-track-bg-override, var(--surface-bg, #2a2f3a));
231
+ --range-track-border: var(--range-track-border-override, var(--border-color, #404040));
232
+ --range-thumb-bg: var(--range-thumb-bg-override, var(--accent-color, #4a9eff));
233
+ -webkit-appearance: none;
234
+ appearance: none;
235
+ background: transparent;
236
+ accent-color: var(--range-thumb-bg);
237
+ cursor: pointer;
238
+ }
239
+ input[type='range']::-webkit-slider-runnable-track {
240
+ height: var(--range-track-height, 0.45rem);
241
+ border-radius: 999px;
242
+ background: var(--range-track-bg);
243
+ box-shadow: inset 0 0 0 1px var(--range-track-border);
244
+ }
245
+ input[type='range']::-webkit-slider-thumb {
246
+ -webkit-appearance: none;
247
+ inline-size: var(--range-thumb-size, 0.9rem);
248
+ block-size: var(--range-thumb-size, 0.9rem);
249
+ margin-top: calc(
250
+ (var(--range-track-height, 0.45rem) - var(--range-thumb-size, 0.9rem)) / 2
251
+ );
252
+ border-radius: 50%;
253
+ background: var(--range-thumb-bg);
254
+ box-shadow: 0 0 0 2px var(--surface-bg, #1f242d);
255
+ }
256
+ input[type='range']::-moz-range-track {
257
+ height: var(--range-track-height, 0.45rem);
258
+ border-radius: 999px;
259
+ background: var(--range-track-bg);
260
+ box-shadow: inset 0 0 0 1px var(--range-track-border);
261
+ }
262
+ input[type='range']::-moz-range-progress {
263
+ height: var(--range-track-height, 0.45rem);
264
+ border-radius: 999px;
265
+ background: var(--range-thumb-bg);
266
+ }
267
+ input[type='range']::-moz-range-thumb {
268
+ inline-size: var(--range-thumb-size, 0.9rem);
269
+ block-size: var(--range-thumb-size, 0.9rem);
270
+ border: 0;
271
+ border-radius: 50%;
272
+ background: var(--range-thumb-bg);
273
+ box-shadow: 0 0 0 2px var(--surface-bg, #1f242d);
274
+ }
207
275
  input[type='number'] {
208
276
  min-width: 40px;
209
277
  width: auto;
@@ -3,7 +3,7 @@
3
3
  import EmptyState from '../EmptyState.svelte'
4
4
  import { StatusMessage } from '../feedback'
5
5
  import Spinner from '../feedback/Spinner.svelte'
6
- import { create_file_drop_handler, drag_over_handlers, load_from_url } from '../io'
6
+ import * as io from '../io'
7
7
  import { type FullscreenToggleProp, toggle_fullscreen, ViewerChrome } from '../layout'
8
8
  import { sync_fullscreen } from '../layout/fullscreen.svelte'
9
9
  import type { Vec3 } from '../math'
@@ -53,7 +53,7 @@
53
53
  surface_color = $bindable(`#4488ff`),
54
54
  surface_opacity = $bindable(0.3),
55
55
  edge_color = $bindable(`#000000`),
56
- edge_width = $bindable(0.05),
56
+ edge_width = $bindable(0.002),
57
57
  show_vectors = $bindable(true),
58
58
  vector_scale = $bindable(1.0),
59
59
  camera_projection = $bindable(`perspective`),
@@ -91,72 +91,68 @@
91
91
  on_point_hover,
92
92
  on_hover,
93
93
  ...rest
94
- }:
95
- & {
96
- structure?: Crystal
97
- bz_order?: number
98
- bz_data?: BrillouinZoneData
99
- controls_open?: boolean
100
- info_pane_open?: boolean
101
- surface_color?: string
102
- surface_opacity?: number
103
- edge_color?: string
104
- edge_width?: number
105
- show_vectors?: boolean
106
- vector_scale?: number
107
- camera_projection?: CameraProjection
108
- // Irreducible BZ options
109
- show_ibz?: boolean
110
- ibz_color?: string
111
- ibz_opacity?: number
112
- ibz_data?: IrreducibleBZData | null
113
- // Controls visibility configuration.
114
- // - 'always': controls always visible
115
- // - 'hover': controls visible on component hover (default)
116
- // - 'never': controls never visible
117
- // - object: { mode, hidden, style } for fine-grained control
118
- //
119
- // Control names: 'filename', 'fullscreen', 'info-pane', 'export-pane', 'controls'
120
- show_controls?: ShowControlsProp
121
- fullscreen?: boolean
122
- width?: number
123
- height?: number
124
- wrapper?: HTMLDivElement
125
- png_dpi?: number
126
- hovered?: boolean
127
- dragover?: boolean
128
- allow_file_drop?: boolean
129
- fullscreen_toggle?: FullscreenToggleProp
130
- data_url?: string
131
- on_file_drop?: (content: string | ArrayBuffer, filename: string) => void
132
- spinner_props?: ComponentProps<typeof Spinner>
133
- loading?: boolean
134
- error_msg?: string
135
- structure_string?: string
136
- // K-path points in Cartesian reciprocal space coordinates (not fractional coords)
137
- // Should be computed using the reciprocal lattice matrix (includes 2π factor)
138
- k_path_points?: Vec3[]
139
- // K-path labels with positions in Cartesian reciprocal space coordinates
140
- // Each position should match a corresponding point in k_path_points
141
- k_path_labels?: { position: Vec3; label: string | null }[]
142
- // Currently hovered k-point in Cartesian reciprocal space coordinates
143
- hovered_k_point?: Vec3 | null
144
- // Index of the currently hovered q-point in the band structure
145
- hovered_qpoint_index?: number | null
146
- // Called with the q-point index when the user hovers the k-path in the BZ (null on leave)
147
- on_kpath_hover?: (qpoint_index: number | null) => void
148
- children?: Snippet<
149
- [{ structure?: Crystal; bz_data?: BrillouinZoneData }]
150
- >
151
- tooltip_config?: BZTooltipProp
152
- on_file_load?: (data: BZHandlerData) => void
153
- on_error?: (data: BZHandlerData) => void
154
- on_fullscreen_change?: (data: BZHandlerData) => void
155
- on_point_hover?: (data: BZHoverData | null) => void
156
- // Deprecated alias for on_point_hover (honored when on_point_hover is unset)
157
- on_hover?: (data: BZHoverData | null) => void
158
- }
159
- & HTMLAttributes<HTMLDivElement> = $props()
94
+ }: {
95
+ structure?: Crystal
96
+ bz_order?: number
97
+ bz_data?: BrillouinZoneData
98
+ controls_open?: boolean
99
+ info_pane_open?: boolean
100
+ surface_color?: string
101
+ surface_opacity?: number
102
+ edge_color?: string
103
+ edge_width?: number
104
+ show_vectors?: boolean
105
+ vector_scale?: number
106
+ camera_projection?: CameraProjection
107
+ // Irreducible BZ options
108
+ show_ibz?: boolean
109
+ ibz_color?: string
110
+ ibz_opacity?: number
111
+ ibz_data?: IrreducibleBZData | null
112
+ // Controls visibility configuration.
113
+ // - 'always': controls always visible
114
+ // - 'hover': controls visible on component hover (default)
115
+ // - 'never': controls never visible
116
+ // - object: { mode, hidden, style } for fine-grained control
117
+ //
118
+ // Control names: 'filename', 'fullscreen', 'info-pane', 'export-pane', 'controls'
119
+ show_controls?: ShowControlsProp
120
+ fullscreen?: boolean
121
+ width?: number
122
+ height?: number
123
+ wrapper?: HTMLDivElement
124
+ png_dpi?: number
125
+ hovered?: boolean
126
+ dragover?: boolean
127
+ allow_file_drop?: boolean
128
+ fullscreen_toggle?: FullscreenToggleProp
129
+ data_url?: string
130
+ on_file_drop?: (content: string | ArrayBuffer, filename: string) => void
131
+ spinner_props?: ComponentProps<typeof Spinner>
132
+ loading?: boolean
133
+ error_msg?: string
134
+ structure_string?: string
135
+ // K-path points in Cartesian reciprocal space coordinates (not fractional coords)
136
+ // Should be computed using the reciprocal lattice matrix (includes factor)
137
+ k_path_points?: Vec3[]
138
+ // K-path labels with positions in Cartesian reciprocal space coordinates
139
+ // Each position should match a corresponding point in k_path_points
140
+ k_path_labels?: { position: Vec3; label: string | null }[]
141
+ // Currently hovered k-point in Cartesian reciprocal space coordinates
142
+ hovered_k_point?: Vec3 | null
143
+ // Index of the currently hovered q-point in the band structure
144
+ hovered_qpoint_index?: number | null
145
+ // Called with the q-point index when the user hovers the k-path in the BZ (null on leave)
146
+ on_kpath_hover?: (qpoint_index: number | null) => void
147
+ children?: Snippet<[{ structure?: Crystal; bz_data?: BrillouinZoneData }]>
148
+ tooltip_config?: BZTooltipProp
149
+ on_file_load?: (data: BZHandlerData) => void
150
+ on_error?: (data: BZHandlerData) => void
151
+ on_fullscreen_change?: (data: BZHandlerData) => void
152
+ on_point_hover?: (data: BZHoverData | null) => void
153
+ // Deprecated alias for on_point_hover (honored when on_point_hover is unset)
154
+ on_hover?: (data: BZHoverData | null) => void
155
+ } & HTMLAttributes<HTMLDivElement> = $props()
160
156
 
161
157
  let scene = $state(undefined)
162
158
  let camera = $state(undefined)
@@ -181,9 +177,7 @@
181
177
 
182
178
  // Parse and load structure from content
183
179
  function parse_structure(content: string | ArrayBuffer, filename: string) {
184
- const text = content instanceof ArrayBuffer
185
- ? new TextDecoder().decode(content)
186
- : content
180
+ const text = content instanceof ArrayBuffer ? new TextDecoder().decode(content) : content
187
181
  const parsed = parse_any_structure(text, filename)
188
182
  if (!parsed) throw new Error(`Failed to parse structure from ${filename}`)
189
183
 
@@ -198,9 +192,7 @@
198
192
  try {
199
193
  parse_structure(content, filename)
200
194
  } catch (err) {
201
- error_msg = `Failed to parse ${filename}: ${
202
- to_error(err).message
203
- }`
195
+ error_msg = `Failed to parse ${filename}: ${to_error(err).message}`
204
196
  on_error?.({ error_msg, filename })
205
197
  }
206
198
  }
@@ -241,9 +233,7 @@
241
233
  analyze_structure_symmetry(structure, {})
242
234
  .then((sym_data) => {
243
235
  if (stale) return
244
- const point_group_ops = extract_point_group_from_operations(
245
- sym_data.operations,
246
- )
236
+ const point_group_ops = extract_point_group_from_operations(sym_data.operations)
247
237
  ibz_data = compute_irreducible_bz(captured_bz, point_group_ops)
248
238
  })
249
239
  .catch((err) => {
@@ -258,24 +248,29 @@
258
248
  })
259
249
 
260
250
  // Load structure from URL or string
251
+ let data_url_load_id = 0
261
252
  $effect(() => {
262
253
  const handle_error = (err: unknown, source: string) => {
263
254
  error_msg = to_error(err).message
264
255
  on_error?.({ error_msg, filename: source })
265
256
  }
266
257
 
267
- if (data_url && !structure) {
258
+ const requested_url = data_url
259
+ if (requested_url && !structure) {
260
+ const load_id = ++data_url_load_id
268
261
  loading = true
269
262
  error_msg = undefined
270
- load_from_url(
271
- data_url,
272
- (content, filename) =>
273
- on_file_drop
274
- ? on_file_drop(content, filename)
275
- : safe_parse(content, filename),
276
- )
277
- .catch((err) => handle_error(err, data_url))
278
- .finally(() => (loading = false))
263
+ io.load_from_url(requested_url, (content, filename) => {
264
+ if (load_id !== data_url_load_id) return
265
+ return on_file_drop ? on_file_drop(content, filename) : safe_parse(content, filename)
266
+ })
267
+ .catch((err) => {
268
+ if (load_id !== data_url_load_id) return
269
+ handle_error(err, io.basename_from_url(requested_url))
270
+ })
271
+ .finally(() => {
272
+ if (load_id === data_url_load_id) loading = false
273
+ })
279
274
  } else if (structure_string && !data_url) {
280
275
  loading = true
281
276
  error_msg = undefined
@@ -289,7 +284,7 @@
289
284
  }
290
285
  })
291
286
 
292
- const handle_file_drop = create_file_drop_handler({
287
+ const handle_file_drop = io.create_file_drop_handler({
293
288
  allow: () => allow_file_drop,
294
289
  on_drop: (content, filename) => (on_file_drop || safe_parse)(content, filename),
295
290
  on_error: (msg) => {
@@ -307,7 +302,8 @@
307
302
  if (
308
303
  target instanceof HTMLElement &&
309
304
  (target.tagName === `INPUT` || target.tagName === `TEXTAREA`)
310
- ) return
305
+ )
306
+ return
311
307
 
312
308
  if (event.key === `f` && fullscreen_toggle) toggle_fullscreen(wrapper)
313
309
  else if (event.key === `i`) info_pane_open = !info_pane_open
@@ -338,10 +334,13 @@
338
334
  onmouseenter={() => (hovered = true)}
339
335
  onmouseleave={() => (hovered = false)}
340
336
  ondrop={handle_file_drop}
341
- {...drag_over_handlers({ allow: () => allow_file_drop, set_dragover: (over) => dragover = over })}
337
+ {...io.drag_over_handlers({
338
+ allow: () => allow_file_drop,
339
+ set_dragover: (over) => (dragover = over),
340
+ })}
342
341
  {onkeydown}
343
342
  {...rest}
344
- class="brillouin-zone {rest.class ?? ``}"
343
+ class={[`brillouin-zone`, rest.class]}
345
344
  >
346
345
  {@render children?.({ structure, bz_data })}
347
346
  {#if loading}