matterviz 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/dist/brillouin/BrillouinZone.svelte +68 -145
  2. package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -14
  3. package/dist/brillouin/BrillouinZoneExportPane.svelte +43 -96
  4. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  5. package/dist/brillouin/BrillouinZoneInfoPane.svelte +9 -32
  6. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
  7. package/dist/brillouin/BrillouinZoneScene.svelte +49 -203
  8. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +3 -23
  9. package/dist/brillouin/ReciprocalVectors.svelte +39 -0
  10. package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
  11. package/dist/brillouin/compute.d.ts +2 -0
  12. package/dist/brillouin/compute.js +80 -77
  13. package/dist/brillouin/geometry.d.ts +8 -0
  14. package/dist/brillouin/geometry.js +57 -0
  15. package/dist/brillouin/index.d.ts +2 -0
  16. package/dist/brillouin/index.js +2 -0
  17. package/dist/brillouin/types.d.ts +2 -2
  18. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
  19. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +100 -191
  20. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
  21. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +176 -464
  22. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
  23. package/dist/chempot-diagram/color.d.ts +3 -6
  24. package/dist/chempot-diagram/color.js +5 -5
  25. package/dist/chempot-diagram/compute.d.ts +3 -3
  26. package/dist/chempot-diagram/compute.js +3 -1
  27. package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
  28. package/dist/chempot-diagram/controls-state.svelte.js +42 -0
  29. package/dist/chempot-diagram/export.d.ts +47 -0
  30. package/dist/chempot-diagram/export.js +133 -0
  31. package/dist/chempot-diagram/index.d.ts +1 -0
  32. package/dist/chempot-diagram/index.js +1 -0
  33. package/dist/chempot-diagram/pointer.d.ts +0 -10
  34. package/dist/chempot-diagram/pointer.js +4 -4
  35. package/dist/chempot-diagram/types.d.ts +3 -3
  36. package/dist/colors/index.js +2 -2
  37. package/dist/composition/FormulaFilter.svelte +6 -5
  38. package/dist/composition/PieChart.svelte +5 -5
  39. package/dist/composition/chem-sys.js +3 -2
  40. package/dist/composition/format.js +3 -2
  41. package/dist/composition/parse.d.ts +0 -1
  42. package/dist/composition/parse.js +17 -19
  43. package/dist/controls.d.ts +1 -0
  44. package/dist/controls.js +0 -1
  45. package/dist/convex-hull/ConvexHull.svelte +8 -10
  46. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
  47. package/dist/convex-hull/ConvexHull2D.svelte +94 -175
  48. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  49. package/dist/convex-hull/ConvexHull3D.svelte +176 -680
  50. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  51. package/dist/convex-hull/ConvexHull4D.svelte +180 -680
  52. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  53. package/dist/convex-hull/ConvexHullChrome.svelte +268 -0
  54. package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
  55. package/dist/convex-hull/ConvexHullControls.svelte +88 -7
  56. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
  57. package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
  58. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
  59. package/dist/convex-hull/ConvexHullStats.svelte +29 -168
  60. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
  61. package/dist/convex-hull/ConvexHullTooltip.svelte +11 -2
  62. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
  63. package/dist/convex-hull/barycentric-coords.d.ts +2 -4
  64. package/dist/convex-hull/barycentric-coords.js +6 -33
  65. package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
  66. package/dist/convex-hull/canvas-interactions.svelte.js +278 -0
  67. package/dist/convex-hull/helpers.d.ts +39 -7
  68. package/dist/convex-hull/helpers.js +154 -69
  69. package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
  70. package/dist/convex-hull/hull-state.svelte.js +124 -0
  71. package/dist/convex-hull/index.d.ts +9 -7
  72. package/dist/convex-hull/index.js +7 -2
  73. package/dist/convex-hull/thermodynamics.js +91 -920
  74. package/dist/convex-hull/types.d.ts +12 -4
  75. package/dist/convex-hull/types.js +12 -0
  76. package/dist/coordination/CoordinationBarPlot.svelte +4 -11
  77. package/dist/element/BohrAtom.svelte +2 -1
  78. package/dist/element/ElementTile.svelte.d.ts +1 -1
  79. package/dist/element/index.d.ts +4 -0
  80. package/dist/element/index.js +18 -0
  81. package/dist/feedback/DragOverlay.svelte +3 -1
  82. package/dist/feedback/DragOverlay.svelte.d.ts +1 -0
  83. package/dist/feedback/StatusMessage.svelte +13 -3
  84. package/dist/fermi-surface/FermiSurface.svelte +67 -146
  85. package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -14
  86. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  87. package/dist/fermi-surface/FermiSurfaceScene.svelte +72 -224
  88. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
  89. package/dist/fermi-surface/compute.js +11 -10
  90. package/dist/fermi-surface/export.js +4 -15
  91. package/dist/fermi-surface/index.d.ts +0 -1
  92. package/dist/fermi-surface/index.js +0 -1
  93. package/dist/fermi-surface/parse.d.ts +1 -1
  94. package/dist/fermi-surface/parse.js +64 -75
  95. package/dist/fermi-surface/types.d.ts +2 -2
  96. package/dist/heatmap-matrix/HeatmapMatrix.svelte +55 -40
  97. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +4 -3
  98. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +3 -2
  99. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
  100. package/dist/heatmap-matrix/index.d.ts +3 -2
  101. package/dist/index.d.ts +1 -0
  102. package/dist/index.js +1 -0
  103. package/dist/io/ExportPane.svelte +166 -0
  104. package/dist/io/ExportPane.svelte.d.ts +17 -0
  105. package/dist/io/decompress.js +1 -2
  106. package/dist/io/export.d.ts +5 -1
  107. package/dist/io/export.js +32 -28
  108. package/dist/io/fetch.d.ts +2 -1
  109. package/dist/io/file-drop.d.ts +7 -0
  110. package/dist/io/file-drop.js +13 -0
  111. package/dist/io/index.d.ts +2 -0
  112. package/dist/io/index.js +10 -0
  113. package/dist/io/types.d.ts +13 -0
  114. package/dist/isosurface/parse.js +46 -44
  115. package/dist/labels.js +1 -1
  116. package/dist/layout/FullscreenButton.svelte +33 -0
  117. package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
  118. package/dist/layout/FullscreenToggle.svelte +8 -14
  119. package/dist/layout/ViewerChrome.svelte +116 -0
  120. package/dist/layout/ViewerChrome.svelte.d.ts +17 -0
  121. package/dist/layout/fullscreen.d.ts +4 -0
  122. package/dist/layout/fullscreen.svelte.d.ts +8 -0
  123. package/dist/layout/fullscreen.svelte.js +37 -0
  124. package/dist/layout/index.d.ts +3 -0
  125. package/dist/layout/index.js +3 -0
  126. package/dist/math.d.ts +7 -3
  127. package/dist/math.js +18 -21
  128. package/dist/overlays/index.d.ts +4 -0
  129. package/dist/periodic-table/PeriodicTable.svelte +9 -8
  130. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  131. package/dist/phase-diagram/PhaseDiagramControls.svelte +3 -2
  132. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
  133. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
  134. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
  135. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +47 -132
  136. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
  137. package/dist/phase-diagram/colors.js +1 -1
  138. package/dist/phase-diagram/parse.d.ts +2 -1
  139. package/dist/plot/bar/BarPlot.svelte +79 -316
  140. package/dist/plot/bar/BarPlot.svelte.d.ts +7 -15
  141. package/dist/plot/bar/BarPlotControls.svelte.d.ts +1 -1
  142. package/dist/plot/bar/SpacegroupBarPlot.svelte +2 -1
  143. package/dist/plot/box/BoxPlot.svelte +76 -246
  144. package/dist/plot/box/BoxPlot.svelte.d.ts +4 -3
  145. package/dist/plot/box/BoxPlotControls.svelte.d.ts +1 -1
  146. package/dist/plot/box/Violin.svelte.d.ts +1 -1
  147. package/dist/plot/box/box-plot.d.ts +3 -2
  148. package/dist/plot/box/box-plot.js +5 -2
  149. package/dist/plot/box/kde.d.ts +2 -1
  150. package/dist/plot/box/kde.js +4 -4
  151. package/dist/plot/core/auto-place.d.ts +1 -1
  152. package/dist/plot/core/auto-place.js +4 -1
  153. package/dist/plot/core/components/ColorBar.svelte +5 -5
  154. package/dist/plot/core/components/ColorBar.svelte.d.ts +5 -4
  155. package/dist/plot/core/components/Line.svelte +3 -2
  156. package/dist/plot/core/components/Line.svelte.d.ts +3 -2
  157. package/dist/plot/core/components/PlotAxis.svelte +2 -1
  158. package/dist/plot/core/components/PlotAxis.svelte.d.ts +2 -1
  159. package/dist/plot/core/components/PlotControls.svelte.d.ts +1 -1
  160. package/dist/plot/core/components/ReferenceLine3D.svelte +2 -2
  161. package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +4 -4
  162. package/dist/plot/core/components/ReferencePlane.svelte +2 -2
  163. package/dist/plot/core/components/ReferencePlane.svelte.d.ts +4 -4
  164. package/dist/plot/core/data-cleaning.js +18 -18
  165. package/dist/plot/core/fill-utils.d.ts +4 -3
  166. package/dist/plot/core/fill-utils.js +6 -3
  167. package/dist/plot/core/interactions.d.ts +5 -1
  168. package/dist/plot/core/interactions.js +14 -0
  169. package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
  170. package/dist/plot/core/pan-zoom.svelte.js +221 -0
  171. package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
  172. package/dist/plot/core/placed-tween.svelte.js +68 -0
  173. package/dist/plot/core/reference-line.d.ts +10 -10
  174. package/dist/plot/core/reference-line.js +6 -6
  175. package/dist/plot/core/scales.d.ts +17 -25
  176. package/dist/plot/core/scales.js +10 -8
  177. package/dist/plot/core/svg.d.ts +2 -1
  178. package/dist/plot/core/types.d.ts +18 -7
  179. package/dist/plot/core/utils/label-placement.d.ts +1 -1
  180. package/dist/plot/core/utils/label-placement.js +3 -3
  181. package/dist/plot/core/utils.d.ts +2 -1
  182. package/dist/plot/histogram/Histogram.svelte +77 -314
  183. package/dist/plot/histogram/HistogramControls.svelte.d.ts +1 -1
  184. package/dist/plot/sankey/Sankey.svelte +2 -5
  185. package/dist/plot/sankey/Sankey.svelte.d.ts +1 -1
  186. package/dist/plot/sankey/sankey.js +3 -1
  187. package/dist/plot/scatter/BinnedScatterPlot.svelte +3 -5
  188. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +4 -4
  189. package/dist/plot/scatter/ScatterPlot.svelte +160 -450
  190. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +7 -15
  191. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  192. package/dist/plot/scatter/binned-scatter-types.d.ts +4 -11
  193. package/dist/plot/scatter/index.d.ts +1 -1
  194. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +15 -26
  195. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +6 -14
  196. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +9 -10
  197. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +5 -5
  198. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +122 -121
  199. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +5 -14
  200. package/dist/plot/scatter-3d/Surface3D.svelte +6 -5
  201. package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +4 -3
  202. package/dist/plot/sunburst/Sunburst.svelte +16 -20
  203. package/dist/plot/sunburst/Sunburst.svelte.d.ts +4 -3
  204. package/dist/plot/sunburst/SunburstControls.svelte.d.ts +1 -1
  205. package/dist/plot/sunburst/sunburst.js +4 -1
  206. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  207. package/dist/sanitize.js +13 -2
  208. package/dist/scene/SceneCamera.svelte +62 -0
  209. package/dist/scene/SceneCamera.svelte.d.ts +19 -0
  210. package/dist/scene/bind-renderer.svelte.d.ts +2 -0
  211. package/dist/scene/bind-renderer.svelte.js +14 -0
  212. package/dist/scene/index.d.ts +4 -0
  213. package/dist/scene/index.js +5 -0
  214. package/dist/scene/props.js +52 -0
  215. package/dist/scene/types.d.ts +26 -0
  216. package/dist/scene/types.js +1 -0
  217. package/dist/settings.d.ts +14 -2
  218. package/dist/settings.js +59 -1
  219. package/dist/spectral/Bands.svelte +8 -7
  220. package/dist/spectral/Bands.svelte.d.ts +3 -2
  221. package/dist/spectral/BandsAndDos.svelte +22 -24
  222. package/dist/spectral/BrillouinBandsDos.svelte +3 -3
  223. package/dist/spectral/Dos.svelte +5 -4
  224. package/dist/spectral/Dos.svelte.d.ts +2 -1
  225. package/dist/spectral/helpers.d.ts +6 -6
  226. package/dist/spectral/helpers.js +43 -37
  227. package/dist/state.svelte.d.ts +0 -7
  228. package/dist/state.svelte.js +0 -6
  229. package/dist/structure/Arrow.svelte +2 -4
  230. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  231. package/dist/structure/CanvasTooltip.svelte +1 -0
  232. package/dist/structure/CellSelect.svelte +11 -3
  233. package/dist/structure/CellSelect.svelte.d.ts +2 -1
  234. package/dist/structure/Lattice.svelte +2 -2
  235. package/dist/structure/Structure.svelte +291 -355
  236. package/dist/structure/Structure.svelte.d.ts +5 -15
  237. package/dist/structure/StructureControls.svelte +217 -2
  238. package/dist/structure/StructureControls.svelte.d.ts +5 -3
  239. package/dist/structure/StructureExportPane.svelte +54 -156
  240. package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
  241. package/dist/structure/StructureInfoPane.svelte +5 -3
  242. package/dist/structure/StructureInfoPane.svelte.d.ts +5 -5
  243. package/dist/structure/StructureScene.svelte +365 -198
  244. package/dist/structure/StructureScene.svelte.d.ts +22 -20
  245. package/dist/structure/{label-placement.d.ts → atom-label-placement.d.ts} +3 -3
  246. package/dist/structure/{label-placement.js → atom-label-placement.js} +12 -2
  247. package/dist/structure/atom-properties.d.ts +1 -1
  248. package/dist/structure/atom-properties.js +11 -16
  249. package/dist/structure/bond-order-perception.js +2 -4
  250. package/dist/structure/bonding.d.ts +3 -0
  251. package/dist/structure/bonding.js +91 -48
  252. package/dist/structure/export.d.ts +24 -4
  253. package/dist/structure/export.js +64 -122
  254. package/dist/structure/index.d.ts +2 -0
  255. package/dist/structure/index.js +2 -0
  256. package/dist/structure/parse.d.ts +3 -2
  257. package/dist/structure/parse.js +333 -370
  258. package/dist/structure/partial-occupancy.d.ts +0 -1
  259. package/dist/structure/partial-occupancy.js +1 -1
  260. package/dist/structure/pbc.d.ts +1 -1
  261. package/dist/structure/pbc.js +186 -13
  262. package/dist/structure/polyhedra.d.ts +41 -0
  263. package/dist/structure/polyhedra.js +602 -0
  264. package/dist/structure/site.d.ts +4 -0
  265. package/dist/structure/site.js +1 -0
  266. package/dist/structure/supercell.js +3 -2
  267. package/dist/structure/validation.js +5 -6
  268. package/dist/symmetry/SymmetryElementControls.svelte +69 -0
  269. package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
  270. package/dist/symmetry/SymmetryElements.svelte +354 -0
  271. package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
  272. package/dist/symmetry/SymmetryStats.svelte +111 -6
  273. package/dist/symmetry/WyckoffTable.svelte +68 -7
  274. package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
  275. package/dist/symmetry/cell-transform.js +7 -14
  276. package/dist/symmetry/index.d.ts +14 -4
  277. package/dist/symmetry/index.js +301 -80
  278. package/dist/symmetry/spacegroups.d.ts +5 -1
  279. package/dist/symmetry/spacegroups.js +15 -1
  280. package/dist/symmetry/symmetry-elements.d.ts +33 -0
  281. package/dist/symmetry/symmetry-elements.js +521 -0
  282. package/dist/symmetry/wyckoff-db.d.ts +9 -0
  283. package/dist/symmetry/wyckoff-db.js +87 -0
  284. package/dist/table/HeatmapTable.svelte +4 -15
  285. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  286. package/dist/trajectory/Trajectory.svelte +58 -61
  287. package/dist/trajectory/Trajectory.svelte.d.ts +10 -22
  288. package/dist/trajectory/TrajectoryExportPane.svelte +15 -24
  289. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
  290. package/dist/trajectory/TrajectoryInfoPane.svelte +3 -2
  291. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
  292. package/dist/trajectory/constants.js +6 -2
  293. package/dist/trajectory/extract.js +17 -37
  294. package/dist/trajectory/format-detect.d.ts +0 -1
  295. package/dist/trajectory/format-detect.js +3 -9
  296. package/dist/trajectory/frame-reader.d.ts +0 -1
  297. package/dist/trajectory/frame-reader.js +62 -128
  298. package/dist/trajectory/helpers.d.ts +10 -2
  299. package/dist/trajectory/helpers.js +56 -36
  300. package/dist/trajectory/parse/ase.d.ts +9 -1
  301. package/dist/trajectory/parse/ase.js +47 -32
  302. package/dist/trajectory/parse/diagnostics.d.ts +3 -0
  303. package/dist/trajectory/parse/diagnostics.js +14 -0
  304. package/dist/trajectory/parse/index.d.ts +1 -1
  305. package/dist/trajectory/parse/index.js +54 -102
  306. package/dist/trajectory/parse/lammps.d.ts +0 -2
  307. package/dist/trajectory/parse/lammps.js +8 -6
  308. package/dist/trajectory/parse/pymatgen.d.ts +2 -0
  309. package/dist/trajectory/parse/pymatgen.js +74 -0
  310. package/dist/trajectory/parse/vasp.js +4 -3
  311. package/dist/trajectory/parse/xyz.d.ts +9 -21
  312. package/dist/trajectory/parse/xyz.js +28 -33
  313. package/dist/trajectory/plotting.d.ts +0 -1
  314. package/dist/trajectory/plotting.js +3 -100
  315. package/dist/utils.d.ts +1 -0
  316. package/dist/utils.js +1 -1
  317. package/dist/xrd/XrdPlot.svelte +14 -29
  318. package/dist/xrd/broadening.d.ts +2 -1
  319. package/dist/xrd/calc-xrd.js +6 -11
  320. package/dist/xrd/index.d.ts +2 -2
  321. package/package.json +29 -16
  322. package/dist/element/data.json +0 -11864
  323. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  324. package/dist/fermi-surface/marching-cubes.js +0 -2
  325. package/dist/plot/core/hover-lock.svelte.d.ts +0 -14
  326. package/dist/plot/core/hover-lock.svelte.js +0 -45
@@ -1,11 +1,13 @@
1
1
  import { get_electro_neg_formula } from '../composition';
2
2
  import { download } from '../io/fetch';
3
3
  import * as math from '../math';
4
+ import { is_plain_object } from '../utils';
4
5
  import { Color, Group, Matrix4, Mesh, MeshStandardMaterial, ShaderMaterial } from 'three';
5
6
  import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js';
6
7
  import { OBJExporter } from 'three/examples/jsm/exporters/OBJExporter.js';
7
- // Type guard to check if a material has a color property (duck typing for bundler compatibility)
8
- // Uses duck typing to work across different Three.js instances (Threlte vs vanilla Three.js)
8
+ // @internal exported only for tests - not part of the public API.
9
+ // Type guard to check if a material has a color property (duck typing for bundler
10
+ // compatibility across different Three.js instances - Threlte vs vanilla Three.js).
9
11
  export function has_color_property(mat) {
10
12
  if (!(`color` in mat))
11
13
  return false;
@@ -47,8 +49,9 @@ function convert_shader_to_standard(shader_mat) {
47
49
  standard_mat.name = shader_mat.name || `converted_shader_material`;
48
50
  return standard_mat;
49
51
  }
50
- // Extract bond gradient colors from geometry attributes for a specific instance
51
- // Returns midpoint color between start and end colors for the bond
52
+ // @internal exported only for tests - not part of the public API.
53
+ // Extract bond gradient colors from geometry attributes for a specific instance.
54
+ // Returns midpoint color between start and end colors for the bond.
52
55
  export function extract_bond_color_for_instance(geometry, instance_idx) {
53
56
  const color_start_attr = geometry.getAttribute(`instanceColorStart`);
54
57
  const color_end_attr = geometry.getAttribute(`instanceColorEnd`);
@@ -70,8 +73,10 @@ export function extract_bond_color_for_instance(geometry, instance_idx) {
70
73
  const [mid_r, mid_g, mid_b] = math.scale(math.add(start_rgb, end_rgb), 0.5);
71
74
  return new Color(mid_r, mid_g, mid_b);
72
75
  }
73
- // Remove custom/non-standard attributes from geometry that cause export issues
74
- // Standard GLTF attributes: position, normal, tangent, texcoord_N, color_N, joints_N, weights_N
76
+ // @internal exported only for tests - not part of the public API.
77
+ // Remove custom/non-standard attributes from geometry that cause export issues.
78
+ // Standard GLTF attributes: position, normal, tangent, texcoord_N, color_N, joints_N,
79
+ // weights_N.
75
80
  export function clean_geometry_for_export(geometry) {
76
81
  const standard_attrs = new Set([
77
82
  `position`,
@@ -98,7 +103,8 @@ export function clean_geometry_for_export(geometry) {
98
103
  geometry.deleteAttribute(attr_name);
99
104
  }
100
105
  }
101
- // Generate MTL (Wavefront Material) content from scene materials
106
+ // @internal exported only for tests - not part of the public API.
107
+ // Generate MTL (Wavefront Material) content from scene materials.
102
108
  export function generate_mtl_content(scene) {
103
109
  const lines = [`# MTL file generated by MatterViz`, ``];
104
110
  const processed_materials = new Set();
@@ -341,6 +347,17 @@ export function create_structure_filename(structure, extension) {
341
347
  const base_name = parts.length > 0 ? parts.join(`-`) : `structure`;
342
348
  return `${base_name}.${extension}`;
343
349
  }
350
+ // First species' element of a site, or `X` when the site has no species
351
+ const site_element = (site) => site.species?.[0]?.element || `X`;
352
+ // Fractional coordinates from abc, falling back to converting xyz; throws when neither
353
+ // is available. idx (when given) is included in the error message.
354
+ function get_frac_coords(site, cart_to_frac, idx) {
355
+ if (Array.isArray(site.abc) && site.abc.length >= 3)
356
+ return site.abc.slice(0, 3);
357
+ if (site.xyz?.length >= 3 && cart_to_frac)
358
+ return cart_to_frac(site.xyz.slice(0, 3));
359
+ throw new Error(`No valid coordinates found for site${idx === undefined ? `` : ` ${idx}`}`);
360
+ }
344
361
  // Generate XYZ content string without saving
345
362
  export function structure_to_xyz_str(structure) {
346
363
  if (!structure?.sites)
@@ -358,8 +375,7 @@ export function structure_to_xyz_str(structure) {
358
375
  // Include extended XYZ lattice information when available so round-trips preserve lattice
359
376
  if (`lattice` in structure && structure.lattice?.matrix?.length === 3) {
360
377
  const lattice_values = structure.lattice.matrix
361
- .flat()
362
- .map((value) => (Number.isFinite(value) ? value : 0).toFixed(8))
378
+ .flatMap((row) => row.map((value) => (Number.isFinite(value) ? value : 0).toFixed(8)))
363
379
  .join(` `);
364
380
  comment_parts.push(`Lattice="${lattice_values}"`);
365
381
  }
@@ -371,14 +387,7 @@ export function structure_to_xyz_str(structure) {
371
387
  : null;
372
388
  // Atom lines: element symbol followed by x, y, z coordinates
373
389
  for (const site of structure.sites) {
374
- // Extract element symbol from species
375
- let element_symbol = `X`; // default fallback
376
- if (site.species && Array.isArray(site.species) && site.species.length > 0) {
377
- // species is an array of Species objects with element property
378
- const first_species = site.species[0];
379
- if (first_species && `element` in first_species && first_species.element)
380
- element_symbol = first_species.element;
381
- }
390
+ const element_symbol = site_element(site);
382
391
  // Get coordinates - prefer xyz; fallback to abc (converted to cartesian if lattice available)
383
392
  let coords;
384
393
  if (site.xyz && Array.isArray(site.xyz) && site.xyz.length >= 3) {
@@ -464,11 +473,8 @@ export function structure_to_cif_str(structure) {
464
473
  lines.push(`_cell_angle_gamma ${lattice.gamma.toFixed(6)}`);
465
474
  }
466
475
  // Space group information
467
- if (`symmetry` in structure &&
468
- structure.symmetry &&
469
- typeof structure.symmetry === `object`) {
470
- const symmetry = structure.symmetry;
471
- const { space_group_number, space_group_symbol } = symmetry;
476
+ if (`symmetry` in structure && is_plain_object(structure.symmetry)) {
477
+ const { space_group_number, space_group_symbol } = structure.symmetry;
472
478
  if (typeof space_group_symbol === `string` && space_group_symbol) {
473
479
  // Quote H-M symbols: their spaces (e.g. 'F m -3 m') would break CIF tokenization
474
480
  lines.push(`_space_group_name_H-M_alt '${space_group_symbol}'`);
@@ -498,16 +504,7 @@ export function structure_to_cif_str(structure) {
498
504
  const site = structure.sites[idx];
499
505
  if (!site)
500
506
  continue; // Skip if site is undefined
501
- // Get fractional coordinates
502
- let frac_coords;
503
- if (Array.isArray(site.abc) && site.abc.length >= 3) {
504
- frac_coords = site.abc.slice(0, 3);
505
- }
506
- else if (site.xyz?.length >= 3 && cart_to_frac) {
507
- frac_coords = cart_to_frac(site.xyz);
508
- }
509
- else
510
- throw new Error(`No valid coordinates found for site ${idx}`);
507
+ const frac_coords = get_frac_coords(site, cart_to_frac, idx);
511
508
  const coords_str = frac_coords.map((coord) => coord.toFixed(8)).join(` `);
512
509
  const species_list = site.species?.length ? site.species : [{ element: `X`, occu: 1 }];
513
510
  for (const [spec_idx, species] of species_list.entries()) {
@@ -548,27 +545,20 @@ export function structure_to_poscar_str(structure) {
548
545
  else {
549
546
  throw new Error(`No valid lattice matrix for POSCAR export`);
550
547
  }
551
- // Count atoms by element
552
- const element_counts = new Map();
553
- const element_symbols = [];
548
+ // Group sites by element in one pass, preserving first-appearance element order
549
+ const sites_by_element = new Map();
554
550
  for (const site of structure.sites) {
555
- let element_symbol = `X`; // default fallback
556
- if (site.species && Array.isArray(site.species) && site.species.length > 0) {
557
- const first_species = site.species[0];
558
- if (first_species && `element` in first_species && first_species.element) {
559
- element_symbol = first_species.element;
560
- }
561
- }
562
- if (!element_counts.has(element_symbol)) {
563
- element_counts.set(element_symbol, 0);
564
- element_symbols.push(element_symbol);
565
- }
566
- element_counts.set(element_symbol, Number(element_counts.get(element_symbol)) + 1);
551
+ const element_symbol = site_element(site);
552
+ const group = sites_by_element.get(element_symbol);
553
+ if (group)
554
+ group.push(site);
555
+ else
556
+ sites_by_element.set(element_symbol, [site]);
567
557
  }
568
558
  // Element symbols line
569
- lines.push(element_symbols.join(` `));
559
+ lines.push([...sites_by_element.keys()].join(` `));
570
560
  // Atom counts line
571
- lines.push(element_symbols.map((el) => element_counts.get(el)).join(` `));
561
+ lines.push([...sites_by_element.values()].map((group) => group.length).join(` `));
572
562
  // Check if any site has selective dynamics
573
563
  const has_selective_dynamics = structure.sites.some((site) => site.properties?.selective_dynamics);
574
564
  if (has_selective_dynamics) {
@@ -579,38 +569,19 @@ export function structure_to_poscar_str(structure) {
579
569
  // Cache inverse transpose for Cartesian→fractional conversion (avoids recomputing per site)
580
570
  const cart_to_frac = lattice.matrix?.length === 3 ? math.create_cart_to_frac(lattice.matrix) : null;
581
571
  // Atom coordinates grouped by element
582
- for (const element_symbol of element_symbols) {
583
- for (const site of structure.sites) {
584
- let site_element = `X`;
585
- if (site.species && Array.isArray(site.species) && site.species.length > 0) {
586
- const first_species = site.species[0];
587
- if (first_species && `element` in first_species && first_species.element) {
588
- site_element = first_species.element;
589
- }
590
- }
591
- if (site_element === element_symbol) {
592
- // Get fractional coordinates
593
- let frac_coords;
594
- if (site.abc && Array.isArray(site.abc) && site.abc.length >= 3) {
595
- frac_coords = site.abc.slice(0, 3);
596
- }
597
- else if (site.xyz?.length >= 3 && cart_to_frac) {
598
- frac_coords = cart_to_frac(site.xyz.slice(0, 3));
599
- }
600
- else {
601
- throw new Error(`No valid coordinates found for site`);
602
- }
603
- let selective_dynamics_str = ``;
604
- if (has_selective_dynamics) {
605
- const sel_dyn = (site.properties?.selective_dynamics ?? [
606
- true,
607
- true,
608
- true,
609
- ]);
610
- selective_dynamics_str = ` ${sel_dyn[0] ? `T` : `F`} ${sel_dyn[1] ? `T` : `F`} ${sel_dyn[2] ? `T` : `F`}`;
611
- }
612
- lines.push(`${frac_coords[0].toFixed(8)} ${frac_coords[1].toFixed(8)} ${frac_coords[2].toFixed(8)}${selective_dynamics_str}`);
572
+ for (const group of sites_by_element.values()) {
573
+ for (const site of group) {
574
+ const frac_coords = get_frac_coords(site, cart_to_frac);
575
+ let selective_dynamics_str = ``;
576
+ if (has_selective_dynamics) {
577
+ const sel_dyn = (site.properties?.selective_dynamics ?? [
578
+ true,
579
+ true,
580
+ true,
581
+ ]);
582
+ selective_dynamics_str = ` ${sel_dyn[0] ? `T` : `F`} ${sel_dyn[1] ? `T` : `F`} ${sel_dyn[2] ? `T` : `F`}`;
613
583
  }
584
+ lines.push(`${frac_coords[0].toFixed(8)} ${frac_coords[1].toFixed(8)} ${frac_coords[2].toFixed(8)}${selective_dynamics_str}`);
614
585
  }
615
586
  }
616
587
  return lines.join(`\n`);
@@ -621,51 +592,22 @@ export function structure_to_json_str(structure) {
621
592
  throw new Error(`No structure to export`);
622
593
  return JSON.stringify(structure, null, 2);
623
594
  }
624
- // Export structure as CIF format
625
- export function export_structure_as_cif(structure) {
626
- try {
627
- const content = structure_to_cif_str(structure);
628
- const filename = create_structure_filename(structure, `cif`);
629
- download(content, filename, `chemical/x-cif`);
630
- }
631
- catch (error) {
632
- console.error(`Failed to export CIF:`, error);
633
- }
634
- }
635
- // Export structure as VASP POSCAR format
636
- export function export_structure_as_poscar(structure) {
637
- try {
638
- const content = structure_to_poscar_str(structure);
639
- const filename = create_structure_filename(structure, `poscar`);
640
- download(content, filename, `text/plain`);
641
- }
642
- catch (error) {
643
- console.error(`Failed to export POSCAR:`, error);
644
- }
645
- }
646
- // Export structure as XYZ format. Format specification:
647
- // - Line 1: Number of atoms
648
- // - Line 2: Comment line (structure ID, formula, etc.)
649
- // - Remaining lines: Element symbol followed by x, y, z coordinates (in Angstrom)
650
- export function export_structure_as_xyz(structure) {
651
- try {
652
- const xyz_content = structure_to_xyz_str(structure);
653
- const filename = create_structure_filename(structure, `xyz`);
654
- download(xyz_content, filename, `text/plain`);
655
- }
656
- catch (error) {
657
- console.error(`Error exporting XYZ:`, error);
658
- }
659
- }
660
- // Export structure in pymatgen JSON format
661
- export function export_structure_as_json(structure) {
595
+ // Text export formats: serializer + file extension + MIME type per format
596
+ export const STRUCT_TEXT_FORMATS = {
597
+ json: { to_str: structure_to_json_str, ext: `json`, mime: `application/json` },
598
+ xyz: { to_str: structure_to_xyz_str, ext: `xyz`, mime: `text/plain` },
599
+ cif: { to_str: structure_to_cif_str, ext: `cif`, mime: `chemical/x-cif` },
600
+ poscar: { to_str: structure_to_poscar_str, ext: `poscar`, mime: `text/plain` },
601
+ };
602
+ // Serialize structure in the given text format and trigger a browser download
603
+ export function export_structure_as(fmt, structure) {
604
+ const { to_str, ext, mime } = STRUCT_TEXT_FORMATS[fmt];
662
605
  try {
663
- const data = structure_to_json_str(structure);
664
- const filename = create_structure_filename(structure, `json`);
665
- download(data, filename, `application/json`);
606
+ const content = to_str(structure);
607
+ download(content, create_structure_filename(structure, ext), mime);
666
608
  }
667
609
  catch (error) {
668
- console.error(`Error exporting JSON:`, error);
610
+ console.error(`Failed to export ${fmt.toUpperCase()}:`, error);
669
611
  }
670
612
  }
671
613
  // Export Three.js scene as GLB (binary GLTF) file
@@ -15,6 +15,8 @@ export { default as CanvasTooltip } from './CanvasTooltip.svelte';
15
15
  export { default as Cylinder } from './Cylinder.svelte';
16
16
  export { default as Lattice } from './Lattice.svelte';
17
17
  export * from './pbc';
18
+ export * from './polyhedra';
19
+ export * from './site';
18
20
  export { default as Structure } from './Structure.svelte';
19
21
  export { default as StructureControls } from './StructureControls.svelte';
20
22
  export { default as StructureExportPane } from './StructureExportPane.svelte';
@@ -10,6 +10,8 @@ export { default as CanvasTooltip } from './CanvasTooltip.svelte';
10
10
  export { default as Cylinder } from './Cylinder.svelte';
11
11
  export { default as Lattice } from './Lattice.svelte';
12
12
  export * from './pbc';
13
+ export * from './polyhedra';
14
+ export * from './site';
13
15
  export { default as Structure } from './Structure.svelte';
14
16
  export { default as StructureControls } from './StructureControls.svelte';
15
17
  export { default as StructureExportPane } from './StructureExportPane.svelte';
@@ -54,9 +54,10 @@ export declare function parse_xyz(content: string): ParsedStructure | null;
54
54
  export declare function parse_cif(content: string, wrap_fractional_coords?: boolean, strict?: boolean): ParsedStructure | null;
55
55
  export type CellType = `primitive_cell` | `unit_cell` | `supercell` | `phonon_primitive_cell` | `phonon_supercell` | `auto`;
56
56
  export declare function parse_phonopy_yaml(content: string, cell_type?: CellType): ParsedStructure | null;
57
+ export declare function is_parsed_structure(obj: unknown): obj is ParsedStructure;
57
58
  export declare function normalize_fractional_coords(structure: ParsedStructure): ParsedStructure;
58
- export declare function parse_structure_file(content: string, filename?: string): ParsedStructure | null;
59
- export declare function parse_any_structure(content: string, filename: string): AnyStructure | null;
59
+ export declare function parse_structure_file(content: string, filename?: string): ParsedStructure;
60
+ export declare function parse_any_structure(content: string, filename: string): AnyStructure;
60
61
  export declare function parse_optimade_json(content: string): ParsedStructure | null;
61
62
  export declare function parse_optimade_from_raw(raw: unknown): ParsedStructure | null;
62
63
  export declare function is_optimade_json(content: string): boolean;