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
@@ -3,7 +3,7 @@ import { type ElementSymbol } from '../element';
3
3
  import Spinner from '../feedback/Spinner.svelte';
4
4
  import type { IsosurfaceSettings, VolumetricData } from '../isosurface/types';
5
5
  import { type FullscreenToggleProp } from '../layout';
6
- import type { AnyStructure, BondEditMode, BondOrder, MeasureMode, StructureBond } from './';
6
+ import type { AnyStructure, BondEditMode, BondOrder, MeasureMode, StructureBond, StructureView } from './';
7
7
  import type { CellType, SymmetrySettings } from '../symmetry';
8
8
  import type { MoyoDataset } from '@spglib/moyo-wasm';
9
9
  import type { ComponentProps, Snippet } from 'svelte';
@@ -34,6 +34,8 @@ type $$ComponentProps = {
34
34
  bond_edit_mode?: BondEditMode;
35
35
  bond_edit_order?: BondOrder;
36
36
  info_pane_open?: boolean;
37
+ multi_view?: boolean;
38
+ views?: StructureView[];
37
39
  fullscreen_toggle?: FullscreenToggleProp;
38
40
  bottom_left?: Snippet<[{
39
41
  structure?: AnyStructure;
@@ -74,6 +76,6 @@ type $$ComponentProps = {
74
76
  on_camera_reset?: EventHandler;
75
77
  on_bonds_change?: (bonds: StructureBond[] | undefined) => void;
76
78
  } & Omit<ComponentProps<typeof StructureControls>, `children` | `onclose`> & Omit<HTMLAttributes<HTMLDivElement>, `children`>;
77
- declare const Structure: import("svelte").Component<$$ComponentProps, {}, "structure" | "height" | "width" | "dragover" | "color_scheme" | "fullscreen" | "wrapper" | "hovered" | "controls_open" | "bonds" | "sym_data" | "background_color" | "background_opacity" | "atom_color_config" | "hidden_elements" | "hidden_prop_vals" | "element_mapping" | "element_radius_overrides" | "site_radius_overrides" | "selected_sites" | "supercell_scaling" | "cell_type" | "loading" | "active_volume_idx" | "measured_sites" | "bond_edit_mode" | "scene_props" | "lattice_props" | "show_image_atoms" | "volumetric_data" | "isosurface_settings" | "png_dpi" | "highlighted_sites" | "hovered_site_idx" | "measure_mode" | "bond_edit_order" | "info_pane_open" | "enable_measure_mode" | "error_msg" | "performance_mode" | "displayed_structure" | "symmetry_settings">;
79
+ declare const Structure: import("svelte").Component<$$ComponentProps, {}, "height" | "width" | "dragover" | "color_scheme" | "fullscreen" | "wrapper" | "hovered" | "controls_open" | "structure" | "active_volume_idx" | "background_color" | "background_opacity" | "show_image_atoms" | "sym_data" | "lattice_props" | "measure_mode" | "selected_sites" | "measured_sites" | "bond_edit_mode" | "bond_edit_order" | "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "site_radius_overrides" | "atom_color_config" | "volumetric_data" | "isosurface_settings" | "scene_props" | "hovered_site_idx" | "bonds" | "element_mapping" | "supercell_scaling" | "cell_type" | "loading" | "png_dpi" | "highlighted_sites" | "info_pane_open" | "multi_view" | "enable_measure_mode" | "error_msg" | "performance_mode" | "displayed_structure" | "symmetry_settings">;
78
80
  type Structure = ReturnType<typeof Structure>;
79
81
  export default Structure;
@@ -0,0 +1,637 @@
1
+ <script lang="ts">
2
+ import type { ShowControlsProp } from '../controls'
3
+ import type { StructureCarouselItem } from './'
4
+ import GlassChip from '../overlays/GlassChip.svelte'
5
+ import { portal } from '../overlays/portal'
6
+ import { SvelteSet } from 'svelte/reactivity'
7
+ import Structure from './Structure.svelte'
8
+
9
+ type Layout = `horizontal` | `vertical`
10
+
11
+ interface Props {
12
+ items: StructureCarouselItem[]
13
+ layout?: Layout
14
+ height?: number
15
+ min_card_width?: number
16
+ max_rendered_items?: number
17
+ resizable?: boolean
18
+ show_controls?: ShowControlsProp
19
+ empty_message?: string
20
+ on_prefetch_more?: () => void
21
+ // Min delay between on_prefetch_more calls while the item count is
22
+ // unchanged (i.e. while a previous prefetch is still in flight).
23
+ prefetch_cooldown_ms?: number
24
+ // Host element to render the pager (‹ 1–3 / 64 ›) into, e.g. an embedding
25
+ // panel's title bar. When unset the pager floats over the carousel bottom.
26
+ pager_target?: HTMLElement | null
27
+ }
28
+
29
+ let {
30
+ items,
31
+ layout = `horizontal`,
32
+ height = 360,
33
+ min_card_width = 190,
34
+ max_rendered_items = 8,
35
+ resizable = false,
36
+ show_controls,
37
+ empty_message = `No structures`,
38
+ on_prefetch_more,
39
+ prefetch_cooldown_ms = 1000,
40
+ pager_target = undefined,
41
+ }: Props = $props()
42
+
43
+ let track: HTMLElement | undefined = $state()
44
+ let carousel: HTMLElement | undefined = $state()
45
+ let carousel_width = $state(0)
46
+ let carousel_height = $state(0)
47
+ let resized_height: number | null = $state(null)
48
+ let resized_width: number | null = $state(null)
49
+ let scroll_pos = $state(0) // along the scroll axis (left horizontally, top vertically)
50
+ let last_prefetch_ms = Number.NEGATIVE_INFINITY
51
+ let last_prefetch_item_count = -1
52
+
53
+ type ResizeDrag = {
54
+ axis: `height` | `width`
55
+ start_position: number
56
+ start_size: number
57
+ }
58
+ let resize_drag: ResizeDrag | undefined = $state()
59
+
60
+ const gap = 8
61
+ const min_resize_size = 150
62
+ // wheel delta for deltaMode=DOM_DELTA_LINE, in px per line (Firefox)
63
+ const wheel_line_height_px = 16
64
+ // px per arrow-key press when resizing via keyboard
65
+ const keyboard_resize_step_px = 16
66
+ const effective_height = $derived(
67
+ layout === `horizontal` && resizable ? (resized_height ?? height) : height,
68
+ )
69
+ const effective_width = $derived(
70
+ layout === `vertical` && resizable
71
+ ? (resized_width ?? (carousel_width > 0 ? carousel_width : min_card_width))
72
+ : min_card_width,
73
+ )
74
+ const card_width = $derived(layout === `horizontal` ? effective_height : effective_width)
75
+ const max_rendered = $derived(Math.max(1, Math.floor(max_rendered_items)))
76
+ const visible_item_count = $derived(Math.min(items.length, max_rendered))
77
+ // stride follows the scroll axis: card inline-size horizontally, block-size vertically
78
+ const item_stride = $derived((layout === `horizontal` ? card_width : effective_height) + gap)
79
+ const total_scroll_extent = $derived(
80
+ items.length === 0 ? 0 : items.length * item_stride - gap,
81
+ )
82
+ const track_width = $derived(
83
+ Math.max(1, visible_item_count) * card_width + Math.max(0, visible_item_count - 1) * gap,
84
+ )
85
+ const first_visible_idx = $derived(Math.max(0, Math.floor(scroll_pos / item_stride)))
86
+ // Cards per viewport page, measured along the scroll axis: inline-size for
87
+ // horizontal layout, block-size for vertical (mixing axes here previously
88
+ // made vertical prefetch thresholds depend on the carousel's WIDTH)
89
+ const measured_page_size = $derived.by(() => {
90
+ const viewport_size = layout === `horizontal` ? carousel_width : carousel_height
91
+ return viewport_size > 0 ? Math.floor((viewport_size + gap) / item_stride) : 1
92
+ })
93
+ const page_size = $derived(Math.max(1, Math.min(visible_item_count, measured_page_size)))
94
+ const max_page_start = $derived(Math.max(0, items.length - page_size))
95
+ const page_start = $derived(Math.min(max_page_start, first_visible_idx))
96
+ const page_end = $derived(Math.min(items.length, page_start + page_size))
97
+ // How many card ELEMENTS exist (canvas mount timing is live_ids' job below).
98
+ // Horizontal: the visible page plus one card per edge — an unaligned scroll
99
+ // position shows partial cards at BOTH edges, and measured_page_size floors,
100
+ // so up to page_size + 2 cards can intersect the viewport. Vertical tracks
101
+ // size their viewport to max_rendered cards (see max-block-size CSS), so
102
+ // there the page itself is the budget.
103
+ const rendered_count = $derived(
104
+ layout === `horizontal`
105
+ ? Math.min(items.length, page_size + 2, max_rendered)
106
+ : Math.min(items.length, max_rendered),
107
+ )
108
+ const window_start = $derived(
109
+ Math.min(Math.max(0, items.length - rendered_count), first_visible_idx),
110
+ )
111
+ const rendered_items = $derived(
112
+ items.slice(window_start, window_start + rendered_count).map((item, offset) => ({
113
+ item,
114
+ idx: window_start + offset,
115
+ })),
116
+ )
117
+ const carousel_style = $derived(
118
+ [
119
+ `--structure-carousel-columns: ${max_rendered}`,
120
+ `--structure-carousel-card-width: ${card_width}px`,
121
+ `--structure-carousel-height: ${effective_height}px`,
122
+ `--structure-carousel-gap: ${gap}px`,
123
+ `--structure-carousel-track-width: ${track_width}px`,
124
+ layout === `horizontal`
125
+ ? `inline-size: min(100%, var(--structure-carousel-track-width))`
126
+ : ``,
127
+ layout === `vertical` && resized_width ? `inline-size: ${resized_width}px` : ``,
128
+ resizable ? `max-inline-size: 100%` : ``,
129
+ resizable ? `min-block-size: ${min_resize_size}px` : ``,
130
+ ]
131
+ .filter(Boolean)
132
+ .join(`; `),
133
+ )
134
+ const track_style = $derived(
135
+ layout === `horizontal`
136
+ ? `overflow-x: auto; overflow-y: hidden; block-size: ${effective_height}px`
137
+ : `overflow-x: hidden; overflow-y: auto;`,
138
+ )
139
+ // Horizontal spacers/cards take their height from the track's CONTENT box
140
+ // (spacer min-block-size 100%, cards inset-block: 0) instead of a fixed
141
+ // px height: a classic (non-overlay) horizontal scrollbar shrinks that
142
+ // content box, and fixed-height cards would get their bottom edge — where
143
+ // the atom legend sits — clipped by exactly the scrollbar's height.
144
+ const spacer_style = $derived(
145
+ layout === `horizontal`
146
+ ? `inline-size: ${total_scroll_extent}px`
147
+ : `block-size: ${total_scroll_extent}px; inline-size: ${card_width}px`,
148
+ )
149
+ const card_style = (idx: number): string => {
150
+ const [x_shift, y_shift] =
151
+ layout === `horizontal` ? [idx * item_stride, 0] : [0, idx * item_stride]
152
+ const cross_size =
153
+ layout === `horizontal` ? `inset-block: 0` : `block-size: ${effective_height}px`
154
+ return `inline-size: ${card_width}px; ${cross_size}; transform: translate3d(${x_shift}px, ${y_shift}px, 0);`
155
+ }
156
+ const structure_scene_props = { gizmo: false }
157
+
158
+ const prefetch = (): void => {
159
+ const now = performance.now()
160
+ if (
161
+ !on_prefetch_more ||
162
+ (items.length === last_prefetch_item_count &&
163
+ now - last_prefetch_ms < prefetch_cooldown_ms)
164
+ ) {
165
+ return
166
+ }
167
+ last_prefetch_ms = now
168
+ last_prefetch_item_count = items.length
169
+ on_prefetch_more()
170
+ }
171
+
172
+ // Cards entering the render window mid-scroll render instantly as label
173
+ // shells and get their WebGL canvas (tracked in live_ids) later: mounting a
174
+ // Threlte scene (context creation + shader compile) takes long enough that a
175
+ // burst of simultaneous mounts stalls fast flings — the main source of
176
+ // scroll jank. While scrolling, at most one card is promoted to live per
177
+ // promote_interval_ms so structures still fill in mid-scroll without
178
+ // stacking several mounts into one frame; once scrolling settles, all
179
+ // remaining shells mount. Cards leaving the window always lose live status
180
+ // (window eviction destroys their canvas regardless) so re-entering cards go
181
+ // through the same throttle instead of burst-remounting from stale ids.
182
+ const scroll_settle_ms = 150
183
+ const promote_interval_ms = 200
184
+ let is_scrolling = $state(false)
185
+ let settle_timer: ReturnType<typeof setTimeout> | undefined
186
+ let last_promote_ms = Number.NEGATIVE_INFINITY
187
+ const live_ids = new SvelteSet<string>()
188
+ $effect(() => {
189
+ const window_ids = new Set(rendered_items.map(({ item }) => item.id))
190
+ for (const id of live_ids) if (!window_ids.has(id)) live_ids.delete(id)
191
+ if (!is_scrolling) {
192
+ for (const id of window_ids) live_ids.add(id)
193
+ } else {
194
+ const now = performance.now()
195
+ const entering = rendered_items.find(({ item }) => !live_ids.has(item.id))
196
+ if (!entering || now - last_promote_ms < promote_interval_ms) return
197
+ last_promote_ms = now
198
+ live_ids.add(entering.item.id)
199
+ }
200
+ })
201
+
202
+ const on_scroll = (): void => {
203
+ if (!track) return
204
+ is_scrolling = true
205
+ clearTimeout(settle_timer)
206
+ settle_timer = setTimeout(() => (is_scrolling = false), scroll_settle_ms)
207
+ scroll_pos = layout === `horizontal` ? track.scrollLeft : track.scrollTop
208
+ // first_visible_idx re-derives from the scroll offset just written above
209
+ const remaining_items = Math.max(0, items.length - first_visible_idx - page_size)
210
+ // Prefetch when within two pages (or one render window) of the end.
211
+ if (remaining_items <= Math.max(max_rendered, page_size * 2)) prefetch()
212
+ }
213
+
214
+ const on_wheel = (event: WheelEvent): void => {
215
+ if (!track || layout !== `horizontal` || event.ctrlKey || items.length <= page_size) return
216
+ const dominant_delta =
217
+ Math.abs(event.deltaX) > Math.abs(event.deltaY) ? event.deltaX : event.deltaY
218
+ if (dominant_delta === 0) return
219
+ const delta_scale =
220
+ event.deltaMode === WheelEvent.DOM_DELTA_LINE
221
+ ? wheel_line_height_px
222
+ : event.deltaMode === WheelEvent.DOM_DELTA_PAGE
223
+ ? track.clientWidth
224
+ : 1
225
+ const delta = dominant_delta * delta_scale
226
+ // unclamped above when max is 0 (track not yet measured); browser clamps anyway
227
+ const max_scroll_left = Math.max(0, track.scrollWidth - track.clientWidth) || Infinity
228
+ const next_scroll_left = Math.min(max_scroll_left, Math.max(0, track.scrollLeft + delta))
229
+ // already at the first/last card: leave the event alone so parent scroll
230
+ // containers can handle it instead of swallowing a no-op
231
+ if (next_scroll_left === track.scrollLeft) return
232
+ event.preventDefault()
233
+ event.stopPropagation()
234
+ track.scrollLeft = next_scroll_left
235
+ on_scroll()
236
+ }
237
+
238
+ const scroll_page = (direction: -1 | 1): void => {
239
+ if (!track) return
240
+ const target_start = Math.min(
241
+ max_page_start,
242
+ Math.max(0, first_visible_idx + direction * page_size),
243
+ )
244
+ track.scrollLeft = target_start * item_stride
245
+ on_scroll()
246
+ }
247
+
248
+ // Keyboard scrolling for the focused track: main-axis arrows move one card,
249
+ // PageUp/PageDown one viewport page, Home/End jump to the ends. Only keys
250
+ // targeting the track itself are handled — card content binds its own arrows
251
+ // (e.g. the info pane's site table) and must not be hijacked. Boundary no-ops
252
+ // fall through to the page, matching the wheel handler.
253
+ const on_track_keydown = (event: KeyboardEvent): void => {
254
+ if (!track || event.target !== track) return
255
+ const horizontal = layout === `horizontal`
256
+ const [back_key, fwd_key] = horizontal
257
+ ? [`ArrowLeft`, `ArrowRight`]
258
+ : [`ArrowUp`, `ArrowDown`]
259
+ const max_scroll = horizontal
260
+ ? Math.max(0, track.scrollWidth - track.clientWidth)
261
+ : Math.max(0, track.scrollHeight - track.clientHeight)
262
+ const current = horizontal ? track.scrollLeft : track.scrollTop
263
+ const deltas: Record<string, number> = {
264
+ [back_key]: -item_stride,
265
+ [fwd_key]: item_stride,
266
+ PageUp: -page_size * item_stride,
267
+ PageDown: page_size * item_stride,
268
+ Home: -current,
269
+ End: max_scroll - current,
270
+ }
271
+ const delta = deltas[event.key]
272
+ if (delta === undefined) return
273
+ const next_scroll = Math.min(max_scroll, Math.max(0, current + delta))
274
+ if (next_scroll === current) return // boundary: let the page handle it
275
+ event.preventDefault()
276
+ if (horizontal) track.scrollLeft = next_scroll
277
+ else track.scrollTop = next_scroll
278
+ on_scroll()
279
+ }
280
+
281
+ const stop_resize = (): void => {
282
+ resize_drag = undefined
283
+ window.removeEventListener(`pointermove`, on_resize_move)
284
+ window.removeEventListener(`pointerup`, stop_resize)
285
+ window.removeEventListener(`pointercancel`, stop_resize)
286
+ }
287
+
288
+ // Shared by pointer drags and keyboard resizes: clamps to the minimum size
289
+ // and (for width) to the parent container.
290
+ const set_resized_size = (axis: `height` | `width`, next_size: number): void => {
291
+ if (axis === `height`) {
292
+ resized_height = Math.max(min_resize_size, next_size)
293
+ } else {
294
+ const clamped = Math.max(min_card_width, next_size)
295
+ const parent_width = carousel?.parentElement?.clientWidth ?? Number.POSITIVE_INFINITY
296
+ resized_width = Math.min(clamped, parent_width > 0 ? parent_width : clamped)
297
+ }
298
+ }
299
+
300
+ const on_resize_move = (event: PointerEvent): void => {
301
+ if (!resize_drag) return
302
+ const position = resize_drag.axis === `height` ? event.clientY : event.clientX
303
+ set_resized_size(
304
+ resize_drag.axis,
305
+ resize_drag.start_size + position - resize_drag.start_position,
306
+ )
307
+ }
308
+
309
+ const resize_by = (delta: number): void => {
310
+ if (layout === `horizontal`) set_resized_size(`height`, effective_height + delta)
311
+ else set_resized_size(`width`, card_width + delta)
312
+ }
313
+
314
+ const on_resize_keydown = (event: KeyboardEvent): void => {
315
+ const [grow, shrink] =
316
+ layout === `horizontal` ? [`ArrowDown`, `ArrowUp`] : [`ArrowRight`, `ArrowLeft`]
317
+ if (event.key !== grow && event.key !== shrink) return
318
+ event.preventDefault()
319
+ resize_by(event.key === grow ? keyboard_resize_step_px : -keyboard_resize_step_px)
320
+ }
321
+
322
+ const start_resize = (event: PointerEvent): void => {
323
+ if (!resizable) return
324
+ event.preventDefault()
325
+ event.stopPropagation()
326
+ resize_drag =
327
+ layout === `horizontal`
328
+ ? { axis: `height`, start_position: event.clientY, start_size: effective_height }
329
+ : { axis: `width`, start_position: event.clientX, start_size: card_width }
330
+ ;(event.currentTarget as HTMLElement).setPointerCapture?.(event.pointerId)
331
+ window.addEventListener(`pointermove`, on_resize_move)
332
+ window.addEventListener(`pointerup`, stop_resize)
333
+ window.addEventListener(`pointercancel`, stop_resize)
334
+ }
335
+
336
+ // Capture before the nested Structure canvas sees the wheel. Orbit controls
337
+ // otherwise consume the event, and Svelte's normal bubble listener cannot
338
+ // reliably turn a mouse wheel into horizontal carousel movement.
339
+ $effect(() => {
340
+ const node = track
341
+ if (!node || layout !== `horizontal`) return
342
+ node.addEventListener(`wheel`, on_wheel, { capture: true, passive: false })
343
+ return () => node.removeEventListener(`wheel`, on_wheel, true)
344
+ })
345
+
346
+ $effect(() => () => {
347
+ stop_resize()
348
+ clearTimeout(settle_timer)
349
+ })
350
+ </script>
351
+
352
+ <section
353
+ bind:this={carousel}
354
+ class={[`structure-carousel`, layout, resizable && `resizable`, resize_drag && `resizing`]}
355
+ style={carousel_style}
356
+ bind:clientWidth={carousel_width}
357
+ bind:clientHeight={carousel_height}
358
+ >
359
+ {#if items.length === 0}
360
+ <p class="empty-carousel">{empty_message}</p>
361
+ {:else}
362
+ <!-- svelte-ignore a11y_no_noninteractive_tabindex, a11y_no_noninteractive_element_interactions
363
+ (focusable scroll region is a valid ARIA carousel pattern: arrows/PageUp/
364
+ PageDown/Home/End scroll it; see on_track_keydown) -->
365
+ <div
366
+ bind:this={track}
367
+ class="structure-carousel-track"
368
+ role="group"
369
+ aria-roledescription="carousel"
370
+ aria-label="Structure carousel"
371
+ tabindex="0"
372
+ onscroll={on_scroll}
373
+ onkeydown={on_track_keydown}
374
+ style={track_style}
375
+ >
376
+ <div class="structure-carousel-spacer" style={spacer_style}>
377
+ {#each rendered_items as { item, idx } (item.id)}
378
+ <article class="structure-card" style={card_style(idx)}>
379
+ <GlassChip class="card-info">
380
+ <strong title={item.label}>{item.label}</strong>
381
+ {#if item.subtitle}
382
+ <span>{item.subtitle}</span>
383
+ {/if}
384
+ </GlassChip>
385
+ {#if live_ids.has(item.id) || !is_scrolling}
386
+ <!-- Fill-the-card overrides for Structure's standalone defaults
387
+ (height 500px, min-width 300px — both larger than a card). -->
388
+ <Structure
389
+ structure={item.structure}
390
+ show_controls={show_controls ?? `never`}
391
+ scene_props={structure_scene_props}
392
+ allow_file_drop={false}
393
+ performance_mode="speed"
394
+ style="--struct-min-width: 0; --struct-height: 100%"
395
+ />
396
+ {/if}
397
+ </article>
398
+ {/each}
399
+ </div>
400
+ </div>
401
+ {#if layout === `horizontal` && items.length > page_size}
402
+ <nav
403
+ aria-label="Structure pages"
404
+ class="structure-carousel-pager"
405
+ class:portaled={Boolean(pager_target)}
406
+ {@attach portal(pager_target)}
407
+ >
408
+ <button
409
+ aria-label="Previous structures"
410
+ disabled={page_start === 0}
411
+ onclick={() => scroll_page(-1)}
412
+ type="button">‹</button
413
+ >
414
+ <span aria-live="polite">{page_start + 1}–{page_end} / {items.length}</span>
415
+ <button
416
+ aria-label="Next structures"
417
+ disabled={page_end >= items.length}
418
+ onclick={() => scroll_page(1)}
419
+ type="button">›</button
420
+ >
421
+ </nav>
422
+ {/if}
423
+ {/if}
424
+ {#if resizable}
425
+ <!-- svelte-ignore a11y_no_noninteractive_element_interactions (focusable separator is a valid ARIA pattern: arrow keys resize, pointer drags) -->
426
+ <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
427
+ <div
428
+ aria-label={layout === `horizontal` ? `Resize carousel height` : `Resize carousel width`}
429
+ aria-orientation={layout === `horizontal` ? `horizontal` : `vertical`}
430
+ aria-valuemin={layout === `horizontal` ? min_resize_size : min_card_width}
431
+ aria-valuemax={Math.round(
432
+ layout === `horizontal`
433
+ ? Math.max(effective_height, carousel_height)
434
+ : Math.max(card_width, carousel_width),
435
+ )}
436
+ aria-valuenow={Math.round(layout === `horizontal` ? effective_height : card_width)}
437
+ class={`structure-carousel-resize-handle ${layout}`}
438
+ onkeydown={on_resize_keydown}
439
+ onpointerdown={start_resize}
440
+ role="separator"
441
+ tabindex="0"
442
+ title={layout === `horizontal`
443
+ ? `Drag to resize carousel height`
444
+ : `Drag to resize carousel width`}
445
+ ></div>
446
+ {/if}
447
+ </section>
448
+
449
+ <style>
450
+ .structure-carousel {
451
+ position: relative;
452
+ min-inline-size: 0;
453
+ overflow: hidden;
454
+ }
455
+ .structure-carousel.horizontal {
456
+ block-size: var(--structure-carousel-height);
457
+ }
458
+ /* reserve a lane for the resize handle below (horizontal) / beside
459
+ (vertical) the cards so the grip never overlaps the structure canvases */
460
+ .structure-carousel.horizontal.resizable {
461
+ block-size: calc(var(--structure-carousel-height) + 8px);
462
+ }
463
+ .structure-carousel.vertical.resizable {
464
+ padding-inline-end: 10px;
465
+ }
466
+ .structure-carousel-track {
467
+ position: relative;
468
+ min-inline-size: 0;
469
+ scrollbar-width: thin;
470
+ overscroll-behavior: contain;
471
+ }
472
+ /* inset ring so it isn't clipped by the carousel's overflow: hidden */
473
+ .structure-carousel-track:focus-visible {
474
+ outline: 2px solid var(--accent-color, Highlight);
475
+ outline-offset: -2px;
476
+ }
477
+ .horizontal .structure-carousel-track {
478
+ inline-size: min(100%, var(--structure-carousel-track-width));
479
+ }
480
+ .vertical .structure-carousel-track {
481
+ max-block-size: calc(var(--structure-carousel-height) * var(--structure-carousel-columns));
482
+ }
483
+ .structure-carousel-spacer {
484
+ position: relative;
485
+ min-block-size: 100%;
486
+ }
487
+ .structure-card {
488
+ position: absolute;
489
+ inset-block-start: 0;
490
+ inset-inline-start: 0;
491
+ min-inline-size: 0;
492
+ overflow: hidden;
493
+ border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
494
+ border-radius: 6px;
495
+ background: var(--structure-carousel-card-bg, light-dark(#e9edf2, #343941));
496
+ contain: layout paint style;
497
+ }
498
+ /* element color chips stay visible at all times; the legend's extra chrome
499
+ is already hover-gated elsewhere (mode chevron via Structure's
500
+ viewer_active, cell-select via .structure:hover, chip × toggles via
501
+ .legend-item:hover) */
502
+ .structure-card :global(.atom-legend) {
503
+ z-index: 4;
504
+ max-inline-size: calc(100% - 8px);
505
+ justify-content: flex-end;
506
+ overflow: visible;
507
+ }
508
+ .structure-card :global(.element-legend sub) {
509
+ display: none;
510
+ }
511
+ /* frosted label/subtitle chip, same look as StructurePopup's stats block */
512
+ .structure-card :global(.card-info) {
513
+ --glass-chip-top: 4px;
514
+ --glass-chip-left: 4px;
515
+ --glass-chip-max-width: calc(100% - 8px);
516
+ --glass-chip-font-size: clamp(9px, calc(var(--structure-carousel-height) * 0.062), 12px);
517
+ line-height: 1.25;
518
+ pointer-events: none;
519
+ }
520
+ .structure-card :global(.card-info strong),
521
+ .structure-card :global(.card-info span) {
522
+ display: block;
523
+ overflow: hidden;
524
+ text-overflow: ellipsis;
525
+ white-space: nowrap;
526
+ }
527
+ .structure-card :global(.card-info span) {
528
+ color: light-dark(#5b6572, #b8c0cc);
529
+ font-size: 0.92em;
530
+ }
531
+ .structure-carousel-pager {
532
+ position: absolute;
533
+ z-index: 6;
534
+ /* own compositing layer, or WKWebView paints the canvas over this (see app.css) */
535
+ will-change: transform;
536
+ inset-block-end: 12px;
537
+ inset-inline-start: 50%;
538
+ display: flex;
539
+ align-items: center;
540
+ gap: 4px;
541
+ padding: 3px 5px;
542
+ border: 1px solid color-mix(in srgb, currentColor 18%, transparent);
543
+ border-radius: 999px;
544
+ background: color-mix(in srgb, light-dark(#f4f6f9, #1f232b) 88%, transparent);
545
+ box-shadow: 0 3px 12px color-mix(in srgb, black 20%, transparent);
546
+ color: light-dark(#404854, #d5dbe4);
547
+ font-size: 10px;
548
+ font-variant-numeric: tabular-nums;
549
+ transform: translateX(-50%);
550
+ }
551
+ /* hosted in a panel title bar instead of floating over the cards */
552
+ .structure-carousel-pager.portaled {
553
+ position: static;
554
+ gap: 1px;
555
+ padding: 0 2px;
556
+ background: transparent;
557
+ box-shadow: none;
558
+ transform: none;
559
+ }
560
+ .structure-carousel-pager.portaled button {
561
+ inline-size: 18px;
562
+ block-size: 18px;
563
+ }
564
+ .structure-carousel-pager button {
565
+ display: grid;
566
+ place-items: center;
567
+ inline-size: 22px;
568
+ block-size: 22px;
569
+ padding: 0 0 2px;
570
+ border: 0;
571
+ border-radius: 50%;
572
+ background: transparent;
573
+ color: inherit;
574
+ cursor: pointer;
575
+ font: inherit;
576
+ font-size: 16px;
577
+ line-height: 1;
578
+ }
579
+ .structure-carousel-pager button:hover:not(:disabled) {
580
+ color: var(--active-color, #6ea8ff);
581
+ }
582
+ .structure-carousel-pager button:disabled {
583
+ opacity: 0.3;
584
+ cursor: default;
585
+ }
586
+ .structure-carousel-resize-handle {
587
+ position: absolute;
588
+ z-index: 5;
589
+ background: transparent;
590
+ touch-action: none;
591
+ }
592
+ .structure-carousel-resize-handle::before {
593
+ position: absolute;
594
+ border-radius: 999px;
595
+ background: color-mix(in srgb, currentColor 32%, transparent);
596
+ content: '';
597
+ /* grip only shows while the carousel is hovered, focused, or resizing */
598
+ opacity: 0;
599
+ transition: opacity 0.15s ease;
600
+ }
601
+ .structure-carousel:hover .structure-carousel-resize-handle::before,
602
+ .structure-carousel-resize-handle:focus-visible::before,
603
+ .structure-carousel.resizing .structure-carousel-resize-handle::before {
604
+ opacity: 1;
605
+ }
606
+ .structure-carousel-resize-handle:hover::before,
607
+ .structure-carousel.resizing .structure-carousel-resize-handle::before {
608
+ background: color-mix(in srgb, var(--active-color, #6ea8ff) 75%, white 10%);
609
+ }
610
+ .structure-carousel-resize-handle.horizontal {
611
+ inset-block-end: 0;
612
+ inset-inline: 0;
613
+ block-size: 8px;
614
+ cursor: ns-resize;
615
+ }
616
+ .structure-carousel-resize-handle.horizontal::before {
617
+ inset-block-end: 2px;
618
+ inset-inline: 42%;
619
+ block-size: 2px;
620
+ }
621
+ .structure-carousel-resize-handle.vertical {
622
+ inset-block: 0;
623
+ inset-inline-end: 0;
624
+ inline-size: 10px;
625
+ cursor: ew-resize;
626
+ }
627
+ .structure-carousel-resize-handle.vertical::before {
628
+ inset-block: 42%;
629
+ inset-inline-end: 3px;
630
+ inline-size: 2px;
631
+ }
632
+ .empty-carousel {
633
+ margin: 0;
634
+ padding: 16px;
635
+ color: light-dark(#6b7482, #aeb6c2);
636
+ }
637
+ </style>
@@ -0,0 +1,19 @@
1
+ import type { ShowControlsProp } from '../controls';
2
+ import type { StructureCarouselItem } from './';
3
+ type Layout = `horizontal` | `vertical`;
4
+ interface Props {
5
+ items: StructureCarouselItem[];
6
+ layout?: Layout;
7
+ height?: number;
8
+ min_card_width?: number;
9
+ max_rendered_items?: number;
10
+ resizable?: boolean;
11
+ show_controls?: ShowControlsProp;
12
+ empty_message?: string;
13
+ on_prefetch_more?: () => void;
14
+ prefetch_cooldown_ms?: number;
15
+ pager_target?: HTMLElement | null;
16
+ }
17
+ declare const StructureCarousel: import("svelte").Component<Props, {}, "">;
18
+ type StructureCarousel = ReturnType<typeof StructureCarousel>;
19
+ export default StructureCarousel;