matterviz 0.3.5 → 0.3.6

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 (855) hide show
  1. package/.vscode/launch.json +13 -0
  2. package/.vscodeignore +7 -0
  3. package/dist/assets/STLExporter-BpTH3YHE.js +8 -0
  4. package/dist/assets/browser-DdDecX_W.js +1 -0
  5. package/dist/assets/export-qgn-H9y6.js +2 -0
  6. package/dist/assets/main-DiKYzti2.css +1 -0
  7. package/dist/assets/moyo_wasm_bg-0ocwg7xY.wasm +0 -0
  8. package/dist/extension.js +31293 -0
  9. package/dist/src/lib/FilePicker.svelte +360 -0
  10. package/dist/src/lib/MillerIndexInput.svelte +66 -0
  11. package/dist/src/lib/api/mp.ts +26 -0
  12. package/dist/src/lib/api/optimade.ts +204 -0
  13. package/dist/src/lib/brillouin/BrillouinZone.svelte +549 -0
  14. package/dist/src/lib/brillouin/BrillouinZoneControls.svelte +144 -0
  15. package/dist/src/lib/brillouin/BrillouinZoneExportPane.svelte +146 -0
  16. package/dist/src/lib/brillouin/BrillouinZoneInfoPane.svelte +146 -0
  17. package/dist/src/lib/brillouin/BrillouinZoneScene.svelte +476 -0
  18. package/dist/src/lib/brillouin/BrillouinZoneTooltip.svelte +92 -0
  19. package/dist/src/lib/brillouin/compute.ts +529 -0
  20. package/dist/src/lib/brillouin/index.ts +8 -0
  21. package/dist/src/lib/brillouin/types.ts +51 -0
  22. package/dist/src/lib/chempot-diagram/ChemPotDiagram.svelte +327 -0
  23. package/dist/src/lib/chempot-diagram/ChemPotDiagram2D.svelte +846 -0
  24. package/dist/src/lib/chempot-diagram/ChemPotDiagram3D.svelte +3193 -0
  25. package/dist/src/lib/chempot-diagram/async-compute.svelte.ts +94 -0
  26. package/dist/src/lib/chempot-diagram/chempot-worker.ts +11 -0
  27. package/dist/src/lib/chempot-diagram/color.ts +42 -0
  28. package/dist/src/lib/chempot-diagram/compute.ts +1014 -0
  29. package/dist/src/lib/chempot-diagram/index.ts +6 -0
  30. package/dist/src/lib/chempot-diagram/pointer.ts +56 -0
  31. package/dist/src/lib/chempot-diagram/temperature.ts +77 -0
  32. package/dist/src/lib/chempot-diagram/types.ts +130 -0
  33. package/dist/src/lib/colors/index.ts +249 -0
  34. package/dist/src/lib/composition/BarChart.svelte +297 -0
  35. package/dist/src/lib/composition/BubbleChart.svelte +218 -0
  36. package/dist/src/lib/composition/Composition.svelte +165 -0
  37. package/dist/src/lib/composition/Formula.svelte +268 -0
  38. package/dist/src/lib/composition/FormulaFilter.svelte +1257 -0
  39. package/dist/src/lib/composition/PieChart.svelte +323 -0
  40. package/dist/src/lib/composition/format.ts +155 -0
  41. package/dist/src/lib/composition/index.ts +37 -0
  42. package/dist/src/lib/composition/parse.ts +605 -0
  43. package/dist/src/lib/constants.ts +134 -0
  44. package/dist/src/lib/controls.ts +42 -0
  45. package/dist/src/lib/convex-hull/ConvexHull.svelte +157 -0
  46. package/dist/src/lib/convex-hull/ConvexHull2D.svelte +825 -0
  47. package/dist/src/lib/convex-hull/ConvexHull3D.svelte +1801 -0
  48. package/dist/src/lib/convex-hull/ConvexHull4D.svelte +1398 -0
  49. package/dist/src/lib/convex-hull/ConvexHullControls.svelte +535 -0
  50. package/dist/src/lib/convex-hull/ConvexHullInfoPane.svelte +125 -0
  51. package/dist/src/lib/convex-hull/ConvexHullStats.svelte +929 -0
  52. package/dist/src/lib/convex-hull/ConvexHullTooltip.svelte +131 -0
  53. package/dist/src/lib/convex-hull/GasPressureControls.svelte +247 -0
  54. package/dist/src/lib/convex-hull/StructurePopup.svelte +151 -0
  55. package/dist/src/lib/convex-hull/TemperatureSlider.svelte +140 -0
  56. package/dist/src/lib/convex-hull/barycentric-coords.ts +246 -0
  57. package/dist/src/lib/convex-hull/demo-temperature.ts +63 -0
  58. package/dist/src/lib/convex-hull/gas-thermodynamics.ts +405 -0
  59. package/dist/src/lib/convex-hull/helpers.ts +932 -0
  60. package/dist/src/lib/convex-hull/index.ts +202 -0
  61. package/dist/src/lib/convex-hull/thermodynamics.ts +2192 -0
  62. package/dist/src/lib/convex-hull/types.ts +267 -0
  63. package/dist/src/lib/coordination/CoordinationBarPlot.svelte +311 -0
  64. package/dist/src/lib/coordination/calc-coordination.ts +93 -0
  65. package/dist/src/lib/coordination/index.ts +9 -0
  66. package/dist/src/lib/effects.svelte.ts +48 -0
  67. package/dist/src/lib/element/BohrAtom.svelte +147 -0
  68. package/dist/src/lib/element/ElementHeading.svelte +26 -0
  69. package/dist/src/lib/element/ElementPhoto.svelte +57 -0
  70. package/dist/src/lib/element/ElementStats.svelte +80 -0
  71. package/dist/src/lib/element/ElementTile.svelte +484 -0
  72. package/dist/src/lib/element/data.json.gz.d.ts +4 -0
  73. package/dist/src/lib/element/data.ts +14 -0
  74. package/dist/src/lib/element/index.ts +8 -0
  75. package/dist/src/lib/element/types.ts +62 -0
  76. package/dist/src/lib/feedback/ClickFeedback.svelte +58 -0
  77. package/dist/src/lib/feedback/DragOverlay.svelte +42 -0
  78. package/dist/src/lib/feedback/index.ts +4 -0
  79. package/dist/src/lib/fermi-surface/FermiSlice.svelte +189 -0
  80. package/dist/src/lib/fermi-surface/FermiSurface.svelte +600 -0
  81. package/dist/src/lib/fermi-surface/FermiSurfaceControls.svelte +448 -0
  82. package/dist/src/lib/fermi-surface/FermiSurfaceScene.svelte +794 -0
  83. package/dist/src/lib/fermi-surface/FermiSurfaceTooltip.svelte +111 -0
  84. package/dist/src/lib/fermi-surface/compute.ts +728 -0
  85. package/dist/src/lib/fermi-surface/constants.ts +32 -0
  86. package/dist/src/lib/fermi-surface/export.ts +64 -0
  87. package/dist/src/lib/fermi-surface/index.ts +14 -0
  88. package/dist/src/lib/fermi-surface/marching-cubes.ts +3 -0
  89. package/dist/src/lib/fermi-surface/parse.ts +574 -0
  90. package/dist/src/lib/fermi-surface/symmetry.ts +56 -0
  91. package/dist/src/lib/fermi-surface/types.ts +159 -0
  92. package/dist/src/lib/heatmap-matrix/HeatmapMatrix.svelte +1545 -0
  93. package/dist/src/lib/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
  94. package/dist/src/lib/heatmap-matrix/index.ts +167 -0
  95. package/dist/src/lib/heatmap-matrix/shared.ts +7 -0
  96. package/dist/src/lib/icons.ts +650 -0
  97. package/dist/src/lib/index.ts +61 -0
  98. package/dist/src/lib/io/decompress.ts +92 -0
  99. package/dist/src/lib/io/export.ts +385 -0
  100. package/dist/src/lib/io/fetch.ts +46 -0
  101. package/dist/src/lib/io/file-drop.ts +51 -0
  102. package/dist/src/lib/io/index.ts +7 -0
  103. package/dist/src/lib/io/is-binary.ts +24 -0
  104. package/dist/src/lib/io/types.ts +8 -0
  105. package/dist/src/lib/io/url-drop.ts +141 -0
  106. package/dist/src/lib/isosurface/Isosurface.svelte +285 -0
  107. package/dist/src/lib/isosurface/IsosurfaceControls.svelte +277 -0
  108. package/dist/src/lib/isosurface/index.ts +7 -0
  109. package/dist/src/lib/isosurface/parse.ts +656 -0
  110. package/dist/src/lib/isosurface/slice.ts +175 -0
  111. package/dist/src/lib/isosurface/types.ts +309 -0
  112. package/dist/src/lib/labels.ts +320 -0
  113. package/dist/src/lib/layout/FullscreenToggle.svelte +50 -0
  114. package/dist/src/lib/layout/InfoCard.svelte +120 -0
  115. package/dist/src/lib/layout/InfoTag.svelte +185 -0
  116. package/dist/src/lib/layout/PropertyFilter.svelte +246 -0
  117. package/dist/src/lib/layout/SettingsSection.svelte +148 -0
  118. package/dist/src/lib/layout/SubpageGrid.svelte +82 -0
  119. package/dist/src/lib/layout/fullscreen.ts +65 -0
  120. package/dist/src/lib/layout/index.ts +11 -0
  121. package/dist/src/lib/layout/json-tree/JsonNode.svelte +548 -0
  122. package/dist/src/lib/layout/json-tree/JsonTree.svelte +1230 -0
  123. package/dist/src/lib/layout/json-tree/JsonValue.svelte +334 -0
  124. package/dist/src/lib/layout/json-tree/index.ts +3 -0
  125. package/dist/src/lib/layout/json-tree/types.ts +126 -0
  126. package/dist/src/lib/layout/json-tree/utils.ts +682 -0
  127. package/dist/src/lib/marching-cubes.ts +614 -0
  128. package/dist/src/lib/math.ts +1081 -0
  129. package/dist/src/lib/overlays/ContextMenu.svelte +162 -0
  130. package/dist/src/lib/overlays/CopyButton.svelte +45 -0
  131. package/dist/src/lib/overlays/DragControlTab.svelte +98 -0
  132. package/dist/src/lib/overlays/DraggablePane.svelte +487 -0
  133. package/dist/src/lib/overlays/InfoPaneCards.svelte +149 -0
  134. package/dist/src/lib/overlays/index.ts +3 -0
  135. package/dist/src/lib/periodic-table/PeriodicTable.svelte +469 -0
  136. package/dist/src/lib/periodic-table/PeriodicTableControls.svelte +557 -0
  137. package/dist/src/lib/periodic-table/PropertySelect.svelte +37 -0
  138. package/dist/src/lib/periodic-table/index.ts +12 -0
  139. package/dist/src/lib/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +1086 -0
  140. package/dist/src/lib/phase-diagram/PhaseDiagramControls.svelte +444 -0
  141. package/dist/src/lib/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
  142. package/dist/src/lib/phase-diagram/PhaseDiagramExportPane.svelte +184 -0
  143. package/dist/src/lib/phase-diagram/PhaseDiagramTooltip.svelte +391 -0
  144. package/dist/src/lib/phase-diagram/TdbInfoPanel.svelte +203 -0
  145. package/dist/src/lib/phase-diagram/build-diagram.ts +186 -0
  146. package/dist/src/lib/phase-diagram/colors.ts +58 -0
  147. package/dist/src/lib/phase-diagram/diagram-input.ts +40 -0
  148. package/dist/src/lib/phase-diagram/index.ts +13 -0
  149. package/dist/src/lib/phase-diagram/parse.ts +348 -0
  150. package/dist/src/lib/phase-diagram/svg-to-diagram.ts +1023 -0
  151. package/dist/src/lib/phase-diagram/types.ts +144 -0
  152. package/dist/src/lib/phase-diagram/utils.ts +775 -0
  153. package/dist/src/lib/plot/AxisLabel.svelte +51 -0
  154. package/dist/src/lib/plot/BarPlot.svelte +2113 -0
  155. package/dist/src/lib/plot/BarPlotControls.svelte +66 -0
  156. package/dist/src/lib/plot/BinnedScatterPlot.svelte +1114 -0
  157. package/dist/src/lib/plot/ColorBar.svelte +721 -0
  158. package/dist/src/lib/plot/ColorScaleSelect.svelte +54 -0
  159. package/dist/src/lib/plot/ElementScatter.svelte +63 -0
  160. package/dist/src/lib/plot/FillArea.svelte +223 -0
  161. package/dist/src/lib/plot/Histogram.svelte +1558 -0
  162. package/dist/src/lib/plot/HistogramControls.svelte +212 -0
  163. package/dist/src/lib/plot/InteractiveAxisLabel.svelte +96 -0
  164. package/dist/src/lib/plot/Line.svelte +84 -0
  165. package/dist/src/lib/plot/PlotAxis.svelte +169 -0
  166. package/dist/src/lib/plot/PlotControls.svelte +537 -0
  167. package/dist/src/lib/plot/PlotLegend.svelte +569 -0
  168. package/dist/src/lib/plot/PlotTooltip.svelte +67 -0
  169. package/dist/src/lib/plot/PortalSelect.svelte +253 -0
  170. package/dist/src/lib/plot/ReferenceLine3D.svelte +156 -0
  171. package/dist/src/lib/plot/ReferencePlane.svelte +175 -0
  172. package/dist/src/lib/plot/ScatterPlot.svelte +2778 -0
  173. package/dist/src/lib/plot/ScatterPlot3D.svelte +529 -0
  174. package/dist/src/lib/plot/ScatterPlot3DControls.svelte +437 -0
  175. package/dist/src/lib/plot/ScatterPlot3DScene.svelte +912 -0
  176. package/dist/src/lib/plot/ScatterPlotControls.svelte +306 -0
  177. package/dist/src/lib/plot/ScatterPoint.svelte +182 -0
  178. package/dist/src/lib/plot/SpacegroupBarPlot.svelte +293 -0
  179. package/dist/src/lib/plot/Surface3D.svelte +197 -0
  180. package/dist/src/lib/plot/ZeroLines.svelte +97 -0
  181. package/dist/src/lib/plot/ZoomRect.svelte +23 -0
  182. package/dist/src/lib/plot/adaptive-density.ts +316 -0
  183. package/dist/src/lib/plot/auto-place.ts +184 -0
  184. package/dist/src/lib/plot/axis-utils.ts +122 -0
  185. package/dist/src/lib/plot/binned-scatter-types.ts +83 -0
  186. package/dist/src/lib/plot/data-cleaning.ts +1069 -0
  187. package/dist/src/lib/plot/data-transform.ts +69 -0
  188. package/dist/src/lib/plot/defaults.ts +9 -0
  189. package/dist/src/lib/plot/fill-utils.ts +494 -0
  190. package/dist/src/lib/plot/hover-lock.svelte.ts +60 -0
  191. package/dist/src/lib/plot/index.ts +53 -0
  192. package/dist/src/lib/plot/interactions.ts +119 -0
  193. package/dist/src/lib/plot/layout.ts +425 -0
  194. package/dist/src/lib/plot/reference-line.ts +426 -0
  195. package/dist/src/lib/plot/scales.ts +654 -0
  196. package/dist/src/lib/plot/svg.ts +23 -0
  197. package/dist/src/lib/plot/types.ts +1144 -0
  198. package/dist/src/lib/plot/utils/label-placement.ts +541 -0
  199. package/dist/src/lib/plot/utils/series-visibility.ts +140 -0
  200. package/dist/src/lib/plot/utils.ts +11 -0
  201. package/dist/src/lib/rdf/RdfPlot.svelte +247 -0
  202. package/dist/src/lib/rdf/calc-rdf.ts +167 -0
  203. package/dist/src/lib/rdf/index.ts +27 -0
  204. package/dist/src/lib/sanitize.ts +126 -0
  205. package/dist/src/lib/settings.ts +1479 -0
  206. package/dist/src/lib/spectral/Bands.svelte +1040 -0
  207. package/dist/src/lib/spectral/BandsAndDos.svelte +134 -0
  208. package/dist/src/lib/spectral/BrillouinBandsDos.svelte +252 -0
  209. package/dist/src/lib/spectral/Dos.svelte +697 -0
  210. package/dist/src/lib/spectral/helpers.ts +1381 -0
  211. package/dist/src/lib/spectral/index.ts +8 -0
  212. package/dist/src/lib/spectral/types.ts +112 -0
  213. package/dist/src/lib/state.svelte.ts +64 -0
  214. package/dist/src/lib/structure/Arrow.svelte +72 -0
  215. package/dist/src/lib/structure/AtomLegend.svelte +815 -0
  216. package/dist/src/lib/structure/Bond.svelte +140 -0
  217. package/dist/src/lib/structure/CanvasTooltip.svelte +33 -0
  218. package/dist/src/lib/structure/CellSelect.svelte +349 -0
  219. package/dist/src/lib/structure/Cylinder.svelte +45 -0
  220. package/dist/src/lib/structure/Lattice.svelte +196 -0
  221. package/dist/src/lib/structure/Structure.svelte +2248 -0
  222. package/dist/src/lib/structure/StructureControls.svelte +1273 -0
  223. package/dist/src/lib/structure/StructureExportPane.svelte +252 -0
  224. package/dist/src/lib/structure/StructureInfoPane.svelte +737 -0
  225. package/dist/src/lib/structure/StructureScene.svelte +2255 -0
  226. package/dist/src/lib/structure/atom-properties.ts +316 -0
  227. package/dist/src/lib/structure/bond-order-perception.ts +447 -0
  228. package/dist/src/lib/structure/bonding.ts +944 -0
  229. package/dist/src/lib/structure/export.ts +861 -0
  230. package/dist/src/lib/structure/index.ts +291 -0
  231. package/dist/src/lib/structure/label-placement.ts +130 -0
  232. package/dist/src/lib/structure/measure.ts +45 -0
  233. package/dist/src/lib/structure/parse.ts +1705 -0
  234. package/dist/src/lib/structure/partial-occupancy.ts +183 -0
  235. package/dist/src/lib/structure/pbc.ts +164 -0
  236. package/dist/src/lib/structure/supercell.ts +226 -0
  237. package/dist/src/lib/structure/validation.ts +11 -0
  238. package/dist/src/lib/symmetry/SymmetryStats.svelte +226 -0
  239. package/dist/src/lib/symmetry/WyckoffTable.svelte +120 -0
  240. package/dist/src/lib/symmetry/cell-transform.ts +118 -0
  241. package/dist/src/lib/symmetry/index.ts +348 -0
  242. package/dist/src/lib/symmetry/spacegroups.ts +404 -0
  243. package/dist/src/lib/table/HeatmapTable.svelte +1833 -0
  244. package/dist/src/lib/table/ToggleMenu.svelte +385 -0
  245. package/dist/src/lib/table/index.ts +139 -0
  246. package/dist/src/lib/theme/ThemeControl.svelte +53 -0
  247. package/dist/src/lib/theme/index.ts +107 -0
  248. package/dist/src/lib/theme/themes.mjs +297 -0
  249. package/dist/src/lib/time.ts +71 -0
  250. package/dist/src/lib/tooltip/TooltipContent.svelte +58 -0
  251. package/dist/src/lib/tooltip/index.ts +2 -0
  252. package/dist/src/lib/tooltip/types.ts +13 -0
  253. package/dist/src/lib/trajectory/Trajectory.svelte +1545 -0
  254. package/dist/src/lib/trajectory/TrajectoryError.svelte +128 -0
  255. package/dist/src/lib/trajectory/TrajectoryExportPane.svelte +357 -0
  256. package/dist/src/lib/trajectory/TrajectoryInfoPane.svelte +313 -0
  257. package/dist/src/lib/trajectory/constants.ts +7 -0
  258. package/dist/src/lib/trajectory/extract.ts +196 -0
  259. package/dist/src/lib/trajectory/format-detect.ts +96 -0
  260. package/dist/src/lib/trajectory/frame-reader.ts +456 -0
  261. package/dist/src/lib/trajectory/helpers.ts +217 -0
  262. package/dist/src/lib/trajectory/index.ts +218 -0
  263. package/dist/src/lib/trajectory/parse/ase.ts +109 -0
  264. package/dist/src/lib/trajectory/parse/hdf5.ts +173 -0
  265. package/dist/src/lib/trajectory/parse/index.ts +411 -0
  266. package/dist/src/lib/trajectory/parse/lammps.ts +215 -0
  267. package/dist/src/lib/trajectory/parse/vasp.ts +102 -0
  268. package/dist/src/lib/trajectory/parse/xyz.ts +143 -0
  269. package/dist/src/lib/trajectory/plotting.ts +599 -0
  270. package/dist/src/lib/trajectory/types.ts +13 -0
  271. package/dist/src/lib/utils.ts +56 -0
  272. package/dist/src/lib/xrd/XrdPlot.svelte +615 -0
  273. package/dist/src/lib/xrd/broadening.ts +130 -0
  274. package/dist/src/lib/xrd/calc-xrd.ts +397 -0
  275. package/dist/src/lib/xrd/index.ts +38 -0
  276. package/dist/src/lib/xrd/parse.ts +858 -0
  277. package/dist/webview.js +29421 -0
  278. package/icon.png +0 -0
  279. package/license +1 -1
  280. package/matterviz-0.3.2.vsix +0 -0
  281. package/matterviz-0.3.4.vsix +0 -0
  282. package/matterviz-0.3.5.vsix +0 -0
  283. package/package.json +1460 -215
  284. package/readme.md +171 -98
  285. package/scripts/sync-config.ts +101 -0
  286. package/src/declarations.d.ts +2 -0
  287. package/src/extension.ts +972 -0
  288. package/src/node-io.ts +65 -0
  289. package/src/types.ts +17 -0
  290. package/src/webview/JsonBrowser.svelte +1079 -0
  291. package/src/webview/PlotPanel.svelte +346 -0
  292. package/src/webview/detect.ts +444 -0
  293. package/src/webview/main.ts +764 -0
  294. package/src/webview/plot-utils.ts +250 -0
  295. package/test-fixtures/all-viz-types.json.gz +0 -0
  296. package/test-fixtures/plot-demo-data.json.gz +0 -0
  297. package/tests/detect.test.ts +604 -0
  298. package/tests/extension.test.ts +2041 -0
  299. package/tests/node-io.test.ts +39 -0
  300. package/tests/plot-utils.test.ts +302 -0
  301. package/tests/vite-plugin-json-gz.test.ts +114 -0
  302. package/tests/vscode-mock.ts +18 -0
  303. package/tests/webview.test.ts +231 -0
  304. package/tsconfig.json +20 -0
  305. package/vite-plugin-json-gz.ts +29 -0
  306. package/vite.config.ts +34 -0
  307. package/vite.extension.config.ts +34 -0
  308. package/dist/EmptyState.svelte.d.ts +0 -9
  309. package/dist/FilePicker.svelte +0 -360
  310. package/dist/FilePicker.svelte.d.ts +0 -17
  311. package/dist/Icon.svelte.d.ts +0 -13
  312. package/dist/MillerIndexInput.svelte +0 -66
  313. package/dist/MillerIndexInput.svelte.d.ts +0 -7
  314. package/dist/api/mp.d.ts +0 -6
  315. package/dist/api/mp.js +0 -22
  316. package/dist/api/optimade.d.ts +0 -45
  317. package/dist/api/optimade.js +0 -135
  318. package/dist/brillouin/BrillouinZone.svelte +0 -546
  319. package/dist/brillouin/BrillouinZone.svelte.d.ts +0 -83
  320. package/dist/brillouin/BrillouinZoneControls.svelte +0 -144
  321. package/dist/brillouin/BrillouinZoneControls.svelte.d.ts +0 -17
  322. package/dist/brillouin/BrillouinZoneExportPane.svelte +0 -148
  323. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +0 -15
  324. package/dist/brillouin/BrillouinZoneInfoPane.svelte +0 -146
  325. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +0 -13
  326. package/dist/brillouin/BrillouinZoneScene.svelte +0 -476
  327. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +0 -48
  328. package/dist/brillouin/BrillouinZoneTooltip.svelte +0 -92
  329. package/dist/brillouin/BrillouinZoneTooltip.svelte.d.ts +0 -8
  330. package/dist/brillouin/compute.d.ts +0 -17
  331. package/dist/brillouin/compute.js +0 -426
  332. package/dist/brillouin/index.d.ts +0 -8
  333. package/dist/brillouin/index.js +0 -8
  334. package/dist/brillouin/types.d.ts +0 -48
  335. package/dist/brillouin/types.js +0 -1
  336. package/dist/chempot-diagram/ChemPotDiagram.svelte +0 -327
  337. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +0 -13
  338. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +0 -847
  339. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +0 -16
  340. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +0 -3194
  341. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +0 -16
  342. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +0 -7
  343. package/dist/chempot-diagram/async-compute.svelte.d.ts +0 -3
  344. package/dist/chempot-diagram/async-compute.svelte.js +0 -78
  345. package/dist/chempot-diagram/chempot-worker.d.ts +0 -1
  346. package/dist/chempot-diagram/chempot-worker.js +0 -11
  347. package/dist/chempot-diagram/color.d.ts +0 -10
  348. package/dist/chempot-diagram/color.js +0 -32
  349. package/dist/chempot-diagram/compute.d.ts +0 -48
  350. package/dist/chempot-diagram/compute.js +0 -812
  351. package/dist/chempot-diagram/index.d.ts +0 -6
  352. package/dist/chempot-diagram/index.js +0 -6
  353. package/dist/chempot-diagram/pointer.d.ts +0 -16
  354. package/dist/chempot-diagram/pointer.js +0 -40
  355. package/dist/chempot-diagram/temperature.d.ts +0 -15
  356. package/dist/chempot-diagram/temperature.js +0 -36
  357. package/dist/chempot-diagram/types.d.ts +0 -86
  358. package/dist/chempot-diagram/types.js +0 -28
  359. package/dist/colors/index.d.ts +0 -47
  360. package/dist/colors/index.js +0 -203
  361. package/dist/composition/BarChart.svelte +0 -297
  362. package/dist/composition/BarChart.svelte.d.ts +0 -39
  363. package/dist/composition/BubbleChart.svelte +0 -218
  364. package/dist/composition/BubbleChart.svelte.d.ts +0 -28
  365. package/dist/composition/Composition.svelte +0 -164
  366. package/dist/composition/Composition.svelte.d.ts +0 -15
  367. package/dist/composition/Formula.svelte +0 -265
  368. package/dist/composition/Formula.svelte.d.ts +0 -19
  369. package/dist/composition/FormulaFilter.svelte +0 -1259
  370. package/dist/composition/FormulaFilter.svelte.d.ts +0 -51
  371. package/dist/composition/PieChart.svelte +0 -323
  372. package/dist/composition/PieChart.svelte.d.ts +0 -37
  373. package/dist/composition/format.d.ts +0 -15
  374. package/dist/composition/format.js +0 -109
  375. package/dist/composition/index.d.ts +0 -20
  376. package/dist/composition/index.js +0 -14
  377. package/dist/composition/parse.d.ts +0 -55
  378. package/dist/composition/parse.js +0 -459
  379. package/dist/constants.d.ts +0 -29
  380. package/dist/constants.js +0 -99
  381. package/dist/controls.d.ts +0 -14
  382. package/dist/controls.js +0 -30
  383. package/dist/convex-hull/ConvexHull.svelte +0 -157
  384. package/dist/convex-hull/ConvexHull.svelte.d.ts +0 -13
  385. package/dist/convex-hull/ConvexHull2D.svelte +0 -814
  386. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +0 -11
  387. package/dist/convex-hull/ConvexHull3D.svelte +0 -1790
  388. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +0 -8
  389. package/dist/convex-hull/ConvexHull4D.svelte +0 -1386
  390. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +0 -8
  391. package/dist/convex-hull/ConvexHullControls.svelte +0 -546
  392. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +0 -48
  393. package/dist/convex-hull/ConvexHullInfoPane.svelte +0 -122
  394. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +0 -18
  395. package/dist/convex-hull/ConvexHullStats.svelte +0 -922
  396. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +0 -15
  397. package/dist/convex-hull/ConvexHullTooltip.svelte +0 -131
  398. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +0 -33
  399. package/dist/convex-hull/GasPressureControls.svelte +0 -247
  400. package/dist/convex-hull/GasPressureControls.svelte.d.ts +0 -11
  401. package/dist/convex-hull/StructurePopup.svelte +0 -116
  402. package/dist/convex-hull/StructurePopup.svelte.d.ts +0 -18
  403. package/dist/convex-hull/TemperatureSlider.svelte +0 -137
  404. package/dist/convex-hull/TemperatureSlider.svelte.d.ts +0 -8
  405. package/dist/convex-hull/barycentric-coords.d.ts +0 -18
  406. package/dist/convex-hull/barycentric-coords.js +0 -182
  407. package/dist/convex-hull/demo-temperature.d.ts +0 -6
  408. package/dist/convex-hull/demo-temperature.js +0 -40
  409. package/dist/convex-hull/gas-thermodynamics.d.ts +0 -16
  410. package/dist/convex-hull/gas-thermodynamics.js +0 -316
  411. package/dist/convex-hull/helpers.d.ts +0 -103
  412. package/dist/convex-hull/helpers.js +0 -689
  413. package/dist/convex-hull/index.d.ts +0 -118
  414. package/dist/convex-hull/index.js +0 -57
  415. package/dist/convex-hull/thermodynamics.d.ts +0 -66
  416. package/dist/convex-hull/thermodynamics.js +0 -1752
  417. package/dist/convex-hull/types.d.ts +0 -162
  418. package/dist/convex-hull/types.js +0 -36
  419. package/dist/coordination/CoordinationBarPlot.svelte +0 -311
  420. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +0 -30
  421. package/dist/coordination/calc-coordination.d.ts +0 -15
  422. package/dist/coordination/calc-coordination.js +0 -63
  423. package/dist/coordination/index.d.ts +0 -8
  424. package/dist/coordination/index.js +0 -7
  425. package/dist/element/BohrAtom.svelte +0 -147
  426. package/dist/element/BohrAtom.svelte.d.ts +0 -20
  427. package/dist/element/ElementHeading.svelte +0 -26
  428. package/dist/element/ElementHeading.svelte.d.ts +0 -8
  429. package/dist/element/ElementPhoto.svelte +0 -57
  430. package/dist/element/ElementPhoto.svelte.d.ts +0 -9
  431. package/dist/element/ElementStats.svelte +0 -80
  432. package/dist/element/ElementStats.svelte.d.ts +0 -8
  433. package/dist/element/ElementTile.svelte +0 -484
  434. package/dist/element/ElementTile.svelte.d.ts +0 -29
  435. package/dist/element/Nucleus.svelte.d.ts +0 -17
  436. package/dist/element/data.d.ts +0 -2
  437. package/dist/element/data.js +0 -2
  438. package/dist/element/data.json.gz.d.ts +0 -2
  439. package/dist/element/index.d.ts +0 -8
  440. package/dist/element/index.js +0 -8
  441. package/dist/element/types.d.ts +0 -57
  442. package/dist/element/types.js +0 -1
  443. package/dist/feedback/ClickFeedback.svelte +0 -58
  444. package/dist/feedback/ClickFeedback.svelte.d.ts +0 -12
  445. package/dist/feedback/DragOverlay.svelte +0 -42
  446. package/dist/feedback/DragOverlay.svelte.d.ts +0 -7
  447. package/dist/feedback/Spinner.svelte.d.ts +0 -7
  448. package/dist/feedback/StatusMessage.svelte.d.ts +0 -9
  449. package/dist/feedback/index.d.ts +0 -4
  450. package/dist/feedback/index.js +0 -4
  451. package/dist/fermi-surface/FermiSlice.svelte +0 -189
  452. package/dist/fermi-surface/FermiSlice.svelte.d.ts +0 -24
  453. package/dist/fermi-surface/FermiSurface.svelte +0 -600
  454. package/dist/fermi-surface/FermiSurface.svelte.d.ts +0 -83
  455. package/dist/fermi-surface/FermiSurfaceControls.svelte +0 -452
  456. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +0 -35
  457. package/dist/fermi-surface/FermiSurfaceScene.svelte +0 -792
  458. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +0 -50
  459. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +0 -111
  460. package/dist/fermi-surface/FermiSurfaceTooltip.svelte.d.ts +0 -8
  461. package/dist/fermi-surface/compute.d.ts +0 -5
  462. package/dist/fermi-surface/compute.js +0 -538
  463. package/dist/fermi-surface/constants.d.ts +0 -9
  464. package/dist/fermi-surface/constants.js +0 -27
  465. package/dist/fermi-surface/export.d.ts +0 -5
  466. package/dist/fermi-surface/export.js +0 -63
  467. package/dist/fermi-surface/index.d.ts +0 -12
  468. package/dist/fermi-surface/index.js +0 -13
  469. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  470. package/dist/fermi-surface/marching-cubes.js +0 -2
  471. package/dist/fermi-surface/parse.d.ts +0 -2
  472. package/dist/fermi-surface/parse.js +0 -495
  473. package/dist/fermi-surface/symmetry.d.ts +0 -3
  474. package/dist/fermi-surface/symmetry.js +0 -46
  475. package/dist/fermi-surface/types.d.ts +0 -113
  476. package/dist/fermi-surface/types.js +0 -4
  477. package/dist/heatmap-matrix/HeatmapMatrix.svelte +0 -1527
  478. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +0 -110
  479. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +0 -225
  480. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +0 -30
  481. package/dist/heatmap-matrix/index.d.ts +0 -53
  482. package/dist/heatmap-matrix/index.js +0 -100
  483. package/dist/heatmap-matrix/shared.d.ts +0 -2
  484. package/dist/heatmap-matrix/shared.js +0 -4
  485. package/dist/icons.d.ts +0 -569
  486. package/dist/icons.js +0 -648
  487. package/dist/index.d.ts +0 -39
  488. package/dist/index.js +0 -39
  489. package/dist/io/decompress.d.ts +0 -10
  490. package/dist/io/decompress.js +0 -74
  491. package/dist/io/export.d.ts +0 -16
  492. package/dist/io/export.js +0 -316
  493. package/dist/io/fetch.d.ts +0 -5
  494. package/dist/io/fetch.js +0 -39
  495. package/dist/io/file-drop.d.ts +0 -7
  496. package/dist/io/file-drop.js +0 -43
  497. package/dist/io/index.d.ts +0 -7
  498. package/dist/io/index.js +0 -7
  499. package/dist/io/is-binary.d.ts +0 -1
  500. package/dist/io/is-binary.js +0 -20
  501. package/dist/io/types.d.ts +0 -8
  502. package/dist/io/types.js +0 -1
  503. package/dist/io/url-drop.d.ts +0 -2
  504. package/dist/io/url-drop.js +0 -117
  505. package/dist/isosurface/Isosurface.svelte +0 -285
  506. package/dist/isosurface/Isosurface.svelte.d.ts +0 -8
  507. package/dist/isosurface/IsosurfaceControls.svelte +0 -291
  508. package/dist/isosurface/IsosurfaceControls.svelte.d.ts +0 -9
  509. package/dist/isosurface/index.d.ts +0 -5
  510. package/dist/isosurface/index.js +0 -6
  511. package/dist/isosurface/parse.d.ts +0 -6
  512. package/dist/isosurface/parse.js +0 -553
  513. package/dist/isosurface/slice.d.ts +0 -11
  514. package/dist/isosurface/slice.js +0 -140
  515. package/dist/isosurface/types.d.ts +0 -56
  516. package/dist/isosurface/types.js +0 -227
  517. package/dist/labels.d.ts +0 -53
  518. package/dist/labels.js +0 -274
  519. package/dist/layout/FullscreenToggle.svelte +0 -50
  520. package/dist/layout/FullscreenToggle.svelte.d.ts +0 -7
  521. package/dist/layout/InfoCard.svelte +0 -120
  522. package/dist/layout/InfoCard.svelte.d.ts +0 -21
  523. package/dist/layout/InfoTag.svelte +0 -183
  524. package/dist/layout/InfoTag.svelte.d.ts +0 -19
  525. package/dist/layout/PropertyFilter.svelte +0 -244
  526. package/dist/layout/PropertyFilter.svelte.d.ts +0 -24
  527. package/dist/layout/SettingsSection.svelte +0 -148
  528. package/dist/layout/SettingsSection.svelte.d.ts +0 -17
  529. package/dist/layout/SubpageGrid.svelte +0 -82
  530. package/dist/layout/SubpageGrid.svelte.d.ts +0 -14
  531. package/dist/layout/fullscreen.d.ts +0 -9
  532. package/dist/layout/fullscreen.js +0 -53
  533. package/dist/layout/index.d.ts +0 -10
  534. package/dist/layout/index.js +0 -8
  535. package/dist/layout/json-tree/JsonNode.svelte +0 -548
  536. package/dist/layout/json-tree/JsonNode.svelte.d.ts +0 -11
  537. package/dist/layout/json-tree/JsonTree.svelte +0 -1222
  538. package/dist/layout/json-tree/JsonTree.svelte.d.ts +0 -6
  539. package/dist/layout/json-tree/JsonValue.svelte +0 -334
  540. package/dist/layout/json-tree/JsonValue.svelte.d.ts +0 -9
  541. package/dist/layout/json-tree/index.d.ts +0 -3
  542. package/dist/layout/json-tree/index.js +0 -3
  543. package/dist/layout/json-tree/types.d.ts +0 -73
  544. package/dist/layout/json-tree/types.js +0 -3
  545. package/dist/layout/json-tree/utils.d.ts +0 -29
  546. package/dist/layout/json-tree/utils.js +0 -649
  547. package/dist/marching-cubes.d.ts +0 -14
  548. package/dist/marching-cubes.js +0 -542
  549. package/dist/math.d.ts +0 -91
  550. package/dist/math.js +0 -896
  551. package/dist/overlays/ContextMenu.svelte +0 -162
  552. package/dist/overlays/ContextMenu.svelte.d.ts +0 -25
  553. package/dist/overlays/CopyButton.svelte +0 -45
  554. package/dist/overlays/CopyButton.svelte.d.ts +0 -8
  555. package/dist/overlays/DraggablePane.svelte +0 -564
  556. package/dist/overlays/DraggablePane.svelte.d.ts +0 -36
  557. package/dist/overlays/InfoPaneCards.svelte +0 -149
  558. package/dist/overlays/InfoPaneCards.svelte.d.ts +0 -22
  559. package/dist/overlays/index.d.ts +0 -2
  560. package/dist/overlays/index.js +0 -2
  561. package/dist/periodic-table/PeriodicTable.svelte +0 -469
  562. package/dist/periodic-table/PeriodicTable.svelte.d.ts +0 -55
  563. package/dist/periodic-table/PeriodicTableControls.svelte +0 -557
  564. package/dist/periodic-table/PeriodicTableControls.svelte.d.ts +0 -24
  565. package/dist/periodic-table/PropertySelect.svelte +0 -37
  566. package/dist/periodic-table/PropertySelect.svelte.d.ts +0 -13
  567. package/dist/periodic-table/TableInset.svelte.d.ts +0 -9
  568. package/dist/periodic-table/index.d.ts +0 -10
  569. package/dist/periodic-table/index.js +0 -4
  570. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +0 -1084
  571. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +0 -44
  572. package/dist/phase-diagram/PhaseDiagramControls.svelte +0 -449
  573. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +0 -30
  574. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +0 -126
  575. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +0 -15
  576. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +0 -192
  577. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +0 -19
  578. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +0 -392
  579. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +0 -16
  580. package/dist/phase-diagram/TdbInfoPanel.svelte +0 -203
  581. package/dist/phase-diagram/TdbInfoPanel.svelte.d.ts +0 -12
  582. package/dist/phase-diagram/build-diagram.d.ts +0 -11
  583. package/dist/phase-diagram/build-diagram.js +0 -167
  584. package/dist/phase-diagram/colors.d.ts +0 -35
  585. package/dist/phase-diagram/colors.js +0 -51
  586. package/dist/phase-diagram/diagram-input.d.ts +0 -33
  587. package/dist/phase-diagram/diagram-input.js +0 -3
  588. package/dist/phase-diagram/index.d.ts +0 -13
  589. package/dist/phase-diagram/index.js +0 -13
  590. package/dist/phase-diagram/parse.d.ts +0 -55
  591. package/dist/phase-diagram/parse.js +0 -276
  592. package/dist/phase-diagram/svg-to-diagram.d.ts +0 -2
  593. package/dist/phase-diagram/svg-to-diagram.js +0 -867
  594. package/dist/phase-diagram/types.d.ts +0 -99
  595. package/dist/phase-diagram/types.js +0 -1
  596. package/dist/phase-diagram/utils.d.ts +0 -118
  597. package/dist/phase-diagram/utils.js +0 -606
  598. package/dist/plot/AxisLabel.svelte +0 -51
  599. package/dist/plot/AxisLabel.svelte.d.ts +0 -16
  600. package/dist/plot/BarPlot.svelte +0 -2265
  601. package/dist/plot/BarPlot.svelte.d.ts +0 -83
  602. package/dist/plot/BarPlotControls.svelte +0 -66
  603. package/dist/plot/BarPlotControls.svelte.d.ts +0 -18
  604. package/dist/plot/ColorBar.svelte +0 -719
  605. package/dist/plot/ColorBar.svelte.d.ts +0 -31
  606. package/dist/plot/ColorScaleSelect.svelte +0 -54
  607. package/dist/plot/ColorScaleSelect.svelte.d.ts +0 -15
  608. package/dist/plot/ElementScatter.svelte +0 -63
  609. package/dist/plot/ElementScatter.svelte.d.ts +0 -14
  610. package/dist/plot/FillArea.svelte +0 -225
  611. package/dist/plot/FillArea.svelte.d.ts +0 -21
  612. package/dist/plot/Histogram.svelte +0 -1672
  613. package/dist/plot/Histogram.svelte.d.ts +0 -50
  614. package/dist/plot/HistogramControls.svelte +0 -212
  615. package/dist/plot/HistogramControls.svelte.d.ts +0 -22
  616. package/dist/plot/InteractiveAxisLabel.svelte +0 -94
  617. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +0 -14
  618. package/dist/plot/Line.svelte +0 -84
  619. package/dist/plot/Line.svelte.d.ts +0 -15
  620. package/dist/plot/PlotControls.svelte +0 -537
  621. package/dist/plot/PlotControls.svelte.d.ts +0 -4
  622. package/dist/plot/PlotLegend.svelte +0 -569
  623. package/dist/plot/PlotLegend.svelte.d.ts +0 -29
  624. package/dist/plot/PlotTooltip.svelte +0 -67
  625. package/dist/plot/PlotTooltip.svelte.d.ts +0 -17
  626. package/dist/plot/PortalSelect.svelte +0 -253
  627. package/dist/plot/PortalSelect.svelte.d.ts +0 -16
  628. package/dist/plot/ReferenceLine.svelte.d.ts +0 -20
  629. package/dist/plot/ReferenceLine3D.svelte +0 -154
  630. package/dist/plot/ReferenceLine3D.svelte.d.ts +0 -14
  631. package/dist/plot/ReferencePlane.svelte +0 -178
  632. package/dist/plot/ReferencePlane.svelte.d.ts +0 -14
  633. package/dist/plot/ScatterPlot.svelte +0 -2845
  634. package/dist/plot/ScatterPlot.svelte.d.ts +0 -93
  635. package/dist/plot/ScatterPlot3D.svelte +0 -502
  636. package/dist/plot/ScatterPlot3D.svelte.d.ts +0 -94
  637. package/dist/plot/ScatterPlot3DControls.svelte +0 -437
  638. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +0 -20
  639. package/dist/plot/ScatterPlot3DScene.svelte +0 -912
  640. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +0 -74
  641. package/dist/plot/ScatterPlotControls.svelte +0 -307
  642. package/dist/plot/ScatterPlotControls.svelte.d.ts +0 -17
  643. package/dist/plot/ScatterPoint.svelte +0 -191
  644. package/dist/plot/ScatterPoint.svelte.d.ts +0 -21
  645. package/dist/plot/SpacegroupBarPlot.svelte +0 -293
  646. package/dist/plot/SpacegroupBarPlot.svelte.d.ts +0 -9
  647. package/dist/plot/Surface3D.svelte +0 -200
  648. package/dist/plot/Surface3D.svelte.d.ts +0 -13
  649. package/dist/plot/ZeroLines.svelte +0 -96
  650. package/dist/plot/ZeroLines.svelte.d.ts +0 -32
  651. package/dist/plot/ZoomRect.svelte +0 -23
  652. package/dist/plot/ZoomRect.svelte.d.ts +0 -8
  653. package/dist/plot/axis-utils.d.ts +0 -19
  654. package/dist/plot/axis-utils.js +0 -80
  655. package/dist/plot/data-cleaning.d.ts +0 -37
  656. package/dist/plot/data-cleaning.js +0 -855
  657. package/dist/plot/data-transform.d.ts +0 -16
  658. package/dist/plot/data-transform.js +0 -45
  659. package/dist/plot/defaults.d.ts +0 -19
  660. package/dist/plot/defaults.js +0 -9
  661. package/dist/plot/fill-utils.d.ts +0 -51
  662. package/dist/plot/fill-utils.js +0 -337
  663. package/dist/plot/hover-lock.svelte.d.ts +0 -14
  664. package/dist/plot/hover-lock.svelte.js +0 -46
  665. package/dist/plot/index.d.ts +0 -37
  666. package/dist/plot/index.js +0 -37
  667. package/dist/plot/interactions.d.ts +0 -12
  668. package/dist/plot/interactions.js +0 -100
  669. package/dist/plot/layout.d.ts +0 -60
  670. package/dist/plot/layout.js +0 -230
  671. package/dist/plot/reference-line.d.ts +0 -60
  672. package/dist/plot/reference-line.js +0 -316
  673. package/dist/plot/scales.d.ts +0 -48
  674. package/dist/plot/scales.js +0 -484
  675. package/dist/plot/svg.d.ts +0 -1
  676. package/dist/plot/svg.js +0 -11
  677. package/dist/plot/types.d.ts +0 -859
  678. package/dist/plot/types.js +0 -103
  679. package/dist/plot/utils/label-placement.d.ts +0 -47
  680. package/dist/plot/utils/label-placement.js +0 -256
  681. package/dist/plot/utils/series-visibility.d.ts +0 -9
  682. package/dist/plot/utils/series-visibility.js +0 -67
  683. package/dist/plot/utils.d.ts +0 -1
  684. package/dist/plot/utils.js +0 -14
  685. package/dist/rdf/RdfPlot.svelte +0 -247
  686. package/dist/rdf/RdfPlot.svelte.d.ts +0 -27
  687. package/dist/rdf/calc-rdf.d.ts +0 -4
  688. package/dist/rdf/calc-rdf.js +0 -111
  689. package/dist/rdf/index.d.ts +0 -23
  690. package/dist/rdf/index.js +0 -2
  691. package/dist/sanitize.d.ts +0 -4
  692. package/dist/sanitize.js +0 -114
  693. package/dist/settings.d.ts +0 -255
  694. package/dist/settings.js +0 -1132
  695. package/dist/spectral/Bands.svelte +0 -1040
  696. package/dist/spectral/Bands.svelte.d.ts +0 -40
  697. package/dist/spectral/BandsAndDos.svelte +0 -128
  698. package/dist/spectral/BandsAndDos.svelte.d.ts +0 -18
  699. package/dist/spectral/BrillouinBandsDos.svelte +0 -248
  700. package/dist/spectral/BrillouinBandsDos.svelte.d.ts +0 -20
  701. package/dist/spectral/Dos.svelte +0 -697
  702. package/dist/spectral/Dos.svelte.d.ts +0 -29
  703. package/dist/spectral/helpers.d.ts +0 -117
  704. package/dist/spectral/helpers.js +0 -1023
  705. package/dist/spectral/index.d.ts +0 -6
  706. package/dist/spectral/index.js +0 -7
  707. package/dist/spectral/types.d.ts +0 -84
  708. package/dist/spectral/types.js +0 -2
  709. package/dist/state.svelte.d.ts +0 -25
  710. package/dist/state.svelte.js +0 -45
  711. package/dist/structure/Arrow.svelte +0 -72
  712. package/dist/structure/Arrow.svelte.d.ts +0 -15
  713. package/dist/structure/AtomLegend.svelte +0 -798
  714. package/dist/structure/AtomLegend.svelte.d.ts +0 -34
  715. package/dist/structure/Bond.svelte +0 -140
  716. package/dist/structure/Bond.svelte.d.ts +0 -9
  717. package/dist/structure/CanvasTooltip.svelte +0 -33
  718. package/dist/structure/CanvasTooltip.svelte.d.ts +0 -12
  719. package/dist/structure/CellSelect.svelte +0 -351
  720. package/dist/structure/CellSelect.svelte.d.ts +0 -13
  721. package/dist/structure/Cylinder.svelte +0 -45
  722. package/dist/structure/Cylinder.svelte.d.ts +0 -10
  723. package/dist/structure/Lattice.svelte +0 -196
  724. package/dist/structure/Lattice.svelte.d.ts +0 -17
  725. package/dist/structure/Structure.svelte +0 -1999
  726. package/dist/structure/Structure.svelte.d.ts +0 -87
  727. package/dist/structure/StructureControls.svelte +0 -1298
  728. package/dist/structure/StructureControls.svelte.d.ts +0 -31
  729. package/dist/structure/StructureExportPane.svelte +0 -251
  730. package/dist/structure/StructureExportPane.svelte.d.ts +0 -17
  731. package/dist/structure/StructureInfoPane.svelte +0 -735
  732. package/dist/structure/StructureInfoPane.svelte.d.ts +0 -19
  733. package/dist/structure/StructureScene.svelte +0 -1905
  734. package/dist/structure/StructureScene.svelte.d.ts +0 -108
  735. package/dist/structure/atom-properties.d.ts +0 -37
  736. package/dist/structure/atom-properties.js +0 -200
  737. package/dist/structure/bond-order-perception.d.ts +0 -13
  738. package/dist/structure/bond-order-perception.js +0 -367
  739. package/dist/structure/bonding.d.ts +0 -42
  740. package/dist/structure/bonding.js +0 -525
  741. package/dist/structure/export.d.ts +0 -20
  742. package/dist/structure/export.js +0 -727
  743. package/dist/structure/index.d.ts +0 -125
  744. package/dist/structure/index.js +0 -171
  745. package/dist/structure/label-placement.d.ts +0 -14
  746. package/dist/structure/label-placement.js +0 -72
  747. package/dist/structure/measure.d.ts +0 -6
  748. package/dist/structure/measure.js +0 -29
  749. package/dist/structure/parse.d.ts +0 -66
  750. package/dist/structure/parse.js +0 -1363
  751. package/dist/structure/partial-occupancy.d.ts +0 -25
  752. package/dist/structure/partial-occupancy.js +0 -99
  753. package/dist/structure/pbc.d.ts +0 -9
  754. package/dist/structure/pbc.js +0 -123
  755. package/dist/structure/supercell.d.ts +0 -8
  756. package/dist/structure/supercell.js +0 -170
  757. package/dist/structure/validation.d.ts +0 -2
  758. package/dist/structure/validation.js +0 -10
  759. package/dist/symmetry/SymmetryStats.svelte +0 -226
  760. package/dist/symmetry/SymmetryStats.svelte.d.ts +0 -21
  761. package/dist/symmetry/WyckoffTable.svelte +0 -113
  762. package/dist/symmetry/WyckoffTable.svelte.d.ts +0 -11
  763. package/dist/symmetry/cell-transform.d.ts +0 -12
  764. package/dist/symmetry/cell-transform.js +0 -91
  765. package/dist/symmetry/index.d.ts +0 -43
  766. package/dist/symmetry/index.js +0 -229
  767. package/dist/symmetry/spacegroups.d.ts +0 -9
  768. package/dist/symmetry/spacegroups.js +0 -394
  769. package/dist/table/HeatmapTable.svelte +0 -1854
  770. package/dist/table/HeatmapTable.svelte.d.ts +0 -49
  771. package/dist/table/ToggleMenu.svelte +0 -376
  772. package/dist/table/ToggleMenu.svelte.d.ts +0 -11
  773. package/dist/table/index.d.ts +0 -74
  774. package/dist/table/index.js +0 -38
  775. package/dist/theme/ThemeControl.svelte +0 -53
  776. package/dist/theme/ThemeControl.svelte.d.ts +0 -9
  777. package/dist/theme/index.d.ts +0 -29
  778. package/dist/theme/index.js +0 -79
  779. package/dist/theme/themes.mjs +0 -285
  780. package/dist/time.d.ts +0 -4
  781. package/dist/time.js +0 -70
  782. package/dist/tooltip/TooltipContent.svelte +0 -58
  783. package/dist/tooltip/TooltipContent.svelte.d.ts +0 -31
  784. package/dist/tooltip/index.d.ts +0 -2
  785. package/dist/tooltip/index.js +0 -2
  786. package/dist/tooltip/types.d.ts +0 -8
  787. package/dist/tooltip/types.js +0 -1
  788. package/dist/trajectory/Trajectory.svelte +0 -1517
  789. package/dist/trajectory/Trajectory.svelte.d.ts +0 -77
  790. package/dist/trajectory/TrajectoryError.svelte +0 -128
  791. package/dist/trajectory/TrajectoryError.svelte.d.ts +0 -13
  792. package/dist/trajectory/TrajectoryExportPane.svelte +0 -357
  793. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +0 -17
  794. package/dist/trajectory/TrajectoryInfoPane.svelte +0 -313
  795. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +0 -17
  796. package/dist/trajectory/constants.d.ts +0 -6
  797. package/dist/trajectory/constants.js +0 -7
  798. package/dist/trajectory/extract.d.ts +0 -5
  799. package/dist/trajectory/extract.js +0 -162
  800. package/dist/trajectory/format-detect.d.ts +0 -9
  801. package/dist/trajectory/format-detect.js +0 -76
  802. package/dist/trajectory/frame-reader.d.ts +0 -17
  803. package/dist/trajectory/frame-reader.js +0 -332
  804. package/dist/trajectory/helpers.d.ts +0 -14
  805. package/dist/trajectory/helpers.js +0 -172
  806. package/dist/trajectory/index.d.ts +0 -63
  807. package/dist/trajectory/index.js +0 -126
  808. package/dist/trajectory/parse/ase.d.ts +0 -2
  809. package/dist/trajectory/parse/ase.js +0 -73
  810. package/dist/trajectory/parse/hdf5.d.ts +0 -2
  811. package/dist/trajectory/parse/hdf5.js +0 -127
  812. package/dist/trajectory/parse/index.d.ts +0 -12
  813. package/dist/trajectory/parse/index.js +0 -299
  814. package/dist/trajectory/parse/lammps.d.ts +0 -5
  815. package/dist/trajectory/parse/lammps.js +0 -179
  816. package/dist/trajectory/parse/vasp.d.ts +0 -2
  817. package/dist/trajectory/parse/vasp.js +0 -68
  818. package/dist/trajectory/parse/xyz.d.ts +0 -2
  819. package/dist/trajectory/parse/xyz.js +0 -110
  820. package/dist/trajectory/plotting.d.ts +0 -28
  821. package/dist/trajectory/plotting.js +0 -423
  822. package/dist/trajectory/types.d.ts +0 -11
  823. package/dist/trajectory/types.js +0 -1
  824. package/dist/utils.d.ts +0 -5
  825. package/dist/utils.js +0 -36
  826. package/dist/xrd/XrdPlot.svelte +0 -615
  827. package/dist/xrd/XrdPlot.svelte.d.ts +0 -28
  828. package/dist/xrd/broadening.d.ts +0 -20
  829. package/dist/xrd/broadening.js +0 -97
  830. package/dist/xrd/calc-xrd.d.ts +0 -37
  831. package/dist/xrd/calc-xrd.js +0 -337
  832. package/dist/xrd/index.d.ts +0 -37
  833. package/dist/xrd/index.js +0 -4
  834. package/dist/xrd/parse.d.ts +0 -13
  835. package/dist/xrd/parse.js +0 -749
  836. /package/dist/{EmptyState.svelte → src/lib/EmptyState.svelte} +0 -0
  837. /package/dist/{Icon.svelte → src/lib/Icon.svelte} +0 -0
  838. /package/dist/{app.css → src/lib/app.css} +0 -0
  839. /package/dist/{chempot-diagram → src/lib/chempot-diagram}/ChemPotScene3D.svelte +0 -0
  840. /package/dist/{colors → src/lib/colors}/alloy-colors.json +0 -0
  841. /package/dist/{colors → src/lib/colors}/dark-mode-colors.json +0 -0
  842. /package/dist/{colors → src/lib/colors}/jmol-colors.json +0 -0
  843. /package/dist/{colors → src/lib/colors}/muted-colors.json +0 -0
  844. /package/dist/{colors → src/lib/colors}/pastel-colors.json +0 -0
  845. /package/dist/{colors → src/lib/colors}/vesta-colors.json +0 -0
  846. /package/dist/{element → src/lib/element}/Nucleus.svelte +0 -0
  847. /package/dist/{element → src/lib/element}/data.json +0 -0
  848. /package/dist/{element → src/lib/element}/data.json.gz +0 -0
  849. /package/dist/{element → src/lib/element}/data.schema.json +0 -0
  850. /package/dist/{element-image-urls.json → src/lib/element-image-urls.json} +0 -0
  851. /package/dist/{feedback → src/lib/feedback}/Spinner.svelte +0 -0
  852. /package/dist/{feedback → src/lib/feedback}/StatusMessage.svelte +0 -0
  853. /package/dist/{periodic-table → src/lib/periodic-table}/TableInset.svelte +0 -0
  854. /package/dist/{plot → src/lib/plot}/ReferenceLine.svelte +0 -0
  855. /package/dist/{xrd → src/lib/xrd}/atomic_scattering_params.json +0 -0
@@ -1,1999 +0,0 @@
1
- <script lang="ts">
2
- import type { ColorSchemeName } from '../colors'
3
- import { ELEMENT_COLOR_SCHEMES } from '../colors'
4
- import type { ShowControlsProp } from '../controls'
5
- import { normalize_show_controls } from '../controls'
6
- import type { ElementSymbol } from '../element'
7
- import { StatusMessage } from '../feedback'
8
- import Spinner from '../feedback/Spinner.svelte'
9
- import Icon from '../Icon.svelte'
10
- import { create_file_drop_handler, load_from_url } from '../io'
11
- import { parse_volumetric_file } from '../isosurface/parse'
12
- import type { IsosurfaceSettings, VolumetricData } from '../isosurface/types'
13
- import {
14
- auto_isosurface_settings,
15
- DEFAULT_ISOSURFACE_SETTINGS,
16
- tile_volumetric_data,
17
- } from '../isosurface/types'
18
- import { ELEM_SYMBOLS } from '../labels'
19
- import { set_fullscreen_bg, toggle_fullscreen } from '../layout'
20
- import type { Vec3 } from '../math'
21
- import { create_cart_to_frac, create_frac_to_cart } from '../math'
22
- import { DEFAULTS } from '../settings'
23
- import { sanitize_html } from '../sanitize'
24
- import { colors } from '../state.svelte'
25
- import type {
26
- AnyStructure,
27
- Crystal,
28
- MeasureMode,
29
- StructureBond,
30
- } from './'
31
- import {
32
- default_vector_configs,
33
- get_element_counts,
34
- get_pbc_image_sites,
35
- get_structure_vector_keys,
36
- } from './'
37
- import { wrap_to_unit_cell } from './pbc'
38
- import {
39
- is_valid_supercell_input,
40
- make_supercell,
41
- parse_supercell_scaling,
42
- } from './supercell'
43
- import type { CellType, SymmetrySettings } from '../symmetry'
44
- import * as symmetry from '../symmetry'
45
- import { transform_cell } from '../symmetry'
46
- import type { MoyoDataset } from '@spglib/moyo-wasm'
47
- import { Canvas } from '@threlte/core'
48
- import type { ComponentProps, Snippet } from 'svelte'
49
- import { untrack } from 'svelte'
50
- import { click_outside, tooltip } from 'svelte-multiselect/attachments'
51
- import type { HTMLAttributes } from 'svelte/elements'
52
- import { SvelteMap, SvelteSet } from 'svelte/reactivity'
53
- import type { Camera, OrthographicCamera, Scene } from 'three'
54
- import type { AtomColorConfig } from './atom-properties'
55
- import { get_property_colors } from './atom-properties'
56
- import AtomLegend from './AtomLegend.svelte'
57
- import CellSelect from './CellSelect.svelte'
58
- import { merge_bond_edits } from './bonding'
59
- import type { StructureHandlerData } from './index'
60
- import { MAX_SELECTED_SITES } from './measure'
61
- import { normalize_fractional_coords, parse_any_structure } from './parse'
62
- import StructureControls from './StructureControls.svelte'
63
- import StructureExportPane from './StructureExportPane.svelte'
64
- import StructureInfoPane from './StructureInfoPane.svelte'
65
- import StructureScene from './StructureScene.svelte'
66
-
67
- // Type alias for event handlers to reduce verbosity
68
- type EventHandler = (data: StructureHandlerData) => void
69
- type BondEditContext = {
70
- structure?: AnyStructure
71
- cell_type: CellType
72
- supercell_scaling: string
73
- show_image_atoms: boolean
74
- }
75
- type BondEditSnapshot = {
76
- bonds: StructureBond[] | undefined
77
- context: BondEditContext
78
- }
79
-
80
- // Local reactive state for scene and lattice props. Deeply reactive so nested mutations propagate.
81
- // Deep-clone to prevent mutations from leaking to global defaults across component instances.
82
- let scene_props = $state(
83
- structuredClone(DEFAULTS.structure) as typeof DEFAULTS.structure & {
84
- active_sites?: number[]
85
- camera_target?: Vec3
86
- },
87
- )
88
- let lattice_props = $state({
89
- cell_edge_opacity: DEFAULTS.structure.cell_edge_opacity,
90
- cell_surface_opacity: DEFAULTS.structure.cell_surface_opacity,
91
- cell_edge_color: DEFAULTS.structure.cell_edge_color,
92
- cell_surface_color: DEFAULTS.structure.cell_surface_color,
93
- cell_edge_width: DEFAULTS.structure.cell_edge_width,
94
- show_cell_vectors: DEFAULTS.structure.show_cell_vectors,
95
- })
96
-
97
- let {
98
- structure = $bindable(),
99
- bonds = $bindable(),
100
- scene_props: scene_props_in = $bindable(),
101
- lattice_props: lattice_props_in = $bindable(),
102
- controls_open = $bindable(false),
103
- info_pane_open = $bindable(false),
104
- enable_measure_mode = $bindable(true),
105
- measure_mode = $bindable<MeasureMode>(`distance`),
106
- background_color = $bindable(),
107
- background_opacity = $bindable(0.1),
108
- show_controls,
109
- fullscreen = $bindable(false),
110
- wrapper = $bindable(),
111
- width = $bindable(0),
112
- height = $bindable(0),
113
- reset_text = `Reset camera (or double-click)`,
114
- color_scheme = $bindable(`Vesta`),
115
- atom_color_config = $bindable({
116
- mode: DEFAULTS.structure.atom_color_mode,
117
- scale: DEFAULTS.structure.atom_color_scale,
118
- scale_type: DEFAULTS.structure.atom_color_scale_type,
119
- }),
120
- hovered = $bindable(false),
121
- dragover = $bindable(false),
122
- allow_file_drop = true,
123
- enable_info_pane = true,
124
- png_dpi = $bindable(150),
125
- show_image_atoms = $bindable(true),
126
- supercell_scaling = $bindable(`1x1x1`),
127
- fullscreen_toggle = DEFAULTS.structure.fullscreen_toggle,
128
- bottom_left,
129
- data_url,
130
- structure_string,
131
- on_file_drop,
132
- spinner_props = {},
133
- loading = $bindable(false),
134
- error_msg = $bindable(),
135
- performance_mode = $bindable(`quality`),
136
- // expose selected site indices for external control/highlighting
137
- selected_sites = $bindable([]),
138
- highlighted_sites = $bindable([]),
139
- hovered_site_idx = $bindable(null),
140
- // expose measured site indices for overlays/labels
141
- measured_sites = $bindable([]),
142
- // expose the displayed structure (with image atoms and supercell) for external use
143
- displayed_structure = $bindable(),
144
- // Track hidden elements across component lifecycle
145
- hidden_elements = $bindable(new SvelteSet<ElementSymbol>()),
146
- // Track hidden property values (e.g. Wyckoff positions, coordination numbers)
147
- hidden_prop_vals = $bindable(new SvelteSet<number | string>()),
148
- // Per-element radius overrides (absolute values in Angstroms)
149
- element_radius_overrides = $bindable<Partial<Record<ElementSymbol, number>>>({}),
150
- // Per-site radius overrides (absolute values in Angstroms)
151
- site_radius_overrides = $bindable<SvelteMap<number, number>>(new SvelteMap()),
152
- // Symmetry analysis data (bindable for external access)
153
- sym_data = $bindable(null),
154
- // Symmetry analysis settings (bindable for external control)
155
- symmetry_settings = $bindable(symmetry.default_sym_settings),
156
- // Map element symbols to different elements (e.g. {'H': 'Na', 'He': 'Cl'})
157
- // Useful for LAMMPS files where atom types are mapped to H, He, Li by default
158
- element_mapping = $bindable(),
159
- // Cell type: original, conventional, or primitive (requires symmetry analysis)
160
- cell_type = $bindable(`original`),
161
- // Volumetric data for isosurface rendering (parsed from CHGCAR or .cube files)
162
- volumetric_data = $bindable<VolumetricData[]>(),
163
- // Isosurface rendering settings
164
- isosurface_settings = $bindable<IsosurfaceSettings>({
165
- ...DEFAULT_ISOSURFACE_SETTINGS,
166
- }),
167
- // Active volume index when multiple volumes are present
168
- active_volume_idx = $bindable(0),
169
- children,
170
- top_right_controls,
171
- on_file_load,
172
- on_error,
173
- on_fullscreen_change,
174
- on_camera_move,
175
- on_camera_reset,
176
- on_bonds_change,
177
- ...rest
178
- }:
179
- & {
180
- structure?: AnyStructure
181
- bonds?: StructureBond[]
182
- scene_props?: ComponentProps<typeof StructureScene>
183
- /**
184
- * Controls visibility configuration.
185
- * - 'always': controls always visible
186
- * - 'hover': controls visible on component hover (default)
187
- * - 'never': controls never visible
188
- * - object: { mode, hidden, style } for fine-grained control
189
- *
190
- * Control names: 'reset-camera', 'fullscreen', 'measure-mode', 'info-pane', 'export-pane', 'controls'
191
- */
192
- show_controls?: ShowControlsProp
193
- fullscreen?: boolean
194
- // bindable width of the canvas
195
- width?: number
196
- // bindable height of the canvas
197
- height?: number
198
- // Canvas wrapper element (for export pane)
199
- wrapper?: HTMLDivElement
200
- // PNG export DPI setting
201
- png_dpi?: number
202
- reset_text?: string
203
- hovered?: boolean
204
- dragover?: boolean
205
- allow_file_drop?: boolean
206
- enable_info_pane?: boolean
207
- enable_measure_mode?: boolean
208
- measure_mode?: MeasureMode
209
- info_pane_open?: boolean
210
- fullscreen_toggle?: Snippet<[{ fullscreen: boolean }]> | boolean
211
- bottom_left?: Snippet<[{ structure?: AnyStructure }]>
212
- top_right_controls?: Snippet // Additional controls to render at the end of the control buttons row
213
- data_url?: string // URL to load structure from (alternative to providing structure directly)
214
- // Generic callback for when files are dropped - receives raw content and filename
215
- on_file_drop?: (content: string | ArrayBuffer, filename: string) => void
216
- // spinner props (passed to Spinner component)
217
- spinner_props?: ComponentProps<typeof Spinner>
218
- loading?: boolean
219
- error_msg?: string
220
- // Performance mode: 'quality' (default) or 'speed' for large structures
221
- performance_mode?: `quality` | `speed`
222
- // allow parent components to control highlighted/selected site indices
223
- selected_sites?: number[]
224
- highlighted_sites?: number[]
225
- hovered_site_idx?: number | null
226
- // explicit measured sites for distance/angle overlays
227
- measured_sites?: number[]
228
- // expose the displayed structure (with image atoms and/or supercell) for external use
229
- displayed_structure?: AnyStructure
230
- // Track which elements are hidden (bindable across frames in trajectories)
231
- hidden_elements?: Set<ElementSymbol>
232
- // Track which property values are hidden (e.g. Wyckoff positions, coordination numbers)
233
- hidden_prop_vals?: Set<number | string>
234
- // Per-element radius overrides (absolute values in Angstroms)
235
- element_radius_overrides?: Partial<Record<ElementSymbol, number>>
236
- // Per-site radius overrides (absolute values in Angstroms)
237
- // Accepts Map or SvelteMap for flexibility with external callers
238
- site_radius_overrides?: Map<number, number> | SvelteMap<number, number>
239
- // Symmetry analysis data (bindable for external access)
240
- sym_data?: MoyoDataset | null
241
- // Symmetry analysis settings (bindable for external control)
242
- symmetry_settings?: Partial<SymmetrySettings>
243
- // Map element symbols to different elements (e.g. {'H': 'Na', 'He': 'Cl'})
244
- element_mapping?: Partial<Record<ElementSymbol, ElementSymbol>>
245
- // Cell type: original, conventional, or primitive (requires symmetry analysis)
246
- cell_type?: CellType
247
- // Volumetric data for isosurface rendering (parsed from CHGCAR or .cube files)
248
- volumetric_data?: VolumetricData[]
249
- // Isosurface rendering settings
250
- isosurface_settings?: IsosurfaceSettings
251
- // Active volume index when multiple volumes are present
252
- active_volume_idx?: number
253
- // structure content as string (alternative to providing structure directly or via data_url)
254
- structure_string?: string
255
- // Atom coloring configuration
256
- atom_color_config?: Partial<AtomColorConfig>
257
- children?: Snippet<[{ structure?: AnyStructure; fullscreen: boolean }]>
258
- on_file_load?: EventHandler
259
- on_error?: EventHandler
260
- on_fullscreen_change?: EventHandler
261
- on_camera_move?: EventHandler
262
- on_camera_reset?: EventHandler
263
- on_bonds_change?: (bonds: StructureBond[] | undefined) => void
264
- }
265
- & Omit<ComponentProps<typeof StructureControls>, `children` | `onclose`>
266
- & Omit<HTMLAttributes<HTMLDivElement>, `children`> = $props()
267
-
268
- // Initialize models from incoming props; mutations come from UI controls; we mirror into local dicts (NOTE only doing shallow merge)
269
- $effect.pre(() => {
270
- if (scene_props_in && typeof scene_props_in === `object`) {
271
- Object.assign(scene_props, scene_props_in)
272
- }
273
- if (lattice_props_in && typeof lattice_props_in === `object`) {
274
- Object.assign(lattice_props, lattice_props_in)
275
- }
276
- })
277
-
278
- // Load structure from URL when data_url is provided
279
- $effect(() => {
280
- if (data_url && !structure) {
281
- loading = true
282
- error_msg = undefined
283
-
284
- load_from_url(data_url, (content, filename) => {
285
- if (on_file_drop) on_file_drop(content, filename)
286
- else {
287
- // Parse structure internally when no handler provided
288
- try {
289
- const text_content = content instanceof ArrayBuffer
290
- ? new TextDecoder().decode(content)
291
- : content
292
- const parsed = parse_file_content(text_content, filename)
293
- emit_file_load_event(parsed, filename, content)
294
- } catch (error) {
295
- error_msg = `Failed to parse structure: ${
296
- error instanceof Error ? error.message : String(error)
297
- }`
298
- on_error?.({ error_msg, filename })
299
- }
300
- }
301
- })
302
- .then(() => loading = false)
303
- .catch((error: Error) => {
304
- console.error(`Failed to load structure from URL:`, error)
305
- error_msg = `Failed to load structure: ${error.message}`
306
- loading = false
307
- on_error?.({ error_msg, filename: data_url })
308
- })
309
- }
310
- })
311
-
312
- $effect(() => { // Parse structure from string when structure_string is provided
313
- if (!structure_string || data_url) return
314
- loading = true
315
- error_msg = undefined
316
- clear_camera_state()
317
- try {
318
- const parsed = parse_any_structure(structure_string, `string`)
319
- if (parsed) {
320
- structure = parsed
321
- untrack(() => emit_file_load_event(parsed, `string`, structure_string))
322
- } else {
323
- throw new Error(`Failed to parse structure from string`)
324
- }
325
- } catch (err) {
326
- error_msg = `Failed to parse structure from string: ${
327
- err instanceof Error ? err.message : String(err)
328
- }`
329
- untrack(() => on_error?.({ error_msg, filename: `string` }))
330
- } finally {
331
- loading = false
332
- }
333
- })
334
-
335
- // Auto-populate vector_configs when structure has vector data (force, magmom, spin, etc.)
336
- // Skip if configs were externally provided. Clear auto-generated configs on structure change.
337
- let vectors_auto_populated_for: AnyStructure | undefined = undefined
338
- let last_auto_configs: Record<string, unknown> | undefined = undefined
339
-
340
- $effect(() => {
341
- if (!structure?.sites || structure === vectors_auto_populated_for) return
342
- const keys = get_structure_vector_keys(structure)
343
- // Clear auto-generated configs from previous structure; preserve externally-modified ones
344
- const existing = scene_props.vector_configs
345
- if (last_auto_configs && existing === last_auto_configs) {
346
- scene_props.vector_configs = {}
347
- last_auto_configs = undefined
348
- } else if (existing && Object.keys(existing).length > 0) {
349
- vectors_auto_populated_for = structure
350
- return
351
- }
352
- vectors_auto_populated_for = structure
353
- if (keys.length === 0) return
354
- const configs = default_vector_configs(keys)
355
- scene_props.vector_configs = configs
356
- // Read back the proxied reference — Svelte 5 $state wraps objects in
357
- // proxies, so `scene_props.vector_configs !== configs`. Storing the proxy
358
- // lets the identity check above detect unmodified auto-configs.
359
- // See https://svelte.dev/e/state_proxy_equality_mismatch
360
- last_auto_configs = scene_props.vector_configs
361
- scene_props.vector_scale ??= DEFAULTS.structure.vector_scale
362
- scene_props.vector_color ??= DEFAULTS.structure.vector_color
363
- })
364
-
365
- // Optimize scene props for performance based on structure size and mode
366
- $effect(() => {
367
- if (structure?.sites && performance_mode === `speed`) {
368
- const site_count = structure.sites.length
369
- const current_sphere_segments = scene_props.sphere_segments || 20
370
-
371
- // Reduce sphere segments for large structures in speed mode
372
- if (site_count > 200) {
373
- scene_props.sphere_segments = Math.min(current_sphere_segments, 12)
374
- }
375
- }
376
- })
377
-
378
- $effect(() => {
379
- colors.element = ELEMENT_COLOR_SCHEMES[color_scheme as ColorSchemeName]
380
- })
381
-
382
- // Compute property-based colors for legend display
383
- let property_colors = $derived(
384
- get_property_colors(
385
- structure,
386
- atom_color_config,
387
- scene_props.bonding_strategy,
388
- sym_data,
389
- ),
390
- )
391
-
392
- let symmetry_run_id = 0
393
- let symmetry_error = $state<string>()
394
- let last_symmetry_structure_ref: AnyStructure | null = null
395
-
396
- // Trigger symmetry analysis when structure is loaded or settings change.
397
- // Skip during atom drags — symmetry doesn't change from moving atoms,
398
- // and WASM analysis on every drag frame causes severe frame drops.
399
- $effect(() => {
400
- if (dragging_atoms) return
401
- if (!structure || !(`lattice` in structure)) {
402
- untrack(() => {
403
- sym_data = null
404
- symmetry_error = undefined
405
- })
406
- last_symmetry_structure_ref = null
407
- return
408
- }
409
-
410
- const current_structure = structure
411
- const structure_changed = current_structure !== last_symmetry_structure_ref
412
- if (structure_changed) {
413
- untrack(() => {
414
- sym_data = null
415
- symmetry_error = undefined
416
- })
417
- last_symmetry_structure_ref = current_structure
418
- } else {
419
- // Keep previous symmetry data while recomputing so bound consumers
420
- // (e.g. SymmetryStats inputs) do not unmount and lose focus.
421
- untrack(() => symmetry_error = undefined)
422
- }
423
- const run_id = ++symmetry_run_id
424
- // Destructure symmetry_settings to ensure Svelte tracks changes to symprec and algo
425
- // (reading just the object reference isn't sufficient for fine-grained reactivity)
426
- const { symprec, algo } = symmetry_settings ?? symmetry.default_sym_settings
427
- const current_settings = { symprec, algo }
428
- // Skip symmetry auto-analysis in unit tests; happy-dom can't fetch WASM assets
429
- if (typeof process !== `undefined` && process.env?.VITEST) return
430
-
431
- symmetry.ensure_moyo_wasm_ready()
432
- .then(() =>
433
- run_id === symmetry_run_id
434
- ? symmetry.analyze_structure_symmetry(current_structure, current_settings)
435
- : null
436
- )
437
- .then((data) => {
438
- if (data && run_id === symmetry_run_id) {
439
- untrack(() => sym_data = data)
440
- }
441
- })
442
- .catch((err) => {
443
- if (run_id === symmetry_run_id) {
444
- untrack(() => sym_data = null)
445
- symmetry_error = `Symmetry analysis failed: ${err?.message || err}`
446
- console.error(`Symmetry analysis failed:`, err)
447
- }
448
- })
449
- })
450
-
451
- let measure_menu_open = $state(false)
452
- let export_pane_open = $state(false)
453
-
454
- // Bond customization state
455
- let added_bonds = $state<StructureBond[]>([])
456
- let removed_bonds = $state<StructureBond[]>([])
457
- let bond_order_overrides = $state<StructureBond[]>([])
458
- let last_emitted_bond_signature = $state<string>()
459
- let bond_edit_snapshot = $state<BondEditSnapshot>()
460
- let has_bond_edits = $derived(
461
- added_bonds.length > 0 || removed_bonds.length > 0 ||
462
- bond_order_overrides.length > 0,
463
- )
464
-
465
- function clear_bond_edits() {
466
- added_bonds = []
467
- removed_bonds = []
468
- bond_order_overrides = []
469
- }
470
-
471
- function emit_bonds(next_bonds: StructureBond[] | undefined) {
472
- const signature = next_bonds === undefined ? `undefined` : JSON.stringify(next_bonds)
473
- if (signature === last_emitted_bond_signature) return
474
- last_emitted_bond_signature = signature
475
- bonds = next_bonds
476
- on_bonds_change?.(next_bonds)
477
- }
478
-
479
- const current_source_bonds = (): StructureBond[] | undefined =>
480
- bonds ?? structure?.properties?.bonds
481
-
482
- const current_bond_edit_context = (): BondEditContext => ({
483
- structure,
484
- cell_type,
485
- supercell_scaling,
486
- show_image_atoms,
487
- })
488
-
489
- const bond_edit_context_changed = (
490
- previous: BondEditContext,
491
- current: BondEditContext,
492
- ): boolean =>
493
- previous.structure !== current.structure ||
494
- previous.cell_type !== current.cell_type ||
495
- previous.supercell_scaling !== current.supercell_scaling ||
496
- previous.show_image_atoms !== current.show_image_atoms
497
-
498
- const resolve_bond_edit_reset_bonds = (
499
- snapshot: BondEditSnapshot,
500
- ): StructureBond[] | undefined =>
501
- snapshot.context.structure === structure ? snapshot.bonds : structure?.properties?.bonds
502
-
503
- $effect(() => {
504
- const snapshot = bond_edit_snapshot
505
- if (snapshot === undefined) return
506
- const context = current_bond_edit_context()
507
- if (!bond_edit_context_changed(snapshot.context, context)) return
508
- untrack(() => {
509
- emit_bonds(resolve_bond_edit_reset_bonds(snapshot))
510
- clear_bond_edits()
511
- bond_edit_snapshot = undefined
512
- })
513
- })
514
-
515
- $effect(() => {
516
- if (!has_bond_edits) {
517
- if (bond_edit_snapshot === undefined) return
518
- emit_bonds(resolve_bond_edit_reset_bonds(bond_edit_snapshot))
519
- bond_edit_snapshot = undefined
520
- return
521
- }
522
- bond_edit_snapshot ??= {
523
- bonds: current_source_bonds(),
524
- context: current_bond_edit_context(),
525
- }
526
- const edited_bonds = merge_bond_edits(
527
- bond_edit_snapshot.bonds ?? [],
528
- added_bonds,
529
- removed_bonds,
530
- bond_order_overrides,
531
- )
532
- emit_bonds(edited_bonds)
533
- })
534
-
535
- // === Edit-atoms mode state ===
536
- let dragging_atoms = $state(false)
537
- let undo_stack = $state<AnyStructure[]>([])
538
- let redo_stack = $state<AnyStructure[]>([])
539
- const MAX_HISTORY = 20
540
- // Flag set before internal edits (undo/redo/delete/add/move) to distinguish
541
- // them from external structure changes (file load, trajectory step, etc.)
542
- let is_internal_edit = false
543
- // Add-atom sub-mode state (bound to StructureScene)
544
- let add_atom_mode = $state(false)
545
- let add_element = $state<ElementSymbol>(`C` as ElementSymbol)
546
- let canvas_cursor = $state(`default`)
547
- let change_element_mode = $state(false)
548
- let change_element_value = $state(``)
549
- // Ephemeral toast message for edit operations
550
- let toast_msg = $state<string | null>(null)
551
- let toast_timer: ReturnType<typeof setTimeout> | undefined
552
- function show_toast(msg: string, duration_ms = 2000) {
553
- clearTimeout(toast_timer)
554
- toast_msg = msg
555
- toast_timer = setTimeout(() => (toast_msg = null), duration_ms)
556
- }
557
-
558
- // Normalize and validate element symbol (e.g. "fe" → "Fe", "Xx" → null)
559
- function normalize_element(input: string): ElementSymbol | null {
560
- const normalized = (input.charAt(0).toUpperCase() +
561
- input.slice(1).toLowerCase()) as ElementSymbol
562
- return ELEM_SYMBOLS.includes(normalized) ? normalized : null
563
- }
564
-
565
- function clear_selection() {
566
- selected_sites = []
567
- measured_sites = []
568
- dragging_atoms = false
569
- }
570
-
571
- function push_undo() {
572
- if (!structure) return
573
- if (undo_stack.length >= MAX_HISTORY) {
574
- undo_stack.splice(0, undo_stack.length - MAX_HISTORY + 1)
575
- }
576
- undo_stack.push($state.snapshot(structure) as AnyStructure)
577
- redo_stack.length = 0
578
- }
579
-
580
- // Shared undo/redo: pop from `source`, push current state onto `target`
581
- function apply_history(source: AnyStructure[], target: AnyStructure[]) {
582
- if (source.length === 0 || !structure) return
583
- const restored = source.pop()
584
- if (!restored) return
585
- is_internal_edit = true
586
- target.push($state.snapshot(structure) as AnyStructure)
587
- structure = restored
588
- clear_selection()
589
- }
590
-
591
- const undo = () => apply_history(undo_stack, redo_stack)
592
- const redo = () => apply_history(redo_stack, undo_stack)
593
-
594
- // Clear undo/redo stacks when structure changes externally (file load, etc.)
595
- // Internal edits set is_internal_edit=true before modifying structure.
596
- // This $effect runs after microtask, so the flag is still set from the edit.
597
- $effect(() => {
598
- // Track structure to re-run when it changes
599
- void structure
600
- if (is_internal_edit) {
601
- is_internal_edit = false
602
- return
603
- }
604
- // External change — clear history and stale edit-atoms state
605
- untrack(() => {
606
- if (undo_stack.length > 0 || redo_stack.length > 0) {
607
- undo_stack = []
608
- redo_stack = []
609
- }
610
- if (measure_mode === `edit-atoms`) {
611
- if (selected_sites.length > 0 || measured_sites.length > 0) clear_selection()
612
- if (site_radius_overrides?.size > 0) site_radius_overrides.clear()
613
- }
614
- })
615
- })
616
-
617
- // Clear selection when switching measure/edit mode so stale state doesn't carry over
618
- let mode_first_run = true
619
- $effect(() => {
620
- void measure_mode // track reactively
621
- if (mode_first_run) {
622
- mode_first_run = false
623
- return
624
- }
625
- untrack(() => {
626
- if (selected_sites.length > 0 || measured_sites.length > 0) clear_selection()
627
- })
628
- })
629
-
630
- // Auto-bake cell type transform and clear stale state when entering edit-atoms mode
631
- $effect(() => {
632
- if (measure_mode !== `edit-atoms`) return
633
- untrack(() => {
634
- // Clear bond edits from edit-bonds mode to avoid stale state
635
- if (has_bond_edits) clear_bond_edits()
636
- if (cell_type !== `original` && cell_transformed_structure && structure) {
637
- // Bake the transformed cell: push original to undo, replace structure
638
- is_internal_edit = true
639
- push_undo()
640
- structure = $state.snapshot(cell_transformed_structure) as AnyStructure
641
- cell_type = `original`
642
- }
643
- })
644
- })
645
-
646
- let controls_config = $derived(normalize_show_controls(show_controls))
647
- let active_scene_sites = $derived([
648
- ...new SvelteSet([...(scene_props.active_sites ?? []), ...highlighted_sites]),
649
- ])
650
-
651
- // Normalize structure coordinates: wrap fractional coords to [0,1) and recompute Cartesian
652
- // This ensures atoms are rendered inside the unit cell regardless of data source
653
- let normalized_structure = $derived.by(() => {
654
- if (!structure || !(`lattice` in structure)) return structure
655
- return normalize_fractional_coords(structure) as AnyStructure
656
- })
657
-
658
- let structure_with_bonds = $derived.by(() => {
659
- if (!normalized_structure || bonds === undefined) return normalized_structure
660
- return {
661
- ...normalized_structure,
662
- properties: { ...normalized_structure.properties, bonds },
663
- } as AnyStructure
664
- })
665
-
666
- // Apply cell type transformation (original, conventional, or primitive)
667
- // This must happen BEFORE supercell transformation
668
- let cell_transformed_structure = $derived.by(() => {
669
- if (
670
- !structure_with_bonds || !(`lattice` in structure_with_bonds) ||
671
- cell_type === `original`
672
- ) {
673
- return structure_with_bonds
674
- }
675
- // Cell type transformation requires symmetry data
676
- if (!sym_data) {
677
- return structure_with_bonds
678
- }
679
- try {
680
- return transform_cell(structure_with_bonds as Crystal, cell_type, sym_data)
681
- } catch (error) {
682
- console.error(`Failed to transform cell to ${cell_type}:`, error)
683
- return structure_with_bonds
684
- }
685
- })
686
-
687
- // Create supercell if needed (uses cell_transformed_structure as base)
688
- let supercell_structure = $state(structure)
689
- let supercell_loading = $state(false)
690
- let has_supercell = $derived(
691
- !!supercell_scaling && ![``, `1x1x1`, `1`].includes(supercell_scaling),
692
- )
693
- let bond_edits_enabled = $derived(
694
- cell_type === `original` && !has_supercell && !supercell_loading,
695
- )
696
-
697
- $effect(() => {
698
- if (measure_mode !== `edit-bonds` || bond_edits_enabled) return
699
- untrack(() => {
700
- clear_selection()
701
- clear_bond_edits()
702
- measure_mode = `distance`
703
- show_toast(`Bond editing is only available for the original 1x1x1 cell`)
704
- })
705
- })
706
-
707
- // Tile volumetric data to match supercell when active.
708
- // Gate on !supercell_loading so the tiled volume and supercell structure update
709
- // in the same frame (large supercells defer structure via setTimeout).
710
- let supercell_volume = $derived.by(() => {
711
- const vol = volumetric_data?.[active_volume_idx]
712
- if (!vol || !has_supercell || supercell_loading) return vol
713
- try {
714
- return tile_volumetric_data(vol, parse_supercell_scaling(supercell_scaling))
715
- } catch {
716
- return vol
717
- }
718
- })
719
-
720
- let supercell_timeout: ReturnType<typeof setTimeout> | undefined
721
- $effect(() => {
722
- const base_structure = cell_transformed_structure
723
- clearTimeout(supercell_timeout)
724
- if (!base_structure || !(`lattice` in base_structure) || !has_supercell) {
725
- supercell_structure = base_structure
726
- supercell_loading = false
727
- } else if (!is_valid_supercell_input(supercell_scaling)) {
728
- supercell_structure = base_structure
729
- supercell_loading = false
730
- } else {
731
- // For large supercells, show loading state and use async generation
732
- const sites_count = base_structure.sites?.length || 0
733
- const [nx_str, ny_str, nz_str] = supercell_scaling.split(/[x×]/)
734
- const scaling_mult = (parseInt(nx_str) || 1) * (parseInt(ny_str) || 1) *
735
- (parseInt(nz_str) || 1)
736
- const estimated_sites = sites_count * scaling_mult
737
-
738
- // Show spinner for supercells with >1000 estimated sites or scaling >8
739
- const show_loading = estimated_sites > 1000 || scaling_mult > 8
740
-
741
- if (show_loading) {
742
- supercell_loading = true
743
- // Use setTimeout to allow UI to update before heavy computation
744
- supercell_timeout = setTimeout(() => {
745
- try {
746
- if (base_structure && `lattice` in base_structure) {
747
- supercell_structure = make_supercell(
748
- base_structure as Crystal,
749
- supercell_scaling,
750
- )
751
- }
752
- } catch (error) {
753
- console.error(`Failed to create supercell:`, error)
754
- supercell_structure = base_structure
755
- } finally {
756
- supercell_loading = false
757
- }
758
- }, 10)
759
- } else {
760
- if (base_structure && `lattice` in base_structure) {
761
- supercell_structure = make_supercell(
762
- base_structure as Crystal,
763
- supercell_scaling,
764
- )
765
- }
766
- supercell_loading = false
767
- }
768
- }
769
- })
770
-
771
- // Clear selections, site overrides, and stale camera target when transformations
772
- // change site indices (skip first run to preserve parent-provided selections)
773
- let first_run = true
774
- $effect(() => {
775
- void [supercell_scaling, show_image_atoms, structure, cell_type] // track reactively
776
- if (first_run) {
777
- first_run = false
778
- return
779
- }
780
- untrack(() => {
781
- // In edit-atoms mode, structure changes are intentional user edits
782
- // (move/add/delete) — preserve the selection so TransformControls stays active
783
- if (measure_mode === `edit-atoms`) return
784
- if (selected_sites.length > 0 || measured_sites.length > 0) clear_selection()
785
- // Clear site radius overrides since site indices are no longer valid
786
- if (site_radius_overrides?.size > 0) site_radius_overrides.clear()
787
- // Clear stale camera target so orbit controls re-center on the new cell
788
- scene_props.camera_target = undefined
789
- })
790
- })
791
-
792
- // Apply element mapping then image atoms to the supercell structure.
793
- // Skip get_pbc_image_sites during atom drags — the vector math + doubled site
794
- // count causes frame drops. Image atoms reappear instantly on drag release.
795
- $effect(() => {
796
- let struct = supercell_structure
797
- if (struct && element_mapping && Object.keys(element_mapping).length > 0) {
798
- const mapping = element_mapping // capture for TypeScript narrowing
799
- struct = {
800
- ...struct,
801
- sites: struct.sites.map((site) => ({
802
- ...site,
803
- species: site.species.map((sp) => ({
804
- ...sp,
805
- element: mapping[sp.element as ElementSymbol] ?? sp.element,
806
- })),
807
- label: mapping[site.label as ElementSymbol] ?? site.label,
808
- })),
809
- }
810
- }
811
- displayed_structure =
812
- !dragging_atoms && show_image_atoms && struct && `lattice` in struct &&
813
- struct.lattice
814
- ? get_pbc_image_sites(struct)
815
- : struct
816
- })
817
-
818
- // Track if camera has ever been moved from initial position
819
- let camera_has_moved = $state(false)
820
- let camera_is_moving = $state(false)
821
- let scene = $state<Scene | undefined>(undefined)
822
- let camera = $state<Camera | undefined>(undefined)
823
- let orbit_controls = $state<
824
- ComponentProps<typeof StructureScene>[`orbit_controls`]
825
- >(undefined)
826
- let rotation_target_ref = $state<Vec3 | undefined>(undefined)
827
- let initial_computed_zoom = $state<number | undefined>(undefined)
828
-
829
- // Mutual exclusion: opening one pane closes others
830
- $effect(() => {
831
- if (info_pane_open) {
832
- untrack(() => [controls_open, export_pane_open] = [false, false])
833
- }
834
- })
835
- $effect(() => {
836
- if (controls_open) {
837
- untrack(() => [info_pane_open, export_pane_open] = [false, false])
838
- }
839
- })
840
- $effect(() => {
841
- if (export_pane_open) {
842
- untrack(() => [info_pane_open, controls_open] = [false, false])
843
- }
844
- })
845
-
846
- // Reset tracking when structure changes
847
- $effect(() => {
848
- if (structure) camera_has_moved = false
849
- })
850
-
851
- // Clear stale camera target and position so StructureScene uses the new
852
- // structure's rotation_target (unit cell center) and auto-positions the camera.
853
- function clear_camera_state() {
854
- scene_props.camera_target = undefined
855
- scene_props.camera_position = [0, 0, 0]
856
- }
857
-
858
- const read_orbit_target = (): Vec3 | undefined => {
859
- if (!orbit_controls?.target) return
860
- const { x, y, z } = orbit_controls.target
861
- return [x, y, z]
862
- }
863
-
864
- const read_camera_position = (): Vec3 | undefined =>
865
- camera
866
- ? [camera.position.x, camera.position.y, camera.position.z]
867
- : scene_props.camera_position
868
-
869
- // Emit debounced camera updates while controls are active.
870
- $effect(() => {
871
- if (!camera_is_moving) return
872
- camera_has_moved = true
873
-
874
- const emit_camera_move = () => {
875
- const camera_position = read_camera_position()
876
- if (camera_position === undefined) return
877
- const camera_target = read_orbit_target()
878
- scene_props.camera_position = camera_position
879
- scene_props.camera_target = camera_target
880
- on_camera_move?.({
881
- structure,
882
- camera_has_moved,
883
- camera_position,
884
- camera_target,
885
- })
886
- }
887
-
888
- emit_camera_move()
889
- const emit_interval = setInterval(emit_camera_move, 200)
890
- return () => clearInterval(emit_interval)
891
- })
892
-
893
- function reset_camera() {
894
- // Reset camera position to trigger automatic positioning.
895
- scene_props.camera_position = [0, 0, 0]
896
- scene_props.camera_target = rotation_target_ref
897
- camera_has_moved = false
898
-
899
- let camera_position: Vec3 = [0, 0, 0]
900
- let camera_target: Vec3 | undefined = rotation_target_ref
901
-
902
- // Reset pan/zoom and ensure controls target returns to structure center.
903
- if (orbit_controls && camera) {
904
- if (
905
- `reset` in orbit_controls &&
906
- typeof orbit_controls.reset === `function`
907
- ) orbit_controls.reset()
908
- if (orbit_controls.target && rotation_target_ref) {
909
- const [target_x, target_y, target_z] = rotation_target_ref
910
- orbit_controls.target.set(target_x, target_y, target_z)
911
- }
912
-
913
- // Reset zoom for orthographic camera
914
- if (`zoom` in camera && initial_computed_zoom !== undefined) {
915
- const ortho_camera = camera as OrthographicCamera
916
- ortho_camera.zoom = initial_computed_zoom
917
- ortho_camera.updateProjectionMatrix()
918
- }
919
-
920
- // Call update to apply changes immediately
921
- if (typeof orbit_controls.update === `function`) orbit_controls.update()
922
- camera_position = read_camera_position() ?? camera_position
923
- camera_target = read_orbit_target()
924
- }
925
-
926
- scene_props.camera_position = camera_position
927
- scene_props.camera_target = camera_target
928
- on_camera_reset?.({ structure, camera_has_moved, camera_position, camera_target })
929
- }
930
-
931
- const emit_file_load_event = (
932
- loaded_structure: AnyStructure,
933
- filename: string,
934
- content: string | ArrayBuffer,
935
- ) =>
936
- on_file_load?.({
937
- structure: loaded_structure,
938
- filename,
939
- file_size: typeof content === `string`
940
- ? new Blob([content]).size
941
- : content.byteLength,
942
- total_atoms: loaded_structure.sites?.length || 0,
943
- })
944
-
945
- // Try to parse content as a volumetric file, setting both structure and volumetric data.
946
- // Delegates format detection entirely to parse_volumetric_file (filename + content sniffing).
947
- // Returns the parsed structure on success, or null if the file isn't a volumetric format.
948
- function try_parse_volumetric(
949
- text_content: string,
950
- filename: string,
951
- ): AnyStructure | null {
952
- const vol_result = parse_volumetric_file(text_content, filename)
953
- if (!vol_result) return null
954
- // parse_volumetric_file extracts structure from file header;
955
- // parsers set pbc so the lattice conforms to Crystal's LatticeType
956
- structure = vol_result.structure as AnyStructure
957
- volumetric_data = vol_result.volumes
958
- // Auto-compute reasonable isosurface settings from data range
959
- const vol = vol_result.volumes[0]
960
- if (vol) {
961
- isosurface_settings = auto_isosurface_settings(vol.data_range)
962
- active_volume_idx = 0
963
- }
964
- return structure
965
- }
966
-
967
- // Parse file content, trying volumetric format first then falling back to plain structure.
968
- // Returns the parsed structure on success, throws on failure.
969
- function parse_file_content(text_content: string, filename: string): AnyStructure {
970
- clear_camera_state()
971
- const vol_struct = try_parse_volumetric(text_content, filename)
972
- if (vol_struct) return vol_struct
973
- // Clear stale volumetric data when loading a non-volumetric file
974
- volumetric_data = []
975
- const parsed = parse_any_structure(text_content, filename)
976
- if (!parsed) throw new Error(`Failed to parse structure from ${filename}`)
977
- structure = parsed
978
- return parsed
979
- }
980
-
981
- const handle_file_drop = create_file_drop_handler({
982
- allow: () => allow_file_drop,
983
- on_drop: (content, filename) => {
984
- if (on_file_drop) return on_file_drop(content, filename)
985
- try {
986
- const text_content = content instanceof ArrayBuffer
987
- ? new TextDecoder().decode(content)
988
- : content
989
- const parsed = parse_file_content(text_content, filename)
990
- emit_file_load_event(parsed, filename, content)
991
- } catch (err) {
992
- error_msg = `Failed to parse structure: ${
993
- err instanceof Error ? err.message : String(err)
994
- }`
995
- on_error?.({ error_msg, filename })
996
- }
997
- },
998
- on_error: (msg) => {
999
- error_msg = msg
1000
- on_error?.({ error_msg: msg })
1001
- },
1002
- set_loading: (val) => {
1003
- loading = val
1004
- if (val) [error_msg, dragover] = [undefined, false]
1005
- },
1006
- })
1007
-
1008
- function handle_keydown(event: KeyboardEvent) {
1009
- // Don't handle shortcuts if user is typing in an input field
1010
- const target = event.target as HTMLElement
1011
- const is_input_focused = target.tagName === `INPUT` ||
1012
- target.tagName === `TEXTAREA`
1013
-
1014
- // Allow Escape to cancel add-atom mode even when the element input is focused
1015
- if (event.key === `Escape` && measure_mode === `edit-atoms` && add_atom_mode) {
1016
- event.preventDefault()
1017
- add_atom_mode = false
1018
- return
1019
- }
1020
-
1021
- if (is_input_focused) return
1022
-
1023
- // Edit-atoms mode shortcuts (including undo/redo)
1024
- if (measure_mode === `edit-atoms`) {
1025
- // Undo/redo shortcuts (Ctrl/Cmd + Z/Y) — only active in edit-atoms mode
1026
- if (event.ctrlKey || event.metaKey) {
1027
- const key = event.key.toLowerCase()
1028
- if (key === `z` && !event.shiftKey) {
1029
- event.preventDefault()
1030
- undo()
1031
- show_toast(`Undo (${undo_stack.length} left)`)
1032
- return
1033
- } else if (key === `y` || (key === `z` && event.shiftKey)) {
1034
- event.preventDefault()
1035
- redo()
1036
- show_toast(`Redo (${redo_stack.length} left)`)
1037
- return
1038
- }
1039
- }
1040
-
1041
- if (event.key === `Delete` || event.key === `Backspace`) {
1042
- // Delete selected atoms
1043
- if (selected_sites.length > 0 && structure?.sites) {
1044
- event.preventDefault()
1045
- is_internal_edit = true
1046
- push_undo()
1047
- const to_delete = scene_to_structure_indices(selected_sites, true)
1048
- const n_deleted = to_delete.size
1049
- clear_selection()
1050
- structure = {
1051
- ...structure,
1052
- sites: structure.sites.filter((_, idx) => !to_delete.has(idx)),
1053
- }
1054
- // Clear per-site overrides since indices shifted after deletion
1055
- if (site_radius_overrides?.size > 0) site_radius_overrides.clear()
1056
- clear_bond_edits()
1057
- show_toast(`Deleted ${n_deleted} site${n_deleted > 1 ? `s` : ``}`)
1058
- }
1059
- return
1060
- }
1061
- const key = event.key.toLowerCase()
1062
- const plain = !event.ctrlKey && !event.metaKey && !event.altKey
1063
-
1064
- if (key === `a` && plain) {
1065
- // Enter add-atom sub-mode (plain 'a' only, not Ctrl+A/Cmd+A/Alt+A)
1066
- event.preventDefault()
1067
- add_atom_mode = !add_atom_mode
1068
- return
1069
- }
1070
- // Change element of selected atoms
1071
- if (key === `e` && plain && selected_sites.length > 0) {
1072
- event.preventDefault()
1073
- change_element_mode = !change_element_mode
1074
- return
1075
- }
1076
- // Duplicate selected atoms at a small offset
1077
- if (
1078
- key === `d` && (event.ctrlKey || event.metaKey) &&
1079
- selected_sites.length > 0 && structure?.sites
1080
- ) {
1081
- event.preventDefault()
1082
- is_internal_edit = true
1083
- push_undo()
1084
- const orig_indices = scene_to_structure_indices(selected_sites)
1085
- const cart_to_frac = get_cart_to_frac()
1086
- const new_sites = structure.sites
1087
- .filter((_, idx) => orig_indices.has(idx))
1088
- .map((site) => {
1089
- const new_xyz: Vec3 = [
1090
- site.xyz[0] + 0.5,
1091
- site.xyz[1] + 0.5,
1092
- site.xyz[2] + 0.5,
1093
- ]
1094
- return {
1095
- ...site,
1096
- xyz: new_xyz,
1097
- abc: cart_to_frac?.(new_xyz) ?? new_xyz,
1098
- properties: { ...site.properties },
1099
- }
1100
- })
1101
- const base_idx = structure.sites.length
1102
- structure = {
1103
- ...structure,
1104
- sites: [...structure.sites, ...new_sites],
1105
- }
1106
- // Select the newly duplicated atoms
1107
- selected_sites = new_sites.map((_, idx) => base_idx + idx)
1108
- measured_sites = [...selected_sites]
1109
- show_toast(
1110
- `Duplicated ${new_sites.length} site${new_sites.length > 1 ? `s` : ``}`,
1111
- )
1112
- return
1113
- }
1114
-
1115
- // add_atom_mode Escape is already handled above (before is_input_focused guard)
1116
- if (event.key === `Escape`) {
1117
- if (change_element_mode) {
1118
- change_element_mode = false
1119
- return
1120
- }
1121
- if (selected_sites.length > 0) {
1122
- clear_selection()
1123
- return
1124
- }
1125
- }
1126
- }
1127
-
1128
- // Interface shortcuts (require Ctrl/Cmd modifier to avoid accidental triggers)
1129
- const has_modifier = event.ctrlKey || event.metaKey
1130
- if (event.key === `f` && has_modifier && fullscreen_toggle) {
1131
- event.preventDefault()
1132
- toggle_fullscreen(wrapper)
1133
- } else if (event.key === `i` && has_modifier && enable_info_pane) {
1134
- event.preventDefault()
1135
- info_pane_open = !info_pane_open
1136
- } else if (event.key === `Escape`) {
1137
- // Prioritize closing panes, then exit edit modes, then exit fullscreen
1138
- if (info_pane_open) info_pane_open = false
1139
- else if (controls_open) controls_open = false
1140
- else if (export_pane_open) export_pane_open = false
1141
- else if (measure_mode === `edit-bonds` || measure_mode === `edit-atoms`) {
1142
- measure_mode = `distance`
1143
- }
1144
- }
1145
- }
1146
-
1147
- // === Edit-atoms mode helpers ===
1148
-
1149
- // Map scene indices (into displayed_structure) back to raw structure indices.
1150
- // Handles supercell atoms via orig_unit_cell_idx property.
1151
- // skip_image_atoms: when true, image atoms (PBC ghosts) are excluded from the result.
1152
- function scene_to_structure_indices(
1153
- scene_indices: number[],
1154
- skip_image_atoms = false,
1155
- ): SvelteSet<number> {
1156
- const result = new SvelteSet<number>()
1157
- for (const scene_idx of scene_indices) {
1158
- const displayed_site = displayed_structure?.sites?.[scene_idx]
1159
- if (!displayed_site) continue
1160
- if (skip_image_atoms && displayed_site.properties?.orig_site_idx != null) {
1161
- continue
1162
- }
1163
-
1164
- if (has_supercell && displayed_site.properties?.orig_unit_cell_idx != null) {
1165
- result.add(displayed_site.properties.orig_unit_cell_idx as number)
1166
- } else if (displayed_site.properties?.orig_site_idx != null) {
1167
- // Image atom (PBC ghost) — map back to its original site index
1168
- result.add(displayed_site.properties.orig_site_idx as number)
1169
- } else {
1170
- result.add(scene_idx)
1171
- }
1172
- }
1173
- return result
1174
- }
1175
-
1176
- // Try to create a Cartesian→fractional converter for the current structure's lattice
1177
- function get_cart_to_frac(): ((xyz: Vec3) => Vec3) | undefined {
1178
- if (!structure || !(`lattice` in structure)) return undefined
1179
- try {
1180
- return create_cart_to_frac((structure as Crystal).lattice.matrix)
1181
- } catch {
1182
- console.warn(`Failed to compute lattice inverse for fractional coordinates`)
1183
- return undefined
1184
- }
1185
- }
1186
-
1187
- // Handle atom moves from TransformControls. Applies Cartesian delta and wraps
1188
- // fractional coords inline so normalize_fractional_coords hits its fast path.
1189
- function handle_sites_moved(scene_indices: number[], delta: Vec3) {
1190
- if (!structure?.sites) return
1191
- is_internal_edit = true
1192
-
1193
- const orig_indices = scene_to_structure_indices(scene_indices)
1194
- // For crystals, wrap to [0,1) inline so normalize_fractional_coords fast-paths.
1195
- // For molecules (no lattice), just apply the Cartesian delta directly.
1196
- const lattice = `lattice` in structure
1197
- ? (structure as Crystal).lattice.matrix
1198
- : null
1199
- const cart_to_frac = lattice ? create_cart_to_frac(lattice) : null
1200
- const frac_to_cart = lattice ? create_frac_to_cart(lattice) : null
1201
- structure = {
1202
- ...structure,
1203
- sites: structure.sites.map((site, idx) => {
1204
- if (!orig_indices.has(idx)) return site
1205
- const new_xyz: Vec3 = [
1206
- site.xyz[0] + delta[0],
1207
- site.xyz[1] + delta[1],
1208
- site.xyz[2] + delta[2],
1209
- ]
1210
- if (!cart_to_frac || !frac_to_cart) {
1211
- return { ...site, xyz: new_xyz, abc: new_xyz }
1212
- }
1213
- const wrapped_abc = wrap_to_unit_cell(cart_to_frac(new_xyz))
1214
- return { ...site, xyz: frac_to_cart(wrapped_abc), abc: wrapped_abc }
1215
- }),
1216
- }
1217
- }
1218
-
1219
- // Change element symbol of selected atoms
1220
- function handle_change_element(new_element: string) {
1221
- if (!structure?.sites || selected_sites.length === 0) return
1222
- const elem = normalize_element(new_element)
1223
- if (!elem) return
1224
- is_internal_edit = true
1225
- push_undo()
1226
- const orig_indices = scene_to_structure_indices(selected_sites)
1227
- structure = {
1228
- ...structure,
1229
- sites: structure.sites.map((site, idx) => {
1230
- if (!orig_indices.has(idx)) return site
1231
- return {
1232
- ...site,
1233
- species: [{ element: elem, occu: 1, oxidation_state: 0 }],
1234
- label: elem,
1235
- }
1236
- }),
1237
- }
1238
- change_element_mode = false
1239
- change_element_value = ``
1240
- show_toast(
1241
- `Changed ${orig_indices.size} site${
1242
- orig_indices.size > 1 ? `s` : ``
1243
- } to ${elem}`,
1244
- )
1245
- }
1246
-
1247
- // Handle add-atom from StructureScene click-to-place
1248
- function handle_add_atom(xyz: Vec3, element: ElementSymbol) {
1249
- if (!structure) return
1250
- const elem = normalize_element(element)
1251
- if (!elem) {
1252
- return console.warn(`Invalid element symbol "${element}", ignoring add-atom`)
1253
- }
1254
- is_internal_edit = true
1255
- push_undo()
1256
- structure = {
1257
- ...structure,
1258
- sites: [...structure.sites, {
1259
- species: [{ element: elem, occu: 1, oxidation_state: 0 }],
1260
- xyz,
1261
- abc: get_cart_to_frac()?.(xyz) ?? xyz,
1262
- label: elem,
1263
- properties: {},
1264
- }],
1265
- }
1266
- show_toast(`Added ${elem} at (${xyz.map((c) => c.toFixed(2)).join(`, `)})`)
1267
- }
1268
-
1269
- // Only set background override when background_color is explicitly provided
1270
- $effect(() => {
1271
- if (typeof window !== `undefined` && wrapper && background_color) {
1272
- // Convert opacity (0-1) to hex alpha value (00-FF)
1273
- const alpha_hex = Math.round(background_opacity * 255)
1274
- .toString(16)
1275
- .padStart(2, `0`)
1276
- wrapper.style.setProperty(
1277
- `--struct-bg-override`,
1278
- `${background_color}${alpha_hex}`,
1279
- )
1280
- } else if (typeof window !== `undefined` && wrapper) {
1281
- // Remove override to use theme system
1282
- wrapper.style.removeProperty(`--struct-bg-override`)
1283
- }
1284
- })
1285
-
1286
- $effect(() => { // fullscreen and background
1287
- if (typeof window !== `undefined`) {
1288
- if (fullscreen && !document.fullscreenElement && wrapper) {
1289
- wrapper.requestFullscreen().catch(console.error)
1290
- } else if (!fullscreen && document.fullscreenElement) {
1291
- document.exitFullscreen()
1292
- }
1293
- }
1294
- set_fullscreen_bg(wrapper, fullscreen, `--struct-bg-fullscreen`)
1295
- })
1296
- </script>
1297
-
1298
- <svelte:document
1299
- onfullscreenchange={() => {
1300
- fullscreen = Boolean(document.fullscreenElement)
1301
- on_fullscreen_change?.({ structure, fullscreen })
1302
- }}
1303
- />
1304
-
1305
- <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
1306
- <div
1307
- class:dragover
1308
- class:active={info_pane_open || controls_open || export_pane_open}
1309
- role="application"
1310
- tabindex="0"
1311
- style:--canvas-cursor={canvas_cursor}
1312
- aria-label="Structure viewer"
1313
- bind:this={wrapper}
1314
- bind:clientWidth={width}
1315
- bind:clientHeight={height}
1316
- onmouseenter={() => (hovered = true)}
1317
- onmouseleave={() => (hovered = false)}
1318
- ondblclick={(event) => {
1319
- const target = event.target as HTMLElement
1320
- // Don't reset if double-click was on UI controls/panes/legend
1321
- if (
1322
- target.closest(`.control-buttons`) ||
1323
- target.closest(`.structure-legend`) ||
1324
- target.closest(`.atom-legend`) ||
1325
- target.closest(`.info-pane`) ||
1326
- target.closest(`.export-pane`) ||
1327
- target.closest(`.controls-pane`) ||
1328
- target.tagName === `BUTTON` ||
1329
- target.tagName === `INPUT` ||
1330
- target.tagName === `SELECT`
1331
- ) return
1332
- // Reset camera for double-clicks on the 3D scene
1333
- reset_camera()
1334
- }}
1335
- ondrop={handle_file_drop}
1336
- ondragover={(event) => {
1337
- event.preventDefault()
1338
- if (!allow_file_drop) return
1339
- dragover = true
1340
- }}
1341
- ondragleave={(event) => {
1342
- event.preventDefault()
1343
- dragover = false
1344
- }}
1345
- onkeydown={handle_keydown}
1346
- {...rest}
1347
- class="structure {rest.class ?? ``}"
1348
- >
1349
- {@render children?.({ structure, fullscreen })}
1350
- {#if loading}
1351
- <Spinner
1352
- text="Loading structure..."
1353
- {...spinner_props}
1354
- style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)"
1355
- />
1356
- {:else if error_msg}
1357
- <StatusMessage bind:message={error_msg} type="error" dismissible />
1358
- {:else if (structure?.sites?.length ?? 0) > 0}
1359
- <section
1360
- class="control-buttons {controls_config.class}"
1361
- style={controls_config.style}
1362
- >
1363
- {#if controls_config.mode !== `never`}
1364
- {#if camera_has_moved && controls_config.visible(`reset-camera`)}
1365
- <button class="reset-camera" onclick={reset_camera} title={reset_text}>
1366
- <!-- Target/Focus icon for reset camera -->
1367
- <Icon icon="Reset" />
1368
- </button>
1369
- {/if}
1370
- {#if fullscreen_toggle && controls_config.visible(`fullscreen`)}
1371
- <button
1372
- type="button"
1373
- onclick={() => fullscreen_toggle && toggle_fullscreen(wrapper)}
1374
- title="{fullscreen ? `Exit` : `Enter`} fullscreen"
1375
- aria-pressed={fullscreen}
1376
- class="fullscreen-toggle"
1377
- style="padding: 0 3px"
1378
- {@attach tooltip()}
1379
- >
1380
- {#if typeof fullscreen_toggle === `function`}
1381
- {@render fullscreen_toggle({ fullscreen })}
1382
- {:else}
1383
- <Icon icon="{fullscreen ? `Exit` : ``}Fullscreen" />
1384
- {/if}
1385
- </button>
1386
- {/if}
1387
-
1388
- {#if enable_measure_mode && controls_config.visible(`measure-mode`)}
1389
- <div
1390
- class="measure-mode-dropdown"
1391
- {@attach click_outside({ callback: () => measure_menu_open = false })}
1392
- >
1393
- <button
1394
- onclick={() => (measure_menu_open = !measure_menu_open)}
1395
- title="Measure / Edit"
1396
- class="view-mode-button"
1397
- class:active={measure_menu_open}
1398
- aria-expanded={measure_menu_open}
1399
- style="transform: scale(1.2)"
1400
- >
1401
- {#if (measured_sites?.length ?? 0) >= MAX_SELECTED_SITES}
1402
- <span class="selection-limit-text">
1403
- {measured_sites.length}/{MAX_SELECTED_SITES}
1404
- </span>
1405
- {:else}
1406
- <Icon
1407
- icon={({
1408
- distance: `Ruler`,
1409
- angle: `Angle`,
1410
- 'edit-bonds': `Link`,
1411
- 'edit-atoms': `Edit`,
1412
- } as const)[measure_mode]}
1413
- />
1414
- {/if}
1415
- <Icon
1416
- icon="Arrow{measure_menu_open ? `Up` : `Down`}"
1417
- style="margin-left: -2px"
1418
- />
1419
- </button>
1420
- {#if (measured_sites?.length ?? 0) > 0 || has_bond_edits}
1421
- <button
1422
- type="button"
1423
- aria-label="Reset selection and bond edits"
1424
- onclick={() => {
1425
- clear_selection()
1426
- clear_bond_edits()
1427
- }}
1428
- >
1429
- <Icon icon="Reset" style="margin-left: -4px" />
1430
- </button>
1431
- {/if}
1432
- {#if measure_menu_open}
1433
- <div class="view-mode-dropdown">
1434
- {#each [
1435
- { mode: `distance`, icon: `Ruler`, label: `Distance`, scale: 1.1 },
1436
- { mode: `angle`, icon: `Angle`, label: `Angle`, scale: 1.3 },
1437
- {
1438
- mode: `edit-atoms`,
1439
- icon: `Edit`,
1440
- label: `Edit Atoms`,
1441
- scale: 1.0,
1442
- },
1443
- {
1444
- mode: `edit-bonds`,
1445
- icon: `Link`,
1446
- label: `Edit Bonds`,
1447
- scale: 1.0,
1448
- },
1449
- ] as const as
1450
- { mode, icon, label, scale }
1451
- (mode)
1452
- }
1453
- <button
1454
- class="view-mode-option"
1455
- class:selected={measure_mode === mode}
1456
- disabled={mode === `edit-bonds` && !bond_edits_enabled}
1457
- title={mode === `edit-bonds` && !bond_edits_enabled
1458
- ? `Bond editing is only available for the original 1x1x1 cell`
1459
- : label}
1460
- onclick={() => {
1461
- if (mode === `edit-bonds` && !bond_edits_enabled) return
1462
- ;[measure_mode, measure_menu_open] = [mode, false]
1463
- }}
1464
- >
1465
- <Icon {icon} style="transform: scale({scale})" />
1466
- <span>{@html sanitize_html(label)}</span>
1467
- </button>
1468
- {/each}
1469
- </div>
1470
- {/if}
1471
- </div>
1472
-
1473
- <!-- Undo/redo buttons (only in edit-atoms mode) -->
1474
- {#if measure_mode === `edit-atoms`}
1475
- <div class="undo-redo-container">
1476
- <button
1477
- type="button"
1478
- aria-label="Undo (Ctrl+Z)"
1479
- disabled={undo_stack.length === 0}
1480
- onclick={undo}
1481
- title="Undo (Ctrl+Z)"
1482
- class="undo-redo-btn"
1483
- >
1484
- <Icon icon="Undo" />
1485
- {#if undo_stack.length > 0}
1486
- <span class="history-count">{undo_stack.length}</span>
1487
- {/if}
1488
- </button>
1489
- <button
1490
- type="button"
1491
- aria-label="Redo (Ctrl+Y)"
1492
- disabled={redo_stack.length === 0}
1493
- onclick={redo}
1494
- title="Redo (Ctrl+Y)"
1495
- class="undo-redo-btn"
1496
- >
1497
- <Icon icon="Redo" />
1498
- {#if redo_stack.length > 0}
1499
- <span class="history-count">{redo_stack.length}</span>
1500
- {/if}
1501
- </button>
1502
- </div>
1503
- {/if}
1504
-
1505
- <!-- Add-atom element input (shown when add_atom_mode is active) -->
1506
- {#if measure_mode === `edit-atoms` && add_atom_mode}
1507
- <div class="add-atom-input">
1508
- <label>
1509
- <span>Element:</span>
1510
- <input
1511
- type="text"
1512
- bind:value={add_element}
1513
- maxlength="2"
1514
- placeholder="C"
1515
- style="width: 3em; text-align: center"
1516
- />
1517
- </label>
1518
- <span style="font-size: 0.75em; opacity: 0.7">Click to place</span>
1519
- </div>
1520
- {/if}
1521
-
1522
- <!-- Change-element input (shown when 'e' pressed with selection) -->
1523
- {#if measure_mode === `edit-atoms` && change_element_mode &&
1524
- selected_sites.length > 0}
1525
- <div class="add-atom-input">
1526
- <label>
1527
- <span>New element:</span>
1528
- <input
1529
- type="text"
1530
- bind:value={change_element_value}
1531
- maxlength="2"
1532
- placeholder="Fe"
1533
- style="width: 3em; text-align: center"
1534
- onkeydown={(event: KeyboardEvent) => {
1535
- if (event.key === `Enter`) {
1536
- handle_change_element(change_element_value)
1537
- } else if (event.key === `Escape`) {
1538
- change_element_mode = false
1539
- }
1540
- event.stopPropagation()
1541
- }}
1542
- {@attach (node: HTMLInputElement) => {
1543
- node.focus()
1544
- }}
1545
- />
1546
- </label>
1547
- <span style="font-size: 0.75em; opacity: 0.7">Enter to apply</span>
1548
- </div>
1549
- {/if}
1550
- {/if}
1551
-
1552
- {#if enable_info_pane && normalized_structure &&
1553
- controls_config.visible(`info-pane`)}
1554
- <StructureInfoPane
1555
- structure={normalized_structure}
1556
- bind:pane_open={info_pane_open}
1557
- bind:highlighted_sites
1558
- bind:hovered_site_idx
1559
- bind:selected_sites
1560
- {sym_data}
1561
- {@attach tooltip({ content: `Structure info pane` })}
1562
- />
1563
- {/if}
1564
-
1565
- {#if controls_config.visible(`export-pane`)}
1566
- <StructureExportPane
1567
- bind:export_pane_open
1568
- structure={normalized_structure}
1569
- {wrapper}
1570
- {scene}
1571
- {camera}
1572
- bind:png_dpi
1573
- pane_props={{ style: `max-height: calc(${height}px - 50px)` }}
1574
- />
1575
- {/if}
1576
-
1577
- {#if controls_config.visible(`controls`)}
1578
- <StructureControls
1579
- bind:controls_open
1580
- bind:scene_props
1581
- bind:lattice_props
1582
- bind:show_image_atoms
1583
- bind:supercell_scaling
1584
- bind:background_color
1585
- bind:background_opacity
1586
- bind:color_scheme
1587
- bind:atom_color_config
1588
- bind:cell_type
1589
- bind:volumetric_data
1590
- bind:isosurface_settings
1591
- bind:active_volume_idx
1592
- {structure}
1593
- {supercell_loading}
1594
- {sym_data}
1595
- />
1596
- {/if}
1597
-
1598
- {@render top_right_controls?.()}
1599
- {/if}
1600
- </section>
1601
-
1602
- <AtomLegend
1603
- bind:atom_color_config
1604
- {property_colors}
1605
- elements={get_element_counts(supercell_structure ?? structure!)}
1606
- bind:hidden_elements
1607
- bind:hidden_prop_vals
1608
- bind:element_mapping
1609
- bind:element_radius_overrides
1610
- bind:site_radius_overrides
1611
- {selected_sites}
1612
- structure={displayed_structure}
1613
- {sym_data}
1614
- >
1615
- {#if structure && `lattice` in structure}
1616
- <CellSelect
1617
- bind:supercell_scaling
1618
- bind:cell_type
1619
- {sym_data}
1620
- loading={supercell_loading}
1621
- direction="up"
1622
- />
1623
- {/if}
1624
- </AtomLegend>
1625
-
1626
- <!-- prevent from rendering in vitest runner since WebGLRenderingContext not available -->
1627
- {#if typeof WebGLRenderingContext !== `undefined`}
1628
- <!-- prevent HTML labels from rendering outside of the canvas -->
1629
- <div style="overflow: hidden; height: 100%; width: 100%">
1630
- <Canvas>
1631
- <StructureScene
1632
- structure={displayed_structure}
1633
- base_structure={cell_transformed_structure}
1634
- {...scene_props}
1635
- {lattice_props}
1636
- volumetric_data={supercell_volume}
1637
- {isosurface_settings}
1638
- bind:camera_is_moving
1639
- bind:selected_sites
1640
- active_sites={active_scene_sites}
1641
- bind:hovered_idx={hovered_site_idx}
1642
- bind:measured_sites
1643
- bind:scene
1644
- bind:camera
1645
- bind:orbit_controls
1646
- bind:rotation_target_ref
1647
- bind:initial_computed_zoom
1648
- bind:hidden_elements
1649
- bind:hidden_prop_vals
1650
- bind:element_radius_overrides
1651
- bind:site_radius_overrides
1652
- bind:added_bonds
1653
- bind:removed_bonds
1654
- bind:bond_order_overrides
1655
- {bond_edits_enabled}
1656
- {measure_mode}
1657
- {width}
1658
- {height}
1659
- {atom_color_config}
1660
- {sym_data}
1661
- on_sites_moved={handle_sites_moved}
1662
- on_operation_start={push_undo}
1663
- on_add_atom={handle_add_atom}
1664
- bind:add_atom_mode
1665
- bind:add_element
1666
- bind:cursor={canvas_cursor}
1667
- bind:dragging_atoms
1668
- />
1669
- </Canvas>
1670
- </div>
1671
- {/if}
1672
-
1673
- <div class="bottom-left">
1674
- {@render bottom_left?.({ structure: displayed_structure })}
1675
- </div>
1676
-
1677
- {#if toast_msg}
1678
- <div class="edit-toast">{toast_msg}</div>
1679
- {/if}
1680
-
1681
- {#if measure_mode === `edit-bonds` && has_bond_edits}
1682
- <div class="bond-edit-status">
1683
- {#if added_bonds.length > 0}
1684
- <span class="added">+{added_bonds.length} added</span>
1685
- {/if}
1686
- {#if removed_bonds.length > 0}
1687
- <span class="removed">-{removed_bonds.length} removed</span>
1688
- {/if}
1689
- {#if bond_order_overrides.length > 0}
1690
- <span class="changed">{bond_order_overrides.length} ordered</span>
1691
- {/if}
1692
- </div>
1693
- {/if}
1694
-
1695
- {#if symmetry_error}
1696
- <div class="symmetry-error">
1697
- <span>{symmetry_error}</span>
1698
- <button onclick={() => (symmetry_error = undefined)} aria-label="Dismiss">
1699
- ×
1700
- </button>
1701
- </div>
1702
- {/if}
1703
- {:else if structure}
1704
- <p class="warn">No sites found in structure</p>
1705
- {:else}
1706
- <p class="warn">No structure provided</p>
1707
- {/if}
1708
- </div>
1709
-
1710
- <style>
1711
- .structure {
1712
- position: relative;
1713
- container-type: size; /* enable cqh/cqw for internal panes */
1714
- height: var(--struct-height, 500px);
1715
- width: var(--struct-width, 100%);
1716
- max-width: var(--struct-max-width, 100%);
1717
- min-width: var(--struct-min-width, 300px);
1718
- border-radius: var(--struct-border-radius, var(--border-radius, 3pt));
1719
- background: var(--struct-bg-override, var(--struct-bg));
1720
- color: var(--struct-text-color);
1721
- display: flex;
1722
- }
1723
- .structure.active {
1724
- z-index: var(--struct-active-z-index, 2);
1725
- }
1726
- .structure:fullscreen {
1727
- background: var(--struct-bg-fullscreen, var(--struct-bg));
1728
- overflow: hidden;
1729
- }
1730
- .structure:fullscreen :global(canvas) {
1731
- height: 100vh !important;
1732
- width: 100vw !important;
1733
- }
1734
- .structure.dragover {
1735
- background: var(--struct-dragover-bg, var(--dragover-bg));
1736
- border: var(--struct-dragover-border, var(--dragover-border));
1737
- }
1738
- /* Ensure canvas is transparent so the themed --struct-bg shows through */
1739
- .structure :global(canvas) {
1740
- background: transparent;
1741
- cursor: var(--canvas-cursor, default);
1742
- }
1743
- /* Avoid accidental text selection while interacting with the viewer */
1744
- .structure :global(canvas),
1745
- .structure section.control-buttons,
1746
- .structure .bottom-left {
1747
- user-select: none;
1748
- }
1749
- div.bottom-left {
1750
- position: absolute;
1751
- bottom: 0;
1752
- left: 0;
1753
- font-size: var(--struct-bottom-left-font-size, 1.2em);
1754
- padding: var(--struct-bottom-left-padding, 1pt 5pt);
1755
- }
1756
- section.control-buttons {
1757
- position: absolute;
1758
- display: flex;
1759
- top: var(--struct-buttons-top, var(--ctrl-btn-top, 1ex));
1760
- right: var(--struct-buttons-right, var(--ctrl-btn-right, 1ex));
1761
- gap: 4pt;
1762
- /* buttons need higher z-index than AtomLegend to make info/controls panes occlude legend */
1763
- /* we also need crazy high z-index to make info/control pane occlude threlte/extras' <HTML> elements for site labels */
1764
- z-index: var(
1765
- --struct-buttons-z-index,
1766
- var(--z-index-overlay-controls, 100000000)
1767
- );
1768
- opacity: 0;
1769
- pointer-events: none;
1770
- transition: opacity 0.2s ease;
1771
- }
1772
- /* Mode: always - controls always visible */
1773
- section.control-buttons.always-visible {
1774
- opacity: 1;
1775
- pointer-events: auto;
1776
- }
1777
- /* Mode: hover - controls visible on component hover */
1778
- .structure:hover section.control-buttons.hover-visible,
1779
- .structure:focus-within section.control-buttons.hover-visible {
1780
- opacity: 1;
1781
- pointer-events: auto;
1782
- }
1783
- /* Mode: never - stays hidden (default state, no additional CSS needed) */
1784
- section.control-buttons > :global(button) {
1785
- background-color: transparent;
1786
- display: flex;
1787
- padding: 1px 6px;
1788
- border-radius: var(--border-radius, 3pt);
1789
- font-size: clamp(0.85em, 2cqmin, 1.3em);
1790
- }
1791
- section.control-buttons :global(button:hover) {
1792
- background-color: color-mix(in srgb, currentColor 8%, transparent);
1793
- }
1794
- /* Match Trajectory dropdown UI */
1795
- .view-mode-dropdown {
1796
- position: absolute;
1797
- top: 115%;
1798
- right: 0;
1799
- background: var(--surface-bg);
1800
- border-radius: var(--border-radius, 3pt);
1801
- box-shadow: 0 8px 16px -4px rgba(0, 0, 0, 0.3), 0 4px 8px -2px rgba(0, 0, 0, 0.1);
1802
- display: flex;
1803
- flex-direction: column;
1804
- }
1805
- .view-mode-option {
1806
- display: flex;
1807
- align-items: center;
1808
- gap: 1ex;
1809
- width: 100%;
1810
- padding: var(--trajectory-view-mode-option-padding, 5pt);
1811
- box-sizing: border-box;
1812
- background: transparent;
1813
- border-radius: 0;
1814
- text-align: left;
1815
- transition: background-color 0.15s ease;
1816
- }
1817
- .view-mode-option:first-child {
1818
- border-top-left-radius: 3px;
1819
- border-top-right-radius: 3px;
1820
- }
1821
- .view-mode-option.selected {
1822
- color: var(--accent-color);
1823
- }
1824
- .view-mode-option span {
1825
- font-weight: 500;
1826
- white-space: nowrap;
1827
- overflow: hidden;
1828
- text-overflow: ellipsis;
1829
- flex: 1;
1830
- }
1831
- .measure-mode-dropdown {
1832
- display: flex;
1833
- position: relative;
1834
- height: fit-content;
1835
- place-self: center;
1836
- }
1837
- .measure-mode-dropdown > button {
1838
- background: transparent;
1839
- padding: 1px 6px;
1840
- font-size: clamp(0.85em, 2cqmin, 1.3em);
1841
- }
1842
- .selection-limit-text {
1843
- font-weight: bold;
1844
- font-size: 0.9em;
1845
- color: var(--accent-color, #ff6b6b);
1846
- min-width: 2.5em;
1847
- text-align: center;
1848
- }
1849
- p.warn {
1850
- position: absolute;
1851
- inset: 0;
1852
- display: grid;
1853
- place-content: center;
1854
- }
1855
- .symmetry-error {
1856
- position: absolute;
1857
- bottom: 1rem;
1858
- right: 1rem;
1859
- background: rgba(255, 165, 0, 0.95);
1860
- color: #000;
1861
- padding: 0.75rem 1rem;
1862
- border-radius: var(--border-radius, 3pt);
1863
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1864
- display: flex;
1865
- gap: 1rem;
1866
- max-width: min(90%, 400px);
1867
- font-size: 0.9rem;
1868
- z-index: 1000;
1869
- }
1870
- .symmetry-error span {
1871
- flex: 1;
1872
- }
1873
- .symmetry-error button {
1874
- background: transparent;
1875
- border: none;
1876
- font-size: 1.5rem;
1877
- line-height: 1;
1878
- padding: 0;
1879
- cursor: pointer;
1880
- opacity: 0.7;
1881
- }
1882
- .symmetry-error button:hover {
1883
- opacity: 1;
1884
- }
1885
- .edit-toast {
1886
- position: absolute;
1887
- bottom: 3rem;
1888
- left: 50%;
1889
- transform: translateX(-50%);
1890
- background: color-mix(in srgb, var(--page-bg, Canvas) 85%, currentColor);
1891
- color: var(--text-color, currentColor);
1892
- padding: 0.4rem 0.8rem;
1893
- border-radius: var(--border-radius, 3pt);
1894
- font-size: 0.8rem;
1895
- z-index: 100;
1896
- pointer-events: none;
1897
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
1898
- animation: toast-fade 2s ease-in-out;
1899
- opacity: 0;
1900
- }
1901
- @keyframes toast-fade {
1902
- 0%, 70% {
1903
- opacity: 1;
1904
- }
1905
- 100% {
1906
- opacity: 0;
1907
- }
1908
- }
1909
- .bond-edit-status {
1910
- position: absolute;
1911
- bottom: 1rem;
1912
- left: 50%;
1913
- transform: translateX(-50%);
1914
- background: color-mix(in srgb, var(--page-bg, Canvas) 85%, currentColor);
1915
- color: var(--text-color, currentColor);
1916
- padding: 0.5rem 1rem;
1917
- border-radius: var(--border-radius, 3pt);
1918
- font-size: 0.85rem;
1919
- display: flex;
1920
- gap: 0.75rem;
1921
- z-index: 100;
1922
- pointer-events: none;
1923
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
1924
- }
1925
- .bond-edit-status .added {
1926
- color: #4caf50;
1927
- font-weight: bold;
1928
- }
1929
- .bond-edit-status .removed {
1930
- color: #f44336;
1931
- font-weight: bold;
1932
- }
1933
- .bond-edit-status .changed {
1934
- color: var(--accent-color, #007acc);
1935
- font-weight: bold;
1936
- }
1937
- /* CellSelect: position at left of legend, show on hover */
1938
- .structure :global(.cell-select) {
1939
- order: -1; /* Move to left side of AtomLegend flex container */
1940
- opacity: 0;
1941
- pointer-events: none;
1942
- transition: opacity 0.3s ease;
1943
- }
1944
- .structure:hover :global(.cell-select) {
1945
- opacity: 1;
1946
- pointer-events: auto;
1947
- }
1948
- .undo-redo-container {
1949
- display: flex;
1950
- }
1951
- .undo-redo-btn {
1952
- position: relative;
1953
- display: flex;
1954
- align-items: center;
1955
- justify-content: center;
1956
- }
1957
- .history-count {
1958
- position: absolute;
1959
- bottom: -2px;
1960
- right: -2px;
1961
- background: var(--accent-color, #007acc);
1962
- color: white;
1963
- border-radius: 50%;
1964
- width: 12px;
1965
- height: 12px;
1966
- font-size: 8px;
1967
- font-weight: bold;
1968
- display: flex;
1969
- align-items: center;
1970
- justify-content: center;
1971
- line-height: 1;
1972
- pointer-events: none;
1973
- z-index: 1;
1974
- }
1975
- .add-atom-input {
1976
- display: flex;
1977
- align-items: center;
1978
- gap: 0.5em;
1979
- background: color-mix(in srgb, var(--page-bg, Canvas) 85%, currentColor);
1980
- color: var(--text-color, currentColor);
1981
- padding: 0.3em 0.6em;
1982
- border-radius: var(--border-radius, 3pt);
1983
- font-size: 0.8rem;
1984
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
1985
- label {
1986
- display: flex;
1987
- align-items: center;
1988
- gap: 0.3em;
1989
- }
1990
- input {
1991
- background: color-mix(in srgb, currentColor 10%, transparent);
1992
- border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
1993
- border-radius: 3px;
1994
- color: inherit;
1995
- font-size: 0.85rem;
1996
- padding: 0.1em 0.3em;
1997
- }
1998
- }
1999
- </style>