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