matterviz 0.3.5 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (855) hide show
  1. package/.vscode/launch.json +13 -0
  2. package/.vscodeignore +7 -0
  3. package/dist/assets/STLExporter-BpTH3YHE.js +8 -0
  4. package/dist/assets/browser-DdDecX_W.js +1 -0
  5. package/dist/assets/export-qgn-H9y6.js +2 -0
  6. package/dist/assets/main-DiKYzti2.css +1 -0
  7. package/dist/assets/moyo_wasm_bg-0ocwg7xY.wasm +0 -0
  8. package/dist/extension.js +31293 -0
  9. package/dist/src/lib/FilePicker.svelte +360 -0
  10. package/dist/src/lib/MillerIndexInput.svelte +66 -0
  11. package/dist/src/lib/api/mp.ts +26 -0
  12. package/dist/src/lib/api/optimade.ts +204 -0
  13. package/dist/src/lib/brillouin/BrillouinZone.svelte +549 -0
  14. package/dist/src/lib/brillouin/BrillouinZoneControls.svelte +144 -0
  15. package/dist/src/lib/brillouin/BrillouinZoneExportPane.svelte +146 -0
  16. package/dist/src/lib/brillouin/BrillouinZoneInfoPane.svelte +146 -0
  17. package/dist/src/lib/brillouin/BrillouinZoneScene.svelte +476 -0
  18. package/dist/src/lib/brillouin/BrillouinZoneTooltip.svelte +92 -0
  19. package/dist/src/lib/brillouin/compute.ts +529 -0
  20. package/dist/src/lib/brillouin/index.ts +8 -0
  21. package/dist/src/lib/brillouin/types.ts +51 -0
  22. package/dist/src/lib/chempot-diagram/ChemPotDiagram.svelte +327 -0
  23. package/dist/src/lib/chempot-diagram/ChemPotDiagram2D.svelte +846 -0
  24. package/dist/src/lib/chempot-diagram/ChemPotDiagram3D.svelte +3193 -0
  25. package/dist/src/lib/chempot-diagram/async-compute.svelte.ts +94 -0
  26. package/dist/src/lib/chempot-diagram/chempot-worker.ts +11 -0
  27. package/dist/src/lib/chempot-diagram/color.ts +42 -0
  28. package/dist/src/lib/chempot-diagram/compute.ts +1014 -0
  29. package/dist/src/lib/chempot-diagram/index.ts +6 -0
  30. package/dist/src/lib/chempot-diagram/pointer.ts +56 -0
  31. package/dist/src/lib/chempot-diagram/temperature.ts +77 -0
  32. package/dist/src/lib/chempot-diagram/types.ts +130 -0
  33. package/dist/src/lib/colors/index.ts +249 -0
  34. package/dist/src/lib/composition/BarChart.svelte +297 -0
  35. package/dist/src/lib/composition/BubbleChart.svelte +218 -0
  36. package/dist/src/lib/composition/Composition.svelte +165 -0
  37. package/dist/src/lib/composition/Formula.svelte +268 -0
  38. package/dist/src/lib/composition/FormulaFilter.svelte +1257 -0
  39. package/dist/src/lib/composition/PieChart.svelte +323 -0
  40. package/dist/src/lib/composition/format.ts +155 -0
  41. package/dist/src/lib/composition/index.ts +37 -0
  42. package/dist/src/lib/composition/parse.ts +605 -0
  43. package/dist/src/lib/constants.ts +134 -0
  44. package/dist/src/lib/controls.ts +42 -0
  45. package/dist/src/lib/convex-hull/ConvexHull.svelte +157 -0
  46. package/dist/src/lib/convex-hull/ConvexHull2D.svelte +825 -0
  47. package/dist/src/lib/convex-hull/ConvexHull3D.svelte +1801 -0
  48. package/dist/src/lib/convex-hull/ConvexHull4D.svelte +1398 -0
  49. package/dist/src/lib/convex-hull/ConvexHullControls.svelte +535 -0
  50. package/dist/src/lib/convex-hull/ConvexHullInfoPane.svelte +125 -0
  51. package/dist/src/lib/convex-hull/ConvexHullStats.svelte +929 -0
  52. package/dist/src/lib/convex-hull/ConvexHullTooltip.svelte +131 -0
  53. package/dist/src/lib/convex-hull/GasPressureControls.svelte +247 -0
  54. package/dist/src/lib/convex-hull/StructurePopup.svelte +151 -0
  55. package/dist/src/lib/convex-hull/TemperatureSlider.svelte +140 -0
  56. package/dist/src/lib/convex-hull/barycentric-coords.ts +246 -0
  57. package/dist/src/lib/convex-hull/demo-temperature.ts +63 -0
  58. package/dist/src/lib/convex-hull/gas-thermodynamics.ts +405 -0
  59. package/dist/src/lib/convex-hull/helpers.ts +932 -0
  60. package/dist/src/lib/convex-hull/index.ts +202 -0
  61. package/dist/src/lib/convex-hull/thermodynamics.ts +2192 -0
  62. package/dist/src/lib/convex-hull/types.ts +267 -0
  63. package/dist/src/lib/coordination/CoordinationBarPlot.svelte +311 -0
  64. package/dist/src/lib/coordination/calc-coordination.ts +93 -0
  65. package/dist/src/lib/coordination/index.ts +9 -0
  66. package/dist/src/lib/effects.svelte.ts +48 -0
  67. package/dist/src/lib/element/BohrAtom.svelte +147 -0
  68. package/dist/src/lib/element/ElementHeading.svelte +26 -0
  69. package/dist/src/lib/element/ElementPhoto.svelte +57 -0
  70. package/dist/src/lib/element/ElementStats.svelte +80 -0
  71. package/dist/src/lib/element/ElementTile.svelte +484 -0
  72. package/dist/src/lib/element/data.json.gz.d.ts +4 -0
  73. package/dist/src/lib/element/data.ts +14 -0
  74. package/dist/src/lib/element/index.ts +8 -0
  75. package/dist/src/lib/element/types.ts +62 -0
  76. package/dist/src/lib/feedback/ClickFeedback.svelte +58 -0
  77. package/dist/src/lib/feedback/DragOverlay.svelte +42 -0
  78. package/dist/src/lib/feedback/index.ts +4 -0
  79. package/dist/src/lib/fermi-surface/FermiSlice.svelte +189 -0
  80. package/dist/src/lib/fermi-surface/FermiSurface.svelte +600 -0
  81. package/dist/src/lib/fermi-surface/FermiSurfaceControls.svelte +448 -0
  82. package/dist/src/lib/fermi-surface/FermiSurfaceScene.svelte +794 -0
  83. package/dist/src/lib/fermi-surface/FermiSurfaceTooltip.svelte +111 -0
  84. package/dist/src/lib/fermi-surface/compute.ts +728 -0
  85. package/dist/src/lib/fermi-surface/constants.ts +32 -0
  86. package/dist/src/lib/fermi-surface/export.ts +64 -0
  87. package/dist/src/lib/fermi-surface/index.ts +14 -0
  88. package/dist/src/lib/fermi-surface/marching-cubes.ts +3 -0
  89. package/dist/src/lib/fermi-surface/parse.ts +574 -0
  90. package/dist/src/lib/fermi-surface/symmetry.ts +56 -0
  91. package/dist/src/lib/fermi-surface/types.ts +159 -0
  92. package/dist/src/lib/heatmap-matrix/HeatmapMatrix.svelte +1545 -0
  93. package/dist/src/lib/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
  94. package/dist/src/lib/heatmap-matrix/index.ts +167 -0
  95. package/dist/src/lib/heatmap-matrix/shared.ts +7 -0
  96. package/dist/src/lib/icons.ts +650 -0
  97. package/dist/src/lib/index.ts +61 -0
  98. package/dist/src/lib/io/decompress.ts +92 -0
  99. package/dist/src/lib/io/export.ts +385 -0
  100. package/dist/src/lib/io/fetch.ts +46 -0
  101. package/dist/src/lib/io/file-drop.ts +51 -0
  102. package/dist/src/lib/io/index.ts +7 -0
  103. package/dist/src/lib/io/is-binary.ts +24 -0
  104. package/dist/src/lib/io/types.ts +8 -0
  105. package/dist/src/lib/io/url-drop.ts +141 -0
  106. package/dist/src/lib/isosurface/Isosurface.svelte +285 -0
  107. package/dist/src/lib/isosurface/IsosurfaceControls.svelte +277 -0
  108. package/dist/src/lib/isosurface/index.ts +7 -0
  109. package/dist/src/lib/isosurface/parse.ts +656 -0
  110. package/dist/src/lib/isosurface/slice.ts +175 -0
  111. package/dist/src/lib/isosurface/types.ts +309 -0
  112. package/dist/src/lib/labels.ts +320 -0
  113. package/dist/src/lib/layout/FullscreenToggle.svelte +50 -0
  114. package/dist/src/lib/layout/InfoCard.svelte +120 -0
  115. package/dist/src/lib/layout/InfoTag.svelte +185 -0
  116. package/dist/src/lib/layout/PropertyFilter.svelte +246 -0
  117. package/dist/src/lib/layout/SettingsSection.svelte +148 -0
  118. package/dist/src/lib/layout/SubpageGrid.svelte +82 -0
  119. package/dist/src/lib/layout/fullscreen.ts +65 -0
  120. package/dist/src/lib/layout/index.ts +11 -0
  121. package/dist/src/lib/layout/json-tree/JsonNode.svelte +548 -0
  122. package/dist/src/lib/layout/json-tree/JsonTree.svelte +1230 -0
  123. package/dist/src/lib/layout/json-tree/JsonValue.svelte +334 -0
  124. package/dist/src/lib/layout/json-tree/index.ts +3 -0
  125. package/dist/src/lib/layout/json-tree/types.ts +126 -0
  126. package/dist/src/lib/layout/json-tree/utils.ts +682 -0
  127. package/dist/src/lib/marching-cubes.ts +614 -0
  128. package/dist/src/lib/math.ts +1081 -0
  129. package/dist/src/lib/overlays/ContextMenu.svelte +162 -0
  130. package/dist/src/lib/overlays/CopyButton.svelte +45 -0
  131. package/dist/src/lib/overlays/DragControlTab.svelte +98 -0
  132. package/dist/src/lib/overlays/DraggablePane.svelte +487 -0
  133. package/dist/src/lib/overlays/InfoPaneCards.svelte +149 -0
  134. package/dist/src/lib/overlays/index.ts +3 -0
  135. package/dist/src/lib/periodic-table/PeriodicTable.svelte +469 -0
  136. package/dist/src/lib/periodic-table/PeriodicTableControls.svelte +557 -0
  137. package/dist/src/lib/periodic-table/PropertySelect.svelte +37 -0
  138. package/dist/src/lib/periodic-table/index.ts +12 -0
  139. package/dist/src/lib/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +1086 -0
  140. package/dist/src/lib/phase-diagram/PhaseDiagramControls.svelte +444 -0
  141. package/dist/src/lib/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
  142. package/dist/src/lib/phase-diagram/PhaseDiagramExportPane.svelte +184 -0
  143. package/dist/src/lib/phase-diagram/PhaseDiagramTooltip.svelte +391 -0
  144. package/dist/src/lib/phase-diagram/TdbInfoPanel.svelte +203 -0
  145. package/dist/src/lib/phase-diagram/build-diagram.ts +186 -0
  146. package/dist/src/lib/phase-diagram/colors.ts +58 -0
  147. package/dist/src/lib/phase-diagram/diagram-input.ts +40 -0
  148. package/dist/src/lib/phase-diagram/index.ts +13 -0
  149. package/dist/src/lib/phase-diagram/parse.ts +348 -0
  150. package/dist/src/lib/phase-diagram/svg-to-diagram.ts +1023 -0
  151. package/dist/src/lib/phase-diagram/types.ts +144 -0
  152. package/dist/src/lib/phase-diagram/utils.ts +775 -0
  153. package/dist/src/lib/plot/AxisLabel.svelte +51 -0
  154. package/dist/src/lib/plot/BarPlot.svelte +2113 -0
  155. package/dist/src/lib/plot/BarPlotControls.svelte +66 -0
  156. package/dist/src/lib/plot/BinnedScatterPlot.svelte +1114 -0
  157. package/dist/src/lib/plot/ColorBar.svelte +721 -0
  158. package/dist/src/lib/plot/ColorScaleSelect.svelte +54 -0
  159. package/dist/src/lib/plot/ElementScatter.svelte +63 -0
  160. package/dist/src/lib/plot/FillArea.svelte +223 -0
  161. package/dist/src/lib/plot/Histogram.svelte +1558 -0
  162. package/dist/src/lib/plot/HistogramControls.svelte +212 -0
  163. package/dist/src/lib/plot/InteractiveAxisLabel.svelte +96 -0
  164. package/dist/src/lib/plot/Line.svelte +84 -0
  165. package/dist/src/lib/plot/PlotAxis.svelte +169 -0
  166. package/dist/src/lib/plot/PlotControls.svelte +537 -0
  167. package/dist/src/lib/plot/PlotLegend.svelte +569 -0
  168. package/dist/src/lib/plot/PlotTooltip.svelte +67 -0
  169. package/dist/src/lib/plot/PortalSelect.svelte +253 -0
  170. package/dist/src/lib/plot/ReferenceLine3D.svelte +156 -0
  171. package/dist/src/lib/plot/ReferencePlane.svelte +175 -0
  172. package/dist/src/lib/plot/ScatterPlot.svelte +2778 -0
  173. package/dist/src/lib/plot/ScatterPlot3D.svelte +529 -0
  174. package/dist/src/lib/plot/ScatterPlot3DControls.svelte +437 -0
  175. package/dist/src/lib/plot/ScatterPlot3DScene.svelte +912 -0
  176. package/dist/src/lib/plot/ScatterPlotControls.svelte +306 -0
  177. package/dist/src/lib/plot/ScatterPoint.svelte +182 -0
  178. package/dist/src/lib/plot/SpacegroupBarPlot.svelte +293 -0
  179. package/dist/src/lib/plot/Surface3D.svelte +197 -0
  180. package/dist/src/lib/plot/ZeroLines.svelte +97 -0
  181. package/dist/src/lib/plot/ZoomRect.svelte +23 -0
  182. package/dist/src/lib/plot/adaptive-density.ts +316 -0
  183. package/dist/src/lib/plot/auto-place.ts +184 -0
  184. package/dist/src/lib/plot/axis-utils.ts +122 -0
  185. package/dist/src/lib/plot/binned-scatter-types.ts +83 -0
  186. package/dist/src/lib/plot/data-cleaning.ts +1069 -0
  187. package/dist/src/lib/plot/data-transform.ts +69 -0
  188. package/dist/src/lib/plot/defaults.ts +9 -0
  189. package/dist/src/lib/plot/fill-utils.ts +494 -0
  190. package/dist/src/lib/plot/hover-lock.svelte.ts +60 -0
  191. package/dist/src/lib/plot/index.ts +53 -0
  192. package/dist/src/lib/plot/interactions.ts +119 -0
  193. package/dist/src/lib/plot/layout.ts +425 -0
  194. package/dist/src/lib/plot/reference-line.ts +426 -0
  195. package/dist/src/lib/plot/scales.ts +654 -0
  196. package/dist/src/lib/plot/svg.ts +23 -0
  197. package/dist/src/lib/plot/types.ts +1144 -0
  198. package/dist/src/lib/plot/utils/label-placement.ts +541 -0
  199. package/dist/src/lib/plot/utils/series-visibility.ts +140 -0
  200. package/dist/src/lib/plot/utils.ts +11 -0
  201. package/dist/src/lib/rdf/RdfPlot.svelte +247 -0
  202. package/dist/src/lib/rdf/calc-rdf.ts +167 -0
  203. package/dist/src/lib/rdf/index.ts +27 -0
  204. package/dist/src/lib/sanitize.ts +126 -0
  205. package/dist/src/lib/settings.ts +1479 -0
  206. package/dist/src/lib/spectral/Bands.svelte +1040 -0
  207. package/dist/src/lib/spectral/BandsAndDos.svelte +134 -0
  208. package/dist/src/lib/spectral/BrillouinBandsDos.svelte +252 -0
  209. package/dist/src/lib/spectral/Dos.svelte +697 -0
  210. package/dist/src/lib/spectral/helpers.ts +1381 -0
  211. package/dist/src/lib/spectral/index.ts +8 -0
  212. package/dist/src/lib/spectral/types.ts +112 -0
  213. package/dist/src/lib/state.svelte.ts +64 -0
  214. package/dist/src/lib/structure/Arrow.svelte +72 -0
  215. package/dist/src/lib/structure/AtomLegend.svelte +815 -0
  216. package/dist/src/lib/structure/Bond.svelte +140 -0
  217. package/dist/src/lib/structure/CanvasTooltip.svelte +33 -0
  218. package/dist/src/lib/structure/CellSelect.svelte +349 -0
  219. package/dist/src/lib/structure/Cylinder.svelte +45 -0
  220. package/dist/src/lib/structure/Lattice.svelte +196 -0
  221. package/dist/src/lib/structure/Structure.svelte +2248 -0
  222. package/dist/src/lib/structure/StructureControls.svelte +1273 -0
  223. package/dist/src/lib/structure/StructureExportPane.svelte +252 -0
  224. package/dist/src/lib/structure/StructureInfoPane.svelte +737 -0
  225. package/dist/src/lib/structure/StructureScene.svelte +2255 -0
  226. package/dist/src/lib/structure/atom-properties.ts +316 -0
  227. package/dist/src/lib/structure/bond-order-perception.ts +447 -0
  228. package/dist/src/lib/structure/bonding.ts +944 -0
  229. package/dist/src/lib/structure/export.ts +861 -0
  230. package/dist/src/lib/structure/index.ts +291 -0
  231. package/dist/src/lib/structure/label-placement.ts +130 -0
  232. package/dist/src/lib/structure/measure.ts +45 -0
  233. package/dist/src/lib/structure/parse.ts +1705 -0
  234. package/dist/src/lib/structure/partial-occupancy.ts +183 -0
  235. package/dist/src/lib/structure/pbc.ts +164 -0
  236. package/dist/src/lib/structure/supercell.ts +226 -0
  237. package/dist/src/lib/structure/validation.ts +11 -0
  238. package/dist/src/lib/symmetry/SymmetryStats.svelte +226 -0
  239. package/dist/src/lib/symmetry/WyckoffTable.svelte +120 -0
  240. package/dist/src/lib/symmetry/cell-transform.ts +118 -0
  241. package/dist/src/lib/symmetry/index.ts +348 -0
  242. package/dist/src/lib/symmetry/spacegroups.ts +404 -0
  243. package/dist/src/lib/table/HeatmapTable.svelte +1833 -0
  244. package/dist/src/lib/table/ToggleMenu.svelte +385 -0
  245. package/dist/src/lib/table/index.ts +139 -0
  246. package/dist/src/lib/theme/ThemeControl.svelte +53 -0
  247. package/dist/src/lib/theme/index.ts +107 -0
  248. package/dist/src/lib/theme/themes.mjs +297 -0
  249. package/dist/src/lib/time.ts +71 -0
  250. package/dist/src/lib/tooltip/TooltipContent.svelte +58 -0
  251. package/dist/src/lib/tooltip/index.ts +2 -0
  252. package/dist/src/lib/tooltip/types.ts +13 -0
  253. package/dist/src/lib/trajectory/Trajectory.svelte +1545 -0
  254. package/dist/src/lib/trajectory/TrajectoryError.svelte +128 -0
  255. package/dist/src/lib/trajectory/TrajectoryExportPane.svelte +357 -0
  256. package/dist/src/lib/trajectory/TrajectoryInfoPane.svelte +313 -0
  257. package/dist/src/lib/trajectory/constants.ts +7 -0
  258. package/dist/src/lib/trajectory/extract.ts +196 -0
  259. package/dist/src/lib/trajectory/format-detect.ts +96 -0
  260. package/dist/src/lib/trajectory/frame-reader.ts +456 -0
  261. package/dist/src/lib/trajectory/helpers.ts +217 -0
  262. package/dist/src/lib/trajectory/index.ts +218 -0
  263. package/dist/src/lib/trajectory/parse/ase.ts +109 -0
  264. package/dist/src/lib/trajectory/parse/hdf5.ts +173 -0
  265. package/dist/src/lib/trajectory/parse/index.ts +411 -0
  266. package/dist/src/lib/trajectory/parse/lammps.ts +215 -0
  267. package/dist/src/lib/trajectory/parse/vasp.ts +102 -0
  268. package/dist/src/lib/trajectory/parse/xyz.ts +143 -0
  269. package/dist/src/lib/trajectory/plotting.ts +599 -0
  270. package/dist/src/lib/trajectory/types.ts +13 -0
  271. package/dist/src/lib/utils.ts +56 -0
  272. package/dist/src/lib/xrd/XrdPlot.svelte +615 -0
  273. package/dist/src/lib/xrd/broadening.ts +130 -0
  274. package/dist/src/lib/xrd/calc-xrd.ts +397 -0
  275. package/dist/src/lib/xrd/index.ts +38 -0
  276. package/dist/src/lib/xrd/parse.ts +858 -0
  277. package/dist/webview.js +29421 -0
  278. package/icon.png +0 -0
  279. package/license +1 -1
  280. package/matterviz-0.3.2.vsix +0 -0
  281. package/matterviz-0.3.4.vsix +0 -0
  282. package/matterviz-0.3.5.vsix +0 -0
  283. package/package.json +1460 -215
  284. package/readme.md +171 -98
  285. package/scripts/sync-config.ts +101 -0
  286. package/src/declarations.d.ts +2 -0
  287. package/src/extension.ts +972 -0
  288. package/src/node-io.ts +65 -0
  289. package/src/types.ts +17 -0
  290. package/src/webview/JsonBrowser.svelte +1079 -0
  291. package/src/webview/PlotPanel.svelte +346 -0
  292. package/src/webview/detect.ts +444 -0
  293. package/src/webview/main.ts +764 -0
  294. package/src/webview/plot-utils.ts +250 -0
  295. package/test-fixtures/all-viz-types.json.gz +0 -0
  296. package/test-fixtures/plot-demo-data.json.gz +0 -0
  297. package/tests/detect.test.ts +604 -0
  298. package/tests/extension.test.ts +2041 -0
  299. package/tests/node-io.test.ts +39 -0
  300. package/tests/plot-utils.test.ts +302 -0
  301. package/tests/vite-plugin-json-gz.test.ts +114 -0
  302. package/tests/vscode-mock.ts +18 -0
  303. package/tests/webview.test.ts +231 -0
  304. package/tsconfig.json +20 -0
  305. package/vite-plugin-json-gz.ts +29 -0
  306. package/vite.config.ts +34 -0
  307. package/vite.extension.config.ts +34 -0
  308. package/dist/EmptyState.svelte.d.ts +0 -9
  309. package/dist/FilePicker.svelte +0 -360
  310. package/dist/FilePicker.svelte.d.ts +0 -17
  311. package/dist/Icon.svelte.d.ts +0 -13
  312. package/dist/MillerIndexInput.svelte +0 -66
  313. package/dist/MillerIndexInput.svelte.d.ts +0 -7
  314. package/dist/api/mp.d.ts +0 -6
  315. package/dist/api/mp.js +0 -22
  316. package/dist/api/optimade.d.ts +0 -45
  317. package/dist/api/optimade.js +0 -135
  318. package/dist/brillouin/BrillouinZone.svelte +0 -546
  319. package/dist/brillouin/BrillouinZone.svelte.d.ts +0 -83
  320. package/dist/brillouin/BrillouinZoneControls.svelte +0 -144
  321. package/dist/brillouin/BrillouinZoneControls.svelte.d.ts +0 -17
  322. package/dist/brillouin/BrillouinZoneExportPane.svelte +0 -148
  323. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +0 -15
  324. package/dist/brillouin/BrillouinZoneInfoPane.svelte +0 -146
  325. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +0 -13
  326. package/dist/brillouin/BrillouinZoneScene.svelte +0 -476
  327. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +0 -48
  328. package/dist/brillouin/BrillouinZoneTooltip.svelte +0 -92
  329. package/dist/brillouin/BrillouinZoneTooltip.svelte.d.ts +0 -8
  330. package/dist/brillouin/compute.d.ts +0 -17
  331. package/dist/brillouin/compute.js +0 -426
  332. package/dist/brillouin/index.d.ts +0 -8
  333. package/dist/brillouin/index.js +0 -8
  334. package/dist/brillouin/types.d.ts +0 -48
  335. package/dist/brillouin/types.js +0 -1
  336. package/dist/chempot-diagram/ChemPotDiagram.svelte +0 -327
  337. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +0 -13
  338. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +0 -847
  339. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +0 -16
  340. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +0 -3194
  341. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +0 -16
  342. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +0 -7
  343. package/dist/chempot-diagram/async-compute.svelte.d.ts +0 -3
  344. package/dist/chempot-diagram/async-compute.svelte.js +0 -78
  345. package/dist/chempot-diagram/chempot-worker.d.ts +0 -1
  346. package/dist/chempot-diagram/chempot-worker.js +0 -11
  347. package/dist/chempot-diagram/color.d.ts +0 -10
  348. package/dist/chempot-diagram/color.js +0 -32
  349. package/dist/chempot-diagram/compute.d.ts +0 -48
  350. package/dist/chempot-diagram/compute.js +0 -812
  351. package/dist/chempot-diagram/index.d.ts +0 -6
  352. package/dist/chempot-diagram/index.js +0 -6
  353. package/dist/chempot-diagram/pointer.d.ts +0 -16
  354. package/dist/chempot-diagram/pointer.js +0 -40
  355. package/dist/chempot-diagram/temperature.d.ts +0 -15
  356. package/dist/chempot-diagram/temperature.js +0 -36
  357. package/dist/chempot-diagram/types.d.ts +0 -86
  358. package/dist/chempot-diagram/types.js +0 -28
  359. package/dist/colors/index.d.ts +0 -47
  360. package/dist/colors/index.js +0 -203
  361. package/dist/composition/BarChart.svelte +0 -297
  362. package/dist/composition/BarChart.svelte.d.ts +0 -39
  363. package/dist/composition/BubbleChart.svelte +0 -218
  364. package/dist/composition/BubbleChart.svelte.d.ts +0 -28
  365. package/dist/composition/Composition.svelte +0 -164
  366. package/dist/composition/Composition.svelte.d.ts +0 -15
  367. package/dist/composition/Formula.svelte +0 -265
  368. package/dist/composition/Formula.svelte.d.ts +0 -19
  369. package/dist/composition/FormulaFilter.svelte +0 -1259
  370. package/dist/composition/FormulaFilter.svelte.d.ts +0 -51
  371. package/dist/composition/PieChart.svelte +0 -323
  372. package/dist/composition/PieChart.svelte.d.ts +0 -37
  373. package/dist/composition/format.d.ts +0 -15
  374. package/dist/composition/format.js +0 -109
  375. package/dist/composition/index.d.ts +0 -20
  376. package/dist/composition/index.js +0 -14
  377. package/dist/composition/parse.d.ts +0 -55
  378. package/dist/composition/parse.js +0 -459
  379. package/dist/constants.d.ts +0 -29
  380. package/dist/constants.js +0 -99
  381. package/dist/controls.d.ts +0 -14
  382. package/dist/controls.js +0 -30
  383. package/dist/convex-hull/ConvexHull.svelte +0 -157
  384. package/dist/convex-hull/ConvexHull.svelte.d.ts +0 -13
  385. package/dist/convex-hull/ConvexHull2D.svelte +0 -814
  386. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +0 -11
  387. package/dist/convex-hull/ConvexHull3D.svelte +0 -1790
  388. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +0 -8
  389. package/dist/convex-hull/ConvexHull4D.svelte +0 -1386
  390. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +0 -8
  391. package/dist/convex-hull/ConvexHullControls.svelte +0 -546
  392. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +0 -48
  393. package/dist/convex-hull/ConvexHullInfoPane.svelte +0 -122
  394. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +0 -18
  395. package/dist/convex-hull/ConvexHullStats.svelte +0 -922
  396. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +0 -15
  397. package/dist/convex-hull/ConvexHullTooltip.svelte +0 -131
  398. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +0 -33
  399. package/dist/convex-hull/GasPressureControls.svelte +0 -247
  400. package/dist/convex-hull/GasPressureControls.svelte.d.ts +0 -11
  401. package/dist/convex-hull/StructurePopup.svelte +0 -116
  402. package/dist/convex-hull/StructurePopup.svelte.d.ts +0 -18
  403. package/dist/convex-hull/TemperatureSlider.svelte +0 -137
  404. package/dist/convex-hull/TemperatureSlider.svelte.d.ts +0 -8
  405. package/dist/convex-hull/barycentric-coords.d.ts +0 -18
  406. package/dist/convex-hull/barycentric-coords.js +0 -182
  407. package/dist/convex-hull/demo-temperature.d.ts +0 -6
  408. package/dist/convex-hull/demo-temperature.js +0 -40
  409. package/dist/convex-hull/gas-thermodynamics.d.ts +0 -16
  410. package/dist/convex-hull/gas-thermodynamics.js +0 -316
  411. package/dist/convex-hull/helpers.d.ts +0 -103
  412. package/dist/convex-hull/helpers.js +0 -689
  413. package/dist/convex-hull/index.d.ts +0 -118
  414. package/dist/convex-hull/index.js +0 -57
  415. package/dist/convex-hull/thermodynamics.d.ts +0 -66
  416. package/dist/convex-hull/thermodynamics.js +0 -1752
  417. package/dist/convex-hull/types.d.ts +0 -162
  418. package/dist/convex-hull/types.js +0 -36
  419. package/dist/coordination/CoordinationBarPlot.svelte +0 -311
  420. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +0 -30
  421. package/dist/coordination/calc-coordination.d.ts +0 -15
  422. package/dist/coordination/calc-coordination.js +0 -63
  423. package/dist/coordination/index.d.ts +0 -8
  424. package/dist/coordination/index.js +0 -7
  425. package/dist/element/BohrAtom.svelte +0 -147
  426. package/dist/element/BohrAtom.svelte.d.ts +0 -20
  427. package/dist/element/ElementHeading.svelte +0 -26
  428. package/dist/element/ElementHeading.svelte.d.ts +0 -8
  429. package/dist/element/ElementPhoto.svelte +0 -57
  430. package/dist/element/ElementPhoto.svelte.d.ts +0 -9
  431. package/dist/element/ElementStats.svelte +0 -80
  432. package/dist/element/ElementStats.svelte.d.ts +0 -8
  433. package/dist/element/ElementTile.svelte +0 -484
  434. package/dist/element/ElementTile.svelte.d.ts +0 -29
  435. package/dist/element/Nucleus.svelte.d.ts +0 -17
  436. package/dist/element/data.d.ts +0 -2
  437. package/dist/element/data.js +0 -2
  438. package/dist/element/data.json.gz.d.ts +0 -2
  439. package/dist/element/index.d.ts +0 -8
  440. package/dist/element/index.js +0 -8
  441. package/dist/element/types.d.ts +0 -57
  442. package/dist/element/types.js +0 -1
  443. package/dist/feedback/ClickFeedback.svelte +0 -58
  444. package/dist/feedback/ClickFeedback.svelte.d.ts +0 -12
  445. package/dist/feedback/DragOverlay.svelte +0 -42
  446. package/dist/feedback/DragOverlay.svelte.d.ts +0 -7
  447. package/dist/feedback/Spinner.svelte.d.ts +0 -7
  448. package/dist/feedback/StatusMessage.svelte.d.ts +0 -9
  449. package/dist/feedback/index.d.ts +0 -4
  450. package/dist/feedback/index.js +0 -4
  451. package/dist/fermi-surface/FermiSlice.svelte +0 -189
  452. package/dist/fermi-surface/FermiSlice.svelte.d.ts +0 -24
  453. package/dist/fermi-surface/FermiSurface.svelte +0 -600
  454. package/dist/fermi-surface/FermiSurface.svelte.d.ts +0 -83
  455. package/dist/fermi-surface/FermiSurfaceControls.svelte +0 -452
  456. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +0 -35
  457. package/dist/fermi-surface/FermiSurfaceScene.svelte +0 -792
  458. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +0 -50
  459. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +0 -111
  460. package/dist/fermi-surface/FermiSurfaceTooltip.svelte.d.ts +0 -8
  461. package/dist/fermi-surface/compute.d.ts +0 -5
  462. package/dist/fermi-surface/compute.js +0 -538
  463. package/dist/fermi-surface/constants.d.ts +0 -9
  464. package/dist/fermi-surface/constants.js +0 -27
  465. package/dist/fermi-surface/export.d.ts +0 -5
  466. package/dist/fermi-surface/export.js +0 -63
  467. package/dist/fermi-surface/index.d.ts +0 -12
  468. package/dist/fermi-surface/index.js +0 -13
  469. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  470. package/dist/fermi-surface/marching-cubes.js +0 -2
  471. package/dist/fermi-surface/parse.d.ts +0 -2
  472. package/dist/fermi-surface/parse.js +0 -495
  473. package/dist/fermi-surface/symmetry.d.ts +0 -3
  474. package/dist/fermi-surface/symmetry.js +0 -46
  475. package/dist/fermi-surface/types.d.ts +0 -113
  476. package/dist/fermi-surface/types.js +0 -4
  477. package/dist/heatmap-matrix/HeatmapMatrix.svelte +0 -1527
  478. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +0 -110
  479. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +0 -225
  480. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +0 -30
  481. package/dist/heatmap-matrix/index.d.ts +0 -53
  482. package/dist/heatmap-matrix/index.js +0 -100
  483. package/dist/heatmap-matrix/shared.d.ts +0 -2
  484. package/dist/heatmap-matrix/shared.js +0 -4
  485. package/dist/icons.d.ts +0 -569
  486. package/dist/icons.js +0 -648
  487. package/dist/index.d.ts +0 -39
  488. package/dist/index.js +0 -39
  489. package/dist/io/decompress.d.ts +0 -10
  490. package/dist/io/decompress.js +0 -74
  491. package/dist/io/export.d.ts +0 -16
  492. package/dist/io/export.js +0 -316
  493. package/dist/io/fetch.d.ts +0 -5
  494. package/dist/io/fetch.js +0 -39
  495. package/dist/io/file-drop.d.ts +0 -7
  496. package/dist/io/file-drop.js +0 -43
  497. package/dist/io/index.d.ts +0 -7
  498. package/dist/io/index.js +0 -7
  499. package/dist/io/is-binary.d.ts +0 -1
  500. package/dist/io/is-binary.js +0 -20
  501. package/dist/io/types.d.ts +0 -8
  502. package/dist/io/types.js +0 -1
  503. package/dist/io/url-drop.d.ts +0 -2
  504. package/dist/io/url-drop.js +0 -117
  505. package/dist/isosurface/Isosurface.svelte +0 -285
  506. package/dist/isosurface/Isosurface.svelte.d.ts +0 -8
  507. package/dist/isosurface/IsosurfaceControls.svelte +0 -291
  508. package/dist/isosurface/IsosurfaceControls.svelte.d.ts +0 -9
  509. package/dist/isosurface/index.d.ts +0 -5
  510. package/dist/isosurface/index.js +0 -6
  511. package/dist/isosurface/parse.d.ts +0 -6
  512. package/dist/isosurface/parse.js +0 -553
  513. package/dist/isosurface/slice.d.ts +0 -11
  514. package/dist/isosurface/slice.js +0 -140
  515. package/dist/isosurface/types.d.ts +0 -56
  516. package/dist/isosurface/types.js +0 -227
  517. package/dist/labels.d.ts +0 -53
  518. package/dist/labels.js +0 -274
  519. package/dist/layout/FullscreenToggle.svelte +0 -50
  520. package/dist/layout/FullscreenToggle.svelte.d.ts +0 -7
  521. package/dist/layout/InfoCard.svelte +0 -120
  522. package/dist/layout/InfoCard.svelte.d.ts +0 -21
  523. package/dist/layout/InfoTag.svelte +0 -183
  524. package/dist/layout/InfoTag.svelte.d.ts +0 -19
  525. package/dist/layout/PropertyFilter.svelte +0 -244
  526. package/dist/layout/PropertyFilter.svelte.d.ts +0 -24
  527. package/dist/layout/SettingsSection.svelte +0 -148
  528. package/dist/layout/SettingsSection.svelte.d.ts +0 -17
  529. package/dist/layout/SubpageGrid.svelte +0 -82
  530. package/dist/layout/SubpageGrid.svelte.d.ts +0 -14
  531. package/dist/layout/fullscreen.d.ts +0 -9
  532. package/dist/layout/fullscreen.js +0 -53
  533. package/dist/layout/index.d.ts +0 -10
  534. package/dist/layout/index.js +0 -8
  535. package/dist/layout/json-tree/JsonNode.svelte +0 -548
  536. package/dist/layout/json-tree/JsonNode.svelte.d.ts +0 -11
  537. package/dist/layout/json-tree/JsonTree.svelte +0 -1222
  538. package/dist/layout/json-tree/JsonTree.svelte.d.ts +0 -6
  539. package/dist/layout/json-tree/JsonValue.svelte +0 -334
  540. package/dist/layout/json-tree/JsonValue.svelte.d.ts +0 -9
  541. package/dist/layout/json-tree/index.d.ts +0 -3
  542. package/dist/layout/json-tree/index.js +0 -3
  543. package/dist/layout/json-tree/types.d.ts +0 -73
  544. package/dist/layout/json-tree/types.js +0 -3
  545. package/dist/layout/json-tree/utils.d.ts +0 -29
  546. package/dist/layout/json-tree/utils.js +0 -649
  547. package/dist/marching-cubes.d.ts +0 -14
  548. package/dist/marching-cubes.js +0 -542
  549. package/dist/math.d.ts +0 -91
  550. package/dist/math.js +0 -896
  551. package/dist/overlays/ContextMenu.svelte +0 -162
  552. package/dist/overlays/ContextMenu.svelte.d.ts +0 -25
  553. package/dist/overlays/CopyButton.svelte +0 -45
  554. package/dist/overlays/CopyButton.svelte.d.ts +0 -8
  555. package/dist/overlays/DraggablePane.svelte +0 -564
  556. package/dist/overlays/DraggablePane.svelte.d.ts +0 -36
  557. package/dist/overlays/InfoPaneCards.svelte +0 -149
  558. package/dist/overlays/InfoPaneCards.svelte.d.ts +0 -22
  559. package/dist/overlays/index.d.ts +0 -2
  560. package/dist/overlays/index.js +0 -2
  561. package/dist/periodic-table/PeriodicTable.svelte +0 -469
  562. package/dist/periodic-table/PeriodicTable.svelte.d.ts +0 -55
  563. package/dist/periodic-table/PeriodicTableControls.svelte +0 -557
  564. package/dist/periodic-table/PeriodicTableControls.svelte.d.ts +0 -24
  565. package/dist/periodic-table/PropertySelect.svelte +0 -37
  566. package/dist/periodic-table/PropertySelect.svelte.d.ts +0 -13
  567. package/dist/periodic-table/TableInset.svelte.d.ts +0 -9
  568. package/dist/periodic-table/index.d.ts +0 -10
  569. package/dist/periodic-table/index.js +0 -4
  570. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +0 -1084
  571. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +0 -44
  572. package/dist/phase-diagram/PhaseDiagramControls.svelte +0 -449
  573. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +0 -30
  574. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +0 -126
  575. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +0 -15
  576. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +0 -192
  577. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +0 -19
  578. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +0 -392
  579. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +0 -16
  580. package/dist/phase-diagram/TdbInfoPanel.svelte +0 -203
  581. package/dist/phase-diagram/TdbInfoPanel.svelte.d.ts +0 -12
  582. package/dist/phase-diagram/build-diagram.d.ts +0 -11
  583. package/dist/phase-diagram/build-diagram.js +0 -167
  584. package/dist/phase-diagram/colors.d.ts +0 -35
  585. package/dist/phase-diagram/colors.js +0 -51
  586. package/dist/phase-diagram/diagram-input.d.ts +0 -33
  587. package/dist/phase-diagram/diagram-input.js +0 -3
  588. package/dist/phase-diagram/index.d.ts +0 -13
  589. package/dist/phase-diagram/index.js +0 -13
  590. package/dist/phase-diagram/parse.d.ts +0 -55
  591. package/dist/phase-diagram/parse.js +0 -276
  592. package/dist/phase-diagram/svg-to-diagram.d.ts +0 -2
  593. package/dist/phase-diagram/svg-to-diagram.js +0 -867
  594. package/dist/phase-diagram/types.d.ts +0 -99
  595. package/dist/phase-diagram/types.js +0 -1
  596. package/dist/phase-diagram/utils.d.ts +0 -118
  597. package/dist/phase-diagram/utils.js +0 -606
  598. package/dist/plot/AxisLabel.svelte +0 -51
  599. package/dist/plot/AxisLabel.svelte.d.ts +0 -16
  600. package/dist/plot/BarPlot.svelte +0 -2265
  601. package/dist/plot/BarPlot.svelte.d.ts +0 -83
  602. package/dist/plot/BarPlotControls.svelte +0 -66
  603. package/dist/plot/BarPlotControls.svelte.d.ts +0 -18
  604. package/dist/plot/ColorBar.svelte +0 -719
  605. package/dist/plot/ColorBar.svelte.d.ts +0 -31
  606. package/dist/plot/ColorScaleSelect.svelte +0 -54
  607. package/dist/plot/ColorScaleSelect.svelte.d.ts +0 -15
  608. package/dist/plot/ElementScatter.svelte +0 -63
  609. package/dist/plot/ElementScatter.svelte.d.ts +0 -14
  610. package/dist/plot/FillArea.svelte +0 -225
  611. package/dist/plot/FillArea.svelte.d.ts +0 -21
  612. package/dist/plot/Histogram.svelte +0 -1672
  613. package/dist/plot/Histogram.svelte.d.ts +0 -50
  614. package/dist/plot/HistogramControls.svelte +0 -212
  615. package/dist/plot/HistogramControls.svelte.d.ts +0 -22
  616. package/dist/plot/InteractiveAxisLabel.svelte +0 -94
  617. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +0 -14
  618. package/dist/plot/Line.svelte +0 -84
  619. package/dist/plot/Line.svelte.d.ts +0 -15
  620. package/dist/plot/PlotControls.svelte +0 -537
  621. package/dist/plot/PlotControls.svelte.d.ts +0 -4
  622. package/dist/plot/PlotLegend.svelte +0 -569
  623. package/dist/plot/PlotLegend.svelte.d.ts +0 -29
  624. package/dist/plot/PlotTooltip.svelte +0 -67
  625. package/dist/plot/PlotTooltip.svelte.d.ts +0 -17
  626. package/dist/plot/PortalSelect.svelte +0 -253
  627. package/dist/plot/PortalSelect.svelte.d.ts +0 -16
  628. package/dist/plot/ReferenceLine.svelte.d.ts +0 -20
  629. package/dist/plot/ReferenceLine3D.svelte +0 -154
  630. package/dist/plot/ReferenceLine3D.svelte.d.ts +0 -14
  631. package/dist/plot/ReferencePlane.svelte +0 -178
  632. package/dist/plot/ReferencePlane.svelte.d.ts +0 -14
  633. package/dist/plot/ScatterPlot.svelte +0 -2845
  634. package/dist/plot/ScatterPlot.svelte.d.ts +0 -93
  635. package/dist/plot/ScatterPlot3D.svelte +0 -502
  636. package/dist/plot/ScatterPlot3D.svelte.d.ts +0 -94
  637. package/dist/plot/ScatterPlot3DControls.svelte +0 -437
  638. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +0 -20
  639. package/dist/plot/ScatterPlot3DScene.svelte +0 -912
  640. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +0 -74
  641. package/dist/plot/ScatterPlotControls.svelte +0 -307
  642. package/dist/plot/ScatterPlotControls.svelte.d.ts +0 -17
  643. package/dist/plot/ScatterPoint.svelte +0 -191
  644. package/dist/plot/ScatterPoint.svelte.d.ts +0 -21
  645. package/dist/plot/SpacegroupBarPlot.svelte +0 -293
  646. package/dist/plot/SpacegroupBarPlot.svelte.d.ts +0 -9
  647. package/dist/plot/Surface3D.svelte +0 -200
  648. package/dist/plot/Surface3D.svelte.d.ts +0 -13
  649. package/dist/plot/ZeroLines.svelte +0 -96
  650. package/dist/plot/ZeroLines.svelte.d.ts +0 -32
  651. package/dist/plot/ZoomRect.svelte +0 -23
  652. package/dist/plot/ZoomRect.svelte.d.ts +0 -8
  653. package/dist/plot/axis-utils.d.ts +0 -19
  654. package/dist/plot/axis-utils.js +0 -80
  655. package/dist/plot/data-cleaning.d.ts +0 -37
  656. package/dist/plot/data-cleaning.js +0 -855
  657. package/dist/plot/data-transform.d.ts +0 -16
  658. package/dist/plot/data-transform.js +0 -45
  659. package/dist/plot/defaults.d.ts +0 -19
  660. package/dist/plot/defaults.js +0 -9
  661. package/dist/plot/fill-utils.d.ts +0 -51
  662. package/dist/plot/fill-utils.js +0 -337
  663. package/dist/plot/hover-lock.svelte.d.ts +0 -14
  664. package/dist/plot/hover-lock.svelte.js +0 -46
  665. package/dist/plot/index.d.ts +0 -37
  666. package/dist/plot/index.js +0 -37
  667. package/dist/plot/interactions.d.ts +0 -12
  668. package/dist/plot/interactions.js +0 -100
  669. package/dist/plot/layout.d.ts +0 -60
  670. package/dist/plot/layout.js +0 -230
  671. package/dist/plot/reference-line.d.ts +0 -60
  672. package/dist/plot/reference-line.js +0 -316
  673. package/dist/plot/scales.d.ts +0 -48
  674. package/dist/plot/scales.js +0 -484
  675. package/dist/plot/svg.d.ts +0 -1
  676. package/dist/plot/svg.js +0 -11
  677. package/dist/plot/types.d.ts +0 -859
  678. package/dist/plot/types.js +0 -103
  679. package/dist/plot/utils/label-placement.d.ts +0 -47
  680. package/dist/plot/utils/label-placement.js +0 -256
  681. package/dist/plot/utils/series-visibility.d.ts +0 -9
  682. package/dist/plot/utils/series-visibility.js +0 -67
  683. package/dist/plot/utils.d.ts +0 -1
  684. package/dist/plot/utils.js +0 -14
  685. package/dist/rdf/RdfPlot.svelte +0 -247
  686. package/dist/rdf/RdfPlot.svelte.d.ts +0 -27
  687. package/dist/rdf/calc-rdf.d.ts +0 -4
  688. package/dist/rdf/calc-rdf.js +0 -111
  689. package/dist/rdf/index.d.ts +0 -23
  690. package/dist/rdf/index.js +0 -2
  691. package/dist/sanitize.d.ts +0 -4
  692. package/dist/sanitize.js +0 -114
  693. package/dist/settings.d.ts +0 -255
  694. package/dist/settings.js +0 -1132
  695. package/dist/spectral/Bands.svelte +0 -1040
  696. package/dist/spectral/Bands.svelte.d.ts +0 -40
  697. package/dist/spectral/BandsAndDos.svelte +0 -128
  698. package/dist/spectral/BandsAndDos.svelte.d.ts +0 -18
  699. package/dist/spectral/BrillouinBandsDos.svelte +0 -248
  700. package/dist/spectral/BrillouinBandsDos.svelte.d.ts +0 -20
  701. package/dist/spectral/Dos.svelte +0 -697
  702. package/dist/spectral/Dos.svelte.d.ts +0 -29
  703. package/dist/spectral/helpers.d.ts +0 -117
  704. package/dist/spectral/helpers.js +0 -1023
  705. package/dist/spectral/index.d.ts +0 -6
  706. package/dist/spectral/index.js +0 -7
  707. package/dist/spectral/types.d.ts +0 -84
  708. package/dist/spectral/types.js +0 -2
  709. package/dist/state.svelte.d.ts +0 -25
  710. package/dist/state.svelte.js +0 -45
  711. package/dist/structure/Arrow.svelte +0 -72
  712. package/dist/structure/Arrow.svelte.d.ts +0 -15
  713. package/dist/structure/AtomLegend.svelte +0 -798
  714. package/dist/structure/AtomLegend.svelte.d.ts +0 -34
  715. package/dist/structure/Bond.svelte +0 -140
  716. package/dist/structure/Bond.svelte.d.ts +0 -9
  717. package/dist/structure/CanvasTooltip.svelte +0 -33
  718. package/dist/structure/CanvasTooltip.svelte.d.ts +0 -12
  719. package/dist/structure/CellSelect.svelte +0 -351
  720. package/dist/structure/CellSelect.svelte.d.ts +0 -13
  721. package/dist/structure/Cylinder.svelte +0 -45
  722. package/dist/structure/Cylinder.svelte.d.ts +0 -10
  723. package/dist/structure/Lattice.svelte +0 -196
  724. package/dist/structure/Lattice.svelte.d.ts +0 -17
  725. package/dist/structure/Structure.svelte +0 -1999
  726. package/dist/structure/Structure.svelte.d.ts +0 -87
  727. package/dist/structure/StructureControls.svelte +0 -1298
  728. package/dist/structure/StructureControls.svelte.d.ts +0 -31
  729. package/dist/structure/StructureExportPane.svelte +0 -251
  730. package/dist/structure/StructureExportPane.svelte.d.ts +0 -17
  731. package/dist/structure/StructureInfoPane.svelte +0 -735
  732. package/dist/structure/StructureInfoPane.svelte.d.ts +0 -19
  733. package/dist/structure/StructureScene.svelte +0 -1905
  734. package/dist/structure/StructureScene.svelte.d.ts +0 -108
  735. package/dist/structure/atom-properties.d.ts +0 -37
  736. package/dist/structure/atom-properties.js +0 -200
  737. package/dist/structure/bond-order-perception.d.ts +0 -13
  738. package/dist/structure/bond-order-perception.js +0 -367
  739. package/dist/structure/bonding.d.ts +0 -42
  740. package/dist/structure/bonding.js +0 -525
  741. package/dist/structure/export.d.ts +0 -20
  742. package/dist/structure/export.js +0 -727
  743. package/dist/structure/index.d.ts +0 -125
  744. package/dist/structure/index.js +0 -171
  745. package/dist/structure/label-placement.d.ts +0 -14
  746. package/dist/structure/label-placement.js +0 -72
  747. package/dist/structure/measure.d.ts +0 -6
  748. package/dist/structure/measure.js +0 -29
  749. package/dist/structure/parse.d.ts +0 -66
  750. package/dist/structure/parse.js +0 -1363
  751. package/dist/structure/partial-occupancy.d.ts +0 -25
  752. package/dist/structure/partial-occupancy.js +0 -99
  753. package/dist/structure/pbc.d.ts +0 -9
  754. package/dist/structure/pbc.js +0 -123
  755. package/dist/structure/supercell.d.ts +0 -8
  756. package/dist/structure/supercell.js +0 -170
  757. package/dist/structure/validation.d.ts +0 -2
  758. package/dist/structure/validation.js +0 -10
  759. package/dist/symmetry/SymmetryStats.svelte +0 -226
  760. package/dist/symmetry/SymmetryStats.svelte.d.ts +0 -21
  761. package/dist/symmetry/WyckoffTable.svelte +0 -113
  762. package/dist/symmetry/WyckoffTable.svelte.d.ts +0 -11
  763. package/dist/symmetry/cell-transform.d.ts +0 -12
  764. package/dist/symmetry/cell-transform.js +0 -91
  765. package/dist/symmetry/index.d.ts +0 -43
  766. package/dist/symmetry/index.js +0 -229
  767. package/dist/symmetry/spacegroups.d.ts +0 -9
  768. package/dist/symmetry/spacegroups.js +0 -394
  769. package/dist/table/HeatmapTable.svelte +0 -1854
  770. package/dist/table/HeatmapTable.svelte.d.ts +0 -49
  771. package/dist/table/ToggleMenu.svelte +0 -376
  772. package/dist/table/ToggleMenu.svelte.d.ts +0 -11
  773. package/dist/table/index.d.ts +0 -74
  774. package/dist/table/index.js +0 -38
  775. package/dist/theme/ThemeControl.svelte +0 -53
  776. package/dist/theme/ThemeControl.svelte.d.ts +0 -9
  777. package/dist/theme/index.d.ts +0 -29
  778. package/dist/theme/index.js +0 -79
  779. package/dist/theme/themes.mjs +0 -285
  780. package/dist/time.d.ts +0 -4
  781. package/dist/time.js +0 -70
  782. package/dist/tooltip/TooltipContent.svelte +0 -58
  783. package/dist/tooltip/TooltipContent.svelte.d.ts +0 -31
  784. package/dist/tooltip/index.d.ts +0 -2
  785. package/dist/tooltip/index.js +0 -2
  786. package/dist/tooltip/types.d.ts +0 -8
  787. package/dist/tooltip/types.js +0 -1
  788. package/dist/trajectory/Trajectory.svelte +0 -1517
  789. package/dist/trajectory/Trajectory.svelte.d.ts +0 -77
  790. package/dist/trajectory/TrajectoryError.svelte +0 -128
  791. package/dist/trajectory/TrajectoryError.svelte.d.ts +0 -13
  792. package/dist/trajectory/TrajectoryExportPane.svelte +0 -357
  793. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +0 -17
  794. package/dist/trajectory/TrajectoryInfoPane.svelte +0 -313
  795. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +0 -17
  796. package/dist/trajectory/constants.d.ts +0 -6
  797. package/dist/trajectory/constants.js +0 -7
  798. package/dist/trajectory/extract.d.ts +0 -5
  799. package/dist/trajectory/extract.js +0 -162
  800. package/dist/trajectory/format-detect.d.ts +0 -9
  801. package/dist/trajectory/format-detect.js +0 -76
  802. package/dist/trajectory/frame-reader.d.ts +0 -17
  803. package/dist/trajectory/frame-reader.js +0 -332
  804. package/dist/trajectory/helpers.d.ts +0 -14
  805. package/dist/trajectory/helpers.js +0 -172
  806. package/dist/trajectory/index.d.ts +0 -63
  807. package/dist/trajectory/index.js +0 -126
  808. package/dist/trajectory/parse/ase.d.ts +0 -2
  809. package/dist/trajectory/parse/ase.js +0 -73
  810. package/dist/trajectory/parse/hdf5.d.ts +0 -2
  811. package/dist/trajectory/parse/hdf5.js +0 -127
  812. package/dist/trajectory/parse/index.d.ts +0 -12
  813. package/dist/trajectory/parse/index.js +0 -299
  814. package/dist/trajectory/parse/lammps.d.ts +0 -5
  815. package/dist/trajectory/parse/lammps.js +0 -179
  816. package/dist/trajectory/parse/vasp.d.ts +0 -2
  817. package/dist/trajectory/parse/vasp.js +0 -68
  818. package/dist/trajectory/parse/xyz.d.ts +0 -2
  819. package/dist/trajectory/parse/xyz.js +0 -110
  820. package/dist/trajectory/plotting.d.ts +0 -28
  821. package/dist/trajectory/plotting.js +0 -423
  822. package/dist/trajectory/types.d.ts +0 -11
  823. package/dist/trajectory/types.js +0 -1
  824. package/dist/utils.d.ts +0 -5
  825. package/dist/utils.js +0 -36
  826. package/dist/xrd/XrdPlot.svelte +0 -615
  827. package/dist/xrd/XrdPlot.svelte.d.ts +0 -28
  828. package/dist/xrd/broadening.d.ts +0 -20
  829. package/dist/xrd/broadening.js +0 -97
  830. package/dist/xrd/calc-xrd.d.ts +0 -37
  831. package/dist/xrd/calc-xrd.js +0 -337
  832. package/dist/xrd/index.d.ts +0 -37
  833. package/dist/xrd/index.js +0 -4
  834. package/dist/xrd/parse.d.ts +0 -13
  835. package/dist/xrd/parse.js +0 -749
  836. /package/dist/{EmptyState.svelte → src/lib/EmptyState.svelte} +0 -0
  837. /package/dist/{Icon.svelte → src/lib/Icon.svelte} +0 -0
  838. /package/dist/{app.css → src/lib/app.css} +0 -0
  839. /package/dist/{chempot-diagram → src/lib/chempot-diagram}/ChemPotScene3D.svelte +0 -0
  840. /package/dist/{colors → src/lib/colors}/alloy-colors.json +0 -0
  841. /package/dist/{colors → src/lib/colors}/dark-mode-colors.json +0 -0
  842. /package/dist/{colors → src/lib/colors}/jmol-colors.json +0 -0
  843. /package/dist/{colors → src/lib/colors}/muted-colors.json +0 -0
  844. /package/dist/{colors → src/lib/colors}/pastel-colors.json +0 -0
  845. /package/dist/{colors → src/lib/colors}/vesta-colors.json +0 -0
  846. /package/dist/{element → src/lib/element}/Nucleus.svelte +0 -0
  847. /package/dist/{element → src/lib/element}/data.json +0 -0
  848. /package/dist/{element → src/lib/element}/data.json.gz +0 -0
  849. /package/dist/{element → src/lib/element}/data.schema.json +0 -0
  850. /package/dist/{element-image-urls.json → src/lib/element-image-urls.json} +0 -0
  851. /package/dist/{feedback → src/lib/feedback}/Spinner.svelte +0 -0
  852. /package/dist/{feedback → src/lib/feedback}/StatusMessage.svelte +0 -0
  853. /package/dist/{periodic-table → src/lib/periodic-table}/TableInset.svelte +0 -0
  854. /package/dist/{plot → src/lib/plot}/ReferenceLine.svelte +0 -0
  855. /package/dist/{xrd → src/lib/xrd}/atomic_scattering_params.json +0 -0
@@ -1,1905 +0,0 @@
1
- <script lang="ts">
2
- import type { D3InterpolateName } from '../colors'
3
- import { AXIS_COLORS, get_d3_interpolator, NEG_AXIS_COLORS } from '../colors'
4
- import type { ElementSymbol } from '../element'
5
- import { element_data } from '../element'
6
- import Isosurface from '../isosurface/Isosurface.svelte'
7
- import type { IsosurfaceSettings, VolumetricData } from '../isosurface/types'
8
- import { DEFAULT_ISOSURFACE_SETTINGS } from '../isosurface/types'
9
- import { format_num } from '../labels'
10
- import type { Vec3 } from '../math'
11
- import * as math from '../math'
12
- import type {
13
- CameraProjection,
14
- ShowBonds,
15
- VectorColorMode,
16
- VectorLayerConfig,
17
- } from '../settings'
18
- import { DEFAULTS } from '../settings'
19
- import { sanitize_html } from '../sanitize'
20
- import { colors } from '../state.svelte'
21
- import type {
22
- AnyStructure,
23
- BondOrder,
24
- BondPair,
25
- MeasureMode,
26
- Site,
27
- StructureBond,
28
- } from './'
29
- import {
30
- Arrow,
31
- atomic_radii,
32
- Cylinder,
33
- get_all_site_vectors,
34
- get_center_of_mass,
35
- get_structure_vector_keys,
36
- Lattice,
37
- VECTOR_PALETTE,
38
- } from './'
39
- import type { AtomColorConfig } from './atom-properties'
40
- import {
41
- get_orig_site_idx,
42
- get_property_colors,
43
- } from './atom-properties'
44
- import * as measure from './measure'
45
- import {
46
- compute_slice_geometry,
47
- merge_split_partial_sites,
48
- PARTIAL_OCCUPANCY_CAP_ARC,
49
- } from './partial-occupancy'
50
- import type { MoyoDataset } from '@spglib/moyo-wasm'
51
- import { T, useThrelte } from '@threlte/core'
52
- import * as extras from '@threlte/extras'
53
- import { type ComponentProps, type Snippet, untrack } from 'svelte'
54
- import { SvelteMap, SvelteSet } from 'svelte/reactivity'
55
- import { type Camera, Color, type Mesh, type Scene } from 'three'
56
- import Bond from './Bond.svelte'
57
- import type { BondingStrategy } from './bonding'
58
- import {
59
- BONDING_STRATEGIES,
60
- get_bond_key,
61
- get_bond_render_matrices,
62
- get_explicit_bond_metadata,
63
- normalize_structure_bond,
64
- structure_bond_to_bond_pair,
65
- } from './bonding'
66
- import {
67
- CanvasTooltip,
68
- compose_perceived_bonds,
69
- perceive_bond_orders,
70
- } from './index'
71
- import {
72
- choose_site_label_offset,
73
- LABEL_OFFSET_EPS,
74
- make_label_position_calculator,
75
- } from './label-placement'
76
-
77
- type InstancedAtomGroup = {
78
- element: string
79
- radius: number
80
- color: string
81
- is_image_atom: boolean
82
- atoms: (typeof atom_data)[number][]
83
- }
84
-
85
- type BondContextMenu = {
86
- site_idx_1: number
87
- site_idx_2: number
88
- cell_shift?: Vec3
89
- position: Vec3
90
- }
91
- type BondKeyTarget = Pick<StructureBond, `site_idx_1` | `site_idx_2` | `cell_shift`>
92
-
93
- let pulse_time = $state(0)
94
- let pulse_opacity = $derived(0.15 + 0.25 * Math.sin(pulse_time * 5))
95
- $effect(() => {
96
- if (!selected_sites?.length && !active_sites?.length) return
97
- if (typeof globalThis === `undefined`) return
98
- const reduce = globalThis.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches
99
- if (reduce) return
100
- let frame_id = 0
101
- const animate = () => {
102
- pulse_time += 0.015
103
- frame_id = requestAnimationFrame(animate)
104
- }
105
- frame_id = requestAnimationFrame(animate)
106
- return () => cancelAnimationFrame(frame_id)
107
- })
108
-
109
- let {
110
- structure = undefined,
111
- base_structure = undefined,
112
- atom_radius = DEFAULTS.structure.atom_radius,
113
- same_size_atoms = false,
114
- camera_position = DEFAULTS.structure.camera_position,
115
- camera_target = undefined,
116
- camera_projection = DEFAULTS.structure.camera_projection,
117
- rotation_damping = DEFAULTS.structure.rotation_damping,
118
- max_zoom = DEFAULTS.structure.max_zoom,
119
- min_zoom = DEFAULTS.structure.min_zoom,
120
- rotate_speed = DEFAULTS.structure.rotate_speed,
121
- zoom_speed = DEFAULTS.structure.zoom_speed,
122
- pan_speed = DEFAULTS.structure.pan_speed,
123
- zoom_to_cursor = DEFAULTS.structure.zoom_to_cursor,
124
- show_atoms = DEFAULTS.structure.show_atoms,
125
- show_bonds = DEFAULTS.structure.show_bonds,
126
- show_site_labels = DEFAULTS.structure.show_site_labels,
127
- show_site_indices = DEFAULTS.structure.show_site_indices,
128
- site_label_size = DEFAULTS.structure.site_label_size,
129
- site_label_offset = $bindable(DEFAULTS.structure.site_label_offset),
130
- site_label_bg_color = DEFAULTS.structure.site_label_bg_color,
131
- site_label_color = DEFAULTS.structure.site_label_color,
132
- site_label_padding = DEFAULTS.structure.site_label_padding,
133
- vector_configs = $bindable<Record<string, VectorLayerConfig>>({}),
134
- vector_scale = DEFAULTS.structure.vector_scale,
135
- vector_color = DEFAULTS.structure.vector_color,
136
- vector_color_mode = DEFAULTS.structure.vector_color_mode as VectorColorMode,
137
- vector_color_scale = DEFAULTS.structure.vector_color_scale,
138
- vector_normalize = DEFAULTS.structure.vector_normalize,
139
- vector_uniform_thickness = DEFAULTS.structure.vector_uniform_thickness,
140
- vector_origin_gap = DEFAULTS.structure.vector_origin_gap,
141
- vector_shaft_radius = DEFAULTS.structure.vector_shaft_radius,
142
- vector_arrow_head_radius = DEFAULTS.structure.vector_arrow_head_radius,
143
- vector_arrow_head_length = DEFAULTS.structure.vector_arrow_head_length,
144
- gizmo = DEFAULTS.structure.show_gizmo,
145
- hovered_idx = $bindable(null),
146
- hovered_site = $bindable(null),
147
- float_fmt = `.3~f`,
148
- auto_rotate = DEFAULTS.structure.auto_rotate,
149
- bond_thickness = DEFAULTS.structure.bond_thickness,
150
- bond_color = DEFAULTS.structure.bond_color,
151
- bonding_strategy = DEFAULTS.structure.bonding_strategy,
152
- auto_bond_order = DEFAULTS.structure.auto_bond_order,
153
- aromatic_display = DEFAULTS.structure.aromatic_display,
154
- bonding_options = {},
155
- fov = DEFAULTS.structure.fov,
156
- initial_zoom = DEFAULTS.structure.initial_zoom,
157
- ambient_light = DEFAULTS.structure.ambient_light,
158
- directional_light = DEFAULTS.structure.directional_light,
159
- sphere_segments = DEFAULTS.structure.sphere_segments,
160
- lattice_props = {},
161
- atom_label,
162
- camera_is_moving = $bindable(false),
163
- width = 0,
164
- height = 0,
165
- measure_mode = `distance`,
166
- selected_sites = $bindable([]),
167
- measured_sites = $bindable([]),
168
- added_bonds = $bindable([]),
169
- removed_bonds = $bindable([]),
170
- bond_order_overrides = $bindable([]),
171
- bond_edits_enabled = true,
172
- selection_highlight_color = `#6cf0ff`,
173
- // Active highlight group with different color
174
- active_sites = $bindable([]),
175
- active_highlight_color = `var(--struct-active-highlight-color, #2563eb)`,
176
- rotation = DEFAULTS.structure.rotation,
177
- scene = $bindable(),
178
- camera = $bindable(),
179
- orbit_controls = $bindable(),
180
- rotation_target_ref = $bindable(),
181
- initial_computed_zoom = $bindable(),
182
- hidden_elements = $bindable(new SvelteSet()),
183
- hidden_prop_vals = $bindable(new SvelteSet<number | string>()),
184
- element_radius_overrides = $bindable<Partial<Record<ElementSymbol, number>>>({}),
185
- site_radius_overrides = $bindable<SvelteMap<number, number>>(new SvelteMap()),
186
- atom_color_config = {
187
- mode: DEFAULTS.structure.atom_color_mode,
188
- scale: DEFAULTS.structure.atom_color_scale as D3InterpolateName,
189
- scale_type: DEFAULTS.structure.atom_color_scale_type,
190
- },
191
- sym_data = null,
192
- // Edit-atoms mode callbacks
193
- on_sites_moved,
194
- on_operation_start,
195
- on_add_atom,
196
- add_atom_mode = $bindable(false),
197
- add_element = $bindable(`C`),
198
- cursor = $bindable(`default`),
199
- dragging_atoms = $bindable(false),
200
- volumetric_data = undefined,
201
- isosurface_settings = DEFAULT_ISOSURFACE_SETTINGS,
202
- }: {
203
- structure?: AnyStructure
204
- base_structure?: AnyStructure // The original structure without image atoms, used for property color calculation
205
- atom_radius?: number // scale factor for atomic radii
206
- same_size_atoms?: boolean // whether to use the same radius for all atoms. if not, the radius will be
207
- // determined by the atomic radius of the element
208
- camera_position?: [x: number, y: number, z: number] // initial camera position from which to render the scene
209
- camera_target?: Vec3 // external orbit-controls target for pan synchronization
210
- camera_projection?: CameraProjection // camera projection type
211
- rotation_damping?: number // rotation damping factor (how quickly the rotation comes to rest after mouse release)
212
- // zoom level of the camera
213
- max_zoom?: number
214
- min_zoom?: number
215
- rotate_speed?: number // rotation speed. set to 0 to disable rotation.
216
- zoom_speed?: number // zoom speed. set to 0 to disable zooming.
217
- pan_speed?: number // pan speed. set to 0 to disable panning.
218
- zoom_to_cursor?: boolean // zoom toward cursor position instead of scene center
219
- show_atoms?: boolean
220
- show_bonds?: ShowBonds
221
- show_site_labels?: boolean
222
- show_site_indices?: boolean
223
- vector_configs?: Record<string, VectorLayerConfig>
224
- vector_scale?: number
225
- vector_color?: string
226
- vector_color_mode?: VectorColorMode
227
- vector_color_scale?: D3InterpolateName
228
- vector_normalize?: boolean
229
- vector_uniform_thickness?: boolean
230
- vector_origin_gap?: number
231
- vector_shaft_radius?: number
232
- vector_arrow_head_radius?: number
233
- vector_arrow_head_length?: number
234
- gizmo?: boolean | ComponentProps<typeof extras.Gizmo>
235
- hovered_idx?: number | null
236
- hovered_site?: Site | null
237
- float_fmt?: string
238
- auto_rotate?: number
239
- initial_zoom?: number
240
- bond_thickness?: number
241
- bond_color?: string
242
- bonding_strategy?: BondingStrategy
243
- auto_bond_order?: boolean
244
- aromatic_display?: `aromatic` | `kekule`
245
- bonding_options?: Record<string, unknown>
246
- fov?: number
247
- ambient_light?: number
248
- directional_light?: number
249
- sphere_segments?: number
250
- lattice_props?: ComponentProps<typeof Lattice>
251
- atom_label?: Snippet<[{ site: Site; site_idx: number }]>
252
- site_label_size?: number
253
- site_label_offset?: Vec3
254
- site_label_bg_color?: string
255
- site_label_color?: string
256
- site_label_padding?: number
257
- camera_is_moving?: boolean // used to prevent tooltip from showing while camera is moving
258
- width?: number // Viewer dimensions for responsive zoom
259
- height?: number
260
- // measurement props
261
- measure_mode?: MeasureMode
262
- selected_sites?: number[]
263
- measured_sites?: number[]
264
- added_bonds?: StructureBond[]
265
- removed_bonds?: StructureBond[]
266
- bond_order_overrides?: StructureBond[]
267
- bond_edits_enabled?: boolean
268
- selection_highlight_color?: string
269
- // Support for active highlight group with different color
270
- active_sites?: number[]
271
- active_highlight_color?: string
272
- rotation?: Vec3 // rotation control prop
273
- // Expose scene and camera for external use (e.g. export pane)
274
- scene?: Scene
275
- camera?: Camera
276
- orbit_controls?: ComponentProps<typeof extras.OrbitControls>[`ref`] // OrbitControls instance
277
- rotation_target_ref?: Vec3 // Expose rotation target for reset
278
- initial_computed_zoom?: number // Expose initial zoom for reset
279
- hidden_elements?: Set<ElementSymbol>
280
- hidden_prop_vals?: Set<number | string> // Track hidden property values (e.g. Wyckoff positions, coordination numbers)
281
- element_radius_overrides?: Partial<Record<ElementSymbol, number>> // Per-element absolute radius in Angstroms
282
- site_radius_overrides?: Map<number, number> | SvelteMap<number, number> // Per-site absolute radius in Angstroms
283
- atom_color_config?: Partial<AtomColorConfig> // Atom coloring configuration
284
- sym_data?: MoyoDataset | null // Symmetry data for Wyckoff coloring
285
- // Edit-atoms mode callbacks and state
286
- on_sites_moved?: (scene_indices: number[], delta: Vec3) => void
287
- on_operation_start?: () => void
288
- on_add_atom?: (xyz: Vec3, element: ElementSymbol) => void
289
- add_atom_mode?: boolean // whether user is in click-to-place add-atom sub-mode
290
- add_element?: ElementSymbol // element to add when clicking in add-atom mode
291
- cursor?: string // cursor style for the 3D canvas
292
- dragging_atoms?: boolean // true while TransformControls drag is active (skips expensive recalculations)
293
- volumetric_data?: VolumetricData // Active volumetric data for isosurface rendering
294
- isosurface_settings?: IsosurfaceSettings // Isosurface rendering settings
295
- } = $props()
296
-
297
- const threlte = useThrelte()
298
- $effect(() => {
299
- scene = threlte.scene
300
- camera = threlte.camera.current
301
- if (threlte.renderer) {
302
- Object.assign(threlte.renderer.domElement, { __renderer: threlte.renderer })
303
- }
304
- })
305
-
306
- // Expose rotation target for external reset
307
- $effect(() => {
308
- rotation_target_ref = rotation_target
309
- })
310
-
311
- // Track initial computed zoom for reset
312
- let stored_initial_zoom = $state<number | undefined>(undefined)
313
- $effect(() => {
314
- if (stored_initial_zoom === undefined && computed_zoom > 0) {
315
- stored_initial_zoom = computed_zoom
316
- }
317
- initial_computed_zoom = stored_initial_zoom
318
- })
319
-
320
- let bond_pairs: BondPair[] = $state([])
321
- let active_tooltip = $state<`atom` | `bond` | null>(null)
322
- let hovered_bond_key = $state<string | null>(null)
323
-
324
- // Cursor style for the canvas, derived from mode and hover state
325
- let canvas_cursor = $derived.by(() => {
326
- if (measure_mode === `edit-atoms` && add_atom_mode) return `crosshair`
327
- if (hovered_idx != null) {
328
- if (measure_mode === `edit-bonds`) {
329
- return bond_edits_enabled && is_editable_bond_site(hovered_idx)
330
- ? `pointer`
331
- : `not-allowed`
332
- }
333
- if (measure_mode === `edit-atoms`) {
334
- const site = structure?.sites?.[hovered_idx]
335
- if (site?.properties?.orig_site_idx != null) return `not-allowed`
336
- return `pointer`
337
- }
338
- return `pointer`
339
- }
340
- return `default`
341
- })
342
-
343
- // Desaturate a color by blending it toward gray (for ghosting image atoms in edit mode)
344
- const gray = new Color(0x999999)
345
- function desaturate(hex: string | undefined, amount = 0.4): string {
346
- return `#${new Color(hex ?? 0x999999).lerp(gray, amount).getHexString()}`
347
- }
348
-
349
- // === Edit-atoms mode state ===
350
- let transform_object = $state<Mesh | undefined>(undefined)
351
- // Plain variable — only used imperatively in TransformControls drag handlers
352
- let drag_start_centroid: Vec3 | null = null
353
- // Frozen centroid set on drag start. While non-null, the TransformControls mesh
354
- // position stays at this fixed value so Svelte's reactive centroid updates (from
355
- // PBC wrapping) don't fight TransformControls. Cleared on mouseUp so the mesh
356
- // snaps to the new wrapped centroid.
357
- let frozen_centroid = $state<Vec3 | null>(null)
358
-
359
- const BOND_ORDER_OPTIONS: { order: BondOrder; label: string }[] = [
360
- { order: 1, label: `Single` },
361
- { order: 2, label: `Double` },
362
- { order: 3, label: `Triple` },
363
- { order: `aromatic`, label: `Aromatic` },
364
- ]
365
- let bond_context_menu = $state<BondContextMenu | null>(null)
366
- // Threlte/HTML pointer events can close the visible menu before a button
367
- // handler runs, so keep the target bond separately for menu actions.
368
- let bond_context_target: BondContextMenu | null = null
369
-
370
- function close_bond_context_menu() {
371
- bond_context_menu = null
372
- bond_context_target = null
373
- }
374
-
375
- const make_bond_record = (
376
- site_idx_1: number,
377
- site_idx_2: number,
378
- order: BondOrder,
379
- cell_shift?: Vec3,
380
- ): StructureBond => normalize_structure_bond(site_idx_1, site_idx_2, order, cell_shift)
381
-
382
- const bond_key_for = (bond: BondKeyTarget): string =>
383
- get_bond_key(bond.site_idx_1, bond.site_idx_2, bond.cell_shift)
384
-
385
- const matches_bond_key = (bond: BondKeyTarget, key: string): boolean =>
386
- bond_key_for(bond) === key
387
-
388
- function is_editable_bond_site(site_idx: number): boolean {
389
- return structure?.sites?.[site_idx]?.properties?.orig_site_idx == null
390
- }
391
-
392
- const can_edit_bond = (bond: BondKeyTarget): boolean =>
393
- bond_edits_enabled &&
394
- is_editable_bond_site(bond.site_idx_1) &&
395
- is_editable_bond_site(bond.site_idx_2)
396
-
397
- const format_bond_order = (order: BondOrder | undefined): string =>
398
- order === undefined ? `1` : `${order}`
399
-
400
- function get_current_bond_order(
401
- site_idx_1: number,
402
- site_idx_2: number,
403
- cell_shift?: Vec3,
404
- ): BondOrder | undefined {
405
- const key = get_bond_key(site_idx_1, site_idx_2, cell_shift)
406
- return bond_order_overrides.find((bond) => matches_bond_key(bond, key))?.order ??
407
- added_bonds.find((bond) => matches_bond_key(bond, key))?.order ??
408
- filtered_bond_pairs.find((bond) => matches_bond_key(bond, key))?.bond_order
409
- }
410
-
411
- const midpoint = (pos_1: Vec3, pos_2: Vec3): Vec3 => [
412
- (pos_1[0] + pos_2[0]) / 2,
413
- (pos_1[1] + pos_2[1]) / 2,
414
- (pos_1[2] + pos_2[2]) / 2,
415
- ]
416
-
417
- let label_screen_margin = $derived(site_label_size * 10 + site_label_padding)
418
-
419
- function open_bond_context_menu(bond: BondPair) {
420
- if (!can_edit_bond(bond)) return
421
- bond_context_target = {
422
- site_idx_1: bond.site_idx_1,
423
- site_idx_2: bond.site_idx_2,
424
- cell_shift: bond.cell_shift,
425
- position: midpoint(bond.pos_1, bond.pos_2),
426
- }
427
- bond_context_menu = bond_context_target
428
- }
429
-
430
- // Toggle a bond between two atoms: cycles through add → remove → restore states
431
- function toggle_bond(site_1: number, site_2: number, cell_shift?: Vec3) {
432
- if (!can_edit_bond({ site_idx_1: site_1, site_idx_2: site_2, cell_shift })) return
433
- const record = make_bond_record(site_1, site_2, 1, cell_shift)
434
- const key = bond_key_for(record)
435
- if (added_bonds.some((bond) => matches_bond_key(bond, key))) {
436
- added_bonds = added_bonds.filter((bond) => !matches_bond_key(bond, key))
437
- return
438
- }
439
- if (removed_bonds.some((bond) => matches_bond_key(bond, key))) {
440
- removed_bonds = removed_bonds.filter((bond) => !matches_bond_key(bond, key))
441
- return
442
- }
443
- const has_calculated_bond = bond_pairs.some((bond) => matches_bond_key(bond, key))
444
- if (bond_order_overrides.some((bond) => matches_bond_key(bond, key))) {
445
- bond_order_overrides = bond_order_overrides.filter((bond) =>
446
- !matches_bond_key(bond, key)
447
- )
448
- if (has_calculated_bond) removed_bonds = [...removed_bonds, record]
449
- return
450
- }
451
- if (has_calculated_bond) removed_bonds = [...removed_bonds, record]
452
- else added_bonds = [...added_bonds, record]
453
- }
454
-
455
- function set_bond_order(
456
- site_idx_1: number,
457
- site_idx_2: number,
458
- order: BondOrder,
459
- cell_shift?: Vec3,
460
- ) {
461
- if (!can_edit_bond({ site_idx_1, site_idx_2, cell_shift })) return
462
- const key = get_bond_key(site_idx_1, site_idx_2, cell_shift)
463
- const new_record = make_bond_record(site_idx_1, site_idx_2, order, cell_shift)
464
- added_bonds = added_bonds.filter((bond) => !matches_bond_key(bond, key))
465
- const has_calculated_bond = bond_pairs.some((bond) => matches_bond_key(bond, key))
466
- if (has_calculated_bond) {
467
- bond_order_overrides = [
468
- ...bond_order_overrides.filter((bond) => !matches_bond_key(bond, key)),
469
- new_record,
470
- ]
471
- removed_bonds = removed_bonds.filter((bond) => !matches_bond_key(bond, key))
472
- } else {
473
- added_bonds = [...added_bonds, new_record]
474
- }
475
- close_bond_context_menu()
476
- }
477
-
478
- function set_context_bond_order(order: BondOrder) {
479
- const menu = bond_context_target ?? bond_context_menu
480
- if (!menu) return
481
- set_bond_order(menu.site_idx_1, menu.site_idx_2, order, menu.cell_shift)
482
- }
483
-
484
- function remove_bond(site_idx_1: number, site_idx_2: number, cell_shift?: Vec3) {
485
- if (!can_edit_bond({ site_idx_1, site_idx_2, cell_shift })) return
486
- const key = get_bond_key(site_idx_1, site_idx_2, cell_shift)
487
- added_bonds = added_bonds.filter((bond) => !matches_bond_key(bond, key))
488
- bond_order_overrides = bond_order_overrides.filter((bond) =>
489
- !matches_bond_key(bond, key)
490
- )
491
- if (
492
- bond_pairs.some((bond) => matches_bond_key(bond, key)) &&
493
- !removed_bonds.some((bond) => matches_bond_key(bond, key))
494
- ) {
495
- removed_bonds = [
496
- ...removed_bonds,
497
- make_bond_record(site_idx_1, site_idx_2, 1, cell_shift),
498
- ]
499
- }
500
- close_bond_context_menu()
501
- }
502
-
503
- function remove_context_bond() {
504
- const menu = bond_context_target ?? bond_context_menu
505
- if (!menu) return
506
- remove_bond(menu.site_idx_1, menu.site_idx_2, menu.cell_shift)
507
- }
508
-
509
- // Deduplicate clicks: when a highlight sphere and the underlying atom both
510
- // intercept the same native click, only the first intersection should fire.
511
- // All threlte intersection events from one click share the same nativeEvent ref.
512
- let last_native_event: Event | null = null
513
-
514
- function toggle_selection(site_index: number, evt?: Event) {
515
- evt?.stopPropagation?.()
516
- const native_event = (evt as Event & { nativeEvent?: unknown } | undefined)
517
- ?.nativeEvent
518
- if (native_event instanceof Event) {
519
- if (native_event === last_native_event) return
520
- last_native_event = native_event
521
- }
522
-
523
- if (measure_mode === `edit-bonds`) {
524
- if (!bond_edits_enabled || !is_editable_bond_site(site_index)) return
525
- // In edit-bonds mode, select atoms to add/remove bonds between them
526
- const new_sites = measured_sites.includes(site_index)
527
- ? measured_sites.filter((idx) => idx !== site_index)
528
- : [...measured_sites, site_index]
529
-
530
- measured_sites = new_sites
531
- selected_sites = new_sites
532
-
533
- // When two atoms are selected, toggle the bond between them
534
- if (measured_sites.length === 2) {
535
- toggle_bond(measured_sites[0], measured_sites[1])
536
- measured_sites = []
537
- selected_sites = []
538
- }
539
- return
540
- }
541
-
542
- if (measure_mode === `edit-atoms`) {
543
- // Block image atoms (detected by orig_site_idx property from PBC)
544
- const site = structure?.sites?.[site_index]
545
- if (site?.properties?.orig_site_idx != null) return
546
-
547
- const is_selected = selected_sites.includes(site_index)
548
- const is_shift = evt instanceof MouseEvent && evt.shiftKey
549
-
550
- // In edit-atoms mode, selected_sites and measured_sites always stay in sync
551
- let new_sites: number[]
552
- if (is_shift) {
553
- // Multi-select: toggle this site in/out of selection
554
- new_sites = is_selected
555
- ? selected_sites.filter((idx) => idx !== site_index)
556
- : [...selected_sites, site_index]
557
- } else {
558
- // Single-select: replace selection (or deselect if already selected)
559
- new_sites = is_selected ? [] : [site_index]
560
- }
561
- selected_sites = new_sites
562
- measured_sites = new_sites
563
- return
564
- }
565
-
566
- if (
567
- !measured_sites.includes(site_index) &&
568
- measured_sites.length >= measure.MAX_SELECTED_SITES
569
- ) {
570
- console.warn(
571
- `Selection size limit reached (${measure.MAX_SELECTED_SITES}). Deselect some sites first.`,
572
- )
573
- return
574
- }
575
-
576
- measured_sites = measured_sites.includes(site_index)
577
- ? measured_sites.filter((idx) => idx !== site_index)
578
- : [...measured_sites, site_index]
579
- selected_sites = selected_sites.includes(site_index)
580
- ? selected_sites.filter((idx) => idx !== site_index)
581
- : [...selected_sites, site_index]
582
- }
583
-
584
- $effect(() => {
585
- void structure
586
- void measure_mode
587
- void bond_edits_enabled
588
- untrack(() => {
589
- close_bond_context_menu()
590
- hovered_bond_key = null
591
- })
592
- })
593
-
594
- $effect(() => {
595
- const count = structure?.sites?.length ?? 0
596
- if (count <= 0) {
597
- measured_sites = []
598
- return
599
- }
600
- untrack(() => {
601
- measured_sites = measured_sites.filter((idx) => idx >= 0 && idx < count)
602
- })
603
- })
604
-
605
- $effect(() => {
606
- cursor = canvas_cursor
607
- })
608
-
609
- extras.interactivity()
610
- $effect.pre(() => {
611
- hovered_site = structure?.sites?.[hovered_idx ?? -1] ?? null
612
- })
613
- let lattice = $derived(
614
- structure && `lattice` in structure ? structure.lattice : null,
615
- )
616
-
617
- let visual_lattice = $derived(
618
- base_structure && `lattice` in base_structure ? base_structure.lattice : lattice,
619
- )
620
-
621
- let rotation_target = $derived(
622
- lattice
623
- ? (math.scale(math.add(...lattice.matrix), 0.5) as Vec3)
624
- : structure
625
- ? get_center_of_mass(structure)
626
- : [0, 0, 0] as Vec3,
627
- )
628
-
629
- let structure_size = $derived(
630
- lattice ? (lattice.a + lattice.b + lattice.c) / 2 : 10,
631
- )
632
-
633
- // Characteristic inter-atomic spacing: cube root of volume per atom.
634
- // Excludes PBC image atoms (orig_site_idx) so toggling image atoms doesn't affect arrow sizing.
635
- let char_atom_spacing = $derived.by(() => {
636
- if (!lattice || !structure?.sites?.length) return structure_size
637
- const n_real = structure.sites.filter((site) =>
638
- site.properties?.orig_site_idx == null
639
- ).length
640
- return n_real > 0 ? Math.cbrt(lattice.volume / n_real) : structure_size
641
- })
642
-
643
- // When uniform thickness is on, convert negative (length-relative) radii to
644
- // positive (absolute) values scaled by inter-atomic spacing.
645
- // Already-positive (absolute) values are preserved as-is.
646
- let eff_shaft_radius = $derived(
647
- vector_uniform_thickness && vector_shaft_radius < 0
648
- ? char_atom_spacing * -vector_shaft_radius
649
- : vector_shaft_radius,
650
- )
651
- let eff_head_radius = $derived(
652
- vector_uniform_thickness && vector_arrow_head_radius < 0
653
- ? char_atom_spacing * -vector_arrow_head_radius
654
- : vector_arrow_head_radius,
655
- )
656
- let eff_head_length = $derived(
657
- vector_uniform_thickness && vector_arrow_head_length < 0
658
- ? char_atom_spacing * -vector_arrow_head_length
659
- : vector_arrow_head_length,
660
- )
661
-
662
- // Compute dynamic camera clipping planes based on structure size
663
- // This prevents z-fighting and disappearing objects when zooming in close on large supercells
664
- let camera_near = $derived(Math.max(0.01, structure_size * 0.01))
665
- let camera_far = $derived(Math.max(1000, structure_size * 100))
666
-
667
- // Using $state because this is mutated in an effect based on viewport/structure size
668
- let computed_zoom = $state(untrack(() => initial_zoom))
669
- $effect(() => {
670
- if (!(width > 0) || !(height > 0)) return
671
- const structure_max_dim = Math.max(1, untrack(() => structure_size))
672
- const viewer_min_dim = Math.min(width, height)
673
- const scale_factor = viewer_min_dim / (structure_max_dim * 50) // 50px per unit
674
- let new_zoom = initial_zoom * scale_factor
675
- if (min_zoom && min_zoom > 0) new_zoom = Math.max(min_zoom, new_zoom)
676
- if (max_zoom && max_zoom > 0) new_zoom = Math.min(max_zoom, new_zoom)
677
- computed_zoom = new_zoom
678
- })
679
-
680
- $effect.pre(() => { // Simple initial camera auto-position: proportional to structure size and fov
681
- if (camera_position.every((val) => val === 0) && structure) {
682
- stored_initial_zoom = undefined
683
- const distance = Math.max(1, structure_size) * (60 / fov)
684
- camera_position = [distance, distance * 0.3, distance * 0.8]
685
- }
686
- })
687
- $effect(() => {
688
- if (structure && show_bonds !== `never`) {
689
- // Determine if we should show bonds based on the setting and structure type
690
- const should_show_bonds = show_bonds === `always` ||
691
- (show_bonds === `crystals` && lattice) ||
692
- (show_bonds === `molecules` && !lattice)
693
-
694
- if (should_show_bonds) {
695
- bond_pairs = BONDING_STRATEGIES[bonding_strategy](structure, bonding_options)
696
- } else bond_pairs = []
697
- } else bond_pairs = []
698
- })
699
-
700
- // Compute property-based colors when not using element coloring
701
- // Use base_structure (original unit cell) for color calculation
702
- let property_colors = $derived(
703
- get_property_colors(
704
- base_structure || structure,
705
- atom_color_config,
706
- bonding_strategy,
707
- sym_data,
708
- ),
709
- )
710
- // Compute weighted average radius for a site based on species occupancies
711
- // Normalizes by total occupancy so vacancy-containing sites render at full size
712
- const calc_weighted_radius = (site: Site): number => {
713
- const total_occu = site.species.reduce((sum, { occu }) => sum + occu, 0)
714
- const weighted_sum = site.species.reduce((sum, { element, occu }) => {
715
- const override = element_radius_overrides?.[element as ElementSymbol]
716
- return sum + occu * (override ?? atomic_radii[element] ?? 1)
717
- }, 0)
718
- return total_occu > 0 ? weighted_sum / total_occu : 1
719
- }
720
-
721
- let atom_data = $derived.by(() => {
722
- if (!show_atoms || !structure?.sites) return []
723
- const render_sites = merge_split_partial_sites(structure.sites, hidden_elements)
724
- return render_sites.flatMap(({ site_idx, site, is_image_atom }) => {
725
- const orig_idx = get_orig_site_idx(site, site_idx)
726
-
727
- // Skip sites with hidden property values
728
- const prop_val = property_colors?.values[orig_idx]
729
- if (prop_val !== undefined && hidden_prop_vals.has(prop_val)) return []
730
-
731
- // Calculate radius: same_size > site override > element override > default
732
- // All radii scale uniformly with atom_radius for consistent slider behavior
733
- const base_radius = same_size_atoms
734
- ? 1
735
- : site_radius_overrides?.get(site_idx) ?? calc_weighted_radius(site)
736
- const radius = base_radius * atom_radius
737
-
738
- // Use property color if available (e.g. coordination number, Wyckoff position)
739
- // Otherwise, each species gets its own element color (important for disordered sites)
740
- const site_property_color = property_colors?.colors[orig_idx]
741
-
742
- const visible_species = site.species.filter(({ element }) =>
743
- !hidden_elements.has(element)
744
- )
745
- const slice_geometry = compute_slice_geometry(visible_species)
746
- return slice_geometry.map((slice_data) => {
747
- return {
748
- site_idx,
749
- element: slice_data.element,
750
- occupancy: slice_data.occupancy,
751
- position: site.xyz,
752
- radius,
753
- color: site_property_color ?? colors.element?.[slice_data.element],
754
- has_partial_occupancy: slice_data.occupancy < 1,
755
- start_phi: slice_data.start_phi,
756
- end_phi: slice_data.end_phi,
757
- phi_length: slice_data.phi_length,
758
- render_start_cap: slice_data.render_start_cap,
759
- render_end_cap: slice_data.render_end_cap,
760
- is_image_atom,
761
- }
762
- })
763
- })
764
- })
765
-
766
- // Shared visibility check: site has at least one non-hidden element and
767
- // its property value (if any) isn't hidden. Used by both bond and vector filtering.
768
- const is_site_visible = (site_idx: number): boolean => {
769
- if (!structure?.sites) return false
770
- const site = structure.sites[site_idx]
771
- const has_visible_element = site?.species.some(({ element }) =>
772
- !hidden_elements.has(element)
773
- )
774
- const orig_idx = get_orig_site_idx(site, site_idx)
775
- const prop_val = property_colors?.values[orig_idx]
776
- const prop_visible = prop_val === undefined ||
777
- !hidden_prop_vals.has(prop_val)
778
- return has_visible_element && prop_visible
779
- }
780
-
781
- // Perception layer: bond_pairs with optional bond-order perception applied.
782
- // Off by default (pass-through). Manual overrides are applied downstream in
783
- // filtered_bond_pairs, so they still win over perceived orders.
784
- let perceived_bond_pairs: BondPair[] = $derived.by(() => {
785
- if (!auto_bond_order || !structure?.sites || bond_pairs.length === 0) {
786
- return bond_pairs
787
- }
788
- const total_charge = (`charge` in structure ? structure.charge : 0) ?? 0
789
- const perceived = perceive_bond_orders(structure.sites, bond_pairs, {
790
- total_charge,
791
- })
792
- // Explicit structure.properties.bonds are user-authoritative and must
793
- // never be clobbered by perception. Composition + precedence is a pure,
794
- // unit-tested helper (see compose_perceived_bonds).
795
- return compose_perceived_bonds(
796
- perceived,
797
- get_explicit_bond_metadata(structure),
798
- aromatic_display,
799
- )
800
- })
801
-
802
- let filtered_bond_pairs = $derived.by(() => {
803
- if (!structure?.sites) return perceived_bond_pairs
804
-
805
- // Build set of removed bond keys for efficient lookup
806
- const removed_keys = new Set(
807
- removed_bonds.map(bond_key_for),
808
- )
809
- const order_overrides = new Map(
810
- bond_order_overrides.map((bond) => [bond_key_for(bond), bond.order]),
811
- )
812
-
813
- // Filter calculated bonds: exclude removed and hidden
814
- const calculated = perceived_bond_pairs
815
- .filter((bond) => {
816
- if (removed_keys.has(bond_key_for(bond))) return false
817
- return is_site_visible(bond.site_idx_1) && is_site_visible(bond.site_idx_2)
818
- })
819
- .map((bond) => {
820
- const override = order_overrides.get(bond_key_for(bond))
821
- return override === undefined ? bond : { ...bond, bond_order: override }
822
- })
823
-
824
- // Create BondPair objects for manually added bonds
825
- const added: BondPair[] = []
826
- for (const added_bond of added_bonds) {
827
- const { site_idx_1: idx_i, site_idx_2: idx_j } = added_bond
828
- if (!is_site_visible(idx_i) || !is_site_visible(idx_j)) continue
829
- added.push(structure_bond_to_bond_pair(structure, added_bond))
830
- }
831
-
832
- return [...calculated, ...added]
833
- })
834
-
835
- let editable_bond_pairs = $derived(
836
- bond_edits_enabled ? filtered_bond_pairs.filter(can_edit_bond) : [],
837
- )
838
-
839
- let smart_site_label_offsets = $derived.by(() => {
840
- const offsets = new SvelteMap<number, Vec3>()
841
- if (filtered_bond_pairs.length === 0) return offsets
842
-
843
- const bond_directions_by_site = new SvelteMap<number, Vec3[]>()
844
- const add_bond_direction = (site_idx: number, pos_1: Vec3, pos_2: Vec3) => {
845
- const direction = math.normalize_vec3(
846
- math.subtract(pos_2, pos_1),
847
- [0, 0, 0],
848
- )
849
- if (Math.hypot(...direction) < LABEL_OFFSET_EPS) return
850
- bond_directions_by_site.set(site_idx, [
851
- ...(bond_directions_by_site.get(site_idx) ?? []),
852
- direction,
853
- ])
854
- }
855
-
856
- for (const { site_idx_1, site_idx_2, pos_1, pos_2 } of filtered_bond_pairs) {
857
- add_bond_direction(site_idx_1, pos_1, pos_2)
858
- add_bond_direction(site_idx_2, pos_2, pos_1)
859
- }
860
- for (const [site_idx, bond_directions] of bond_directions_by_site) {
861
- offsets.set(site_idx, choose_site_label_offset(bond_directions, site_label_offset))
862
- }
863
- return offsets
864
- })
865
-
866
- let instanced_bond_groups = $derived.by(() => {
867
- if (!structure?.sites || filtered_bond_pairs.length === 0) return []
868
-
869
- const group = {
870
- thickness: bond_thickness,
871
- ambient_light,
872
- directional_light,
873
- instances: [] as {
874
- matrix: Float32Array
875
- color_start: string
876
- color_end: string
877
- }[],
878
- }
879
-
880
- for (const bond_data of filtered_bond_pairs) {
881
- const site_a = structure.sites[bond_data.site_idx_1]
882
- const site_b = structure.sites[bond_data.site_idx_2]
883
-
884
- const get_majority_color = (site: typeof site_a) => {
885
- if (!site?.species || site.species.length === 0) return bond_color
886
- const majority_species = site.species.reduce((max, spec) =>
887
- spec.occu > max.occu ? spec : max
888
- )
889
- return colors.element?.[majority_species.element] || bond_color
890
- }
891
-
892
- const color_start = get_majority_color(site_a)
893
- const color_end = get_majority_color(site_b)
894
- for (const matrix of get_bond_render_matrices(bond_data, bond_thickness)) {
895
- group.instances.push({ matrix, color_start, color_end })
896
- }
897
- }
898
-
899
- return group.instances.length > 0 ? [group] : []
900
- })
901
-
902
- let radius_by_site_idx = $derived.by(() => {
903
- const map = new SvelteMap<number, number>()
904
- for (const atom of atom_data) {
905
- if (!map.has(atom.site_idx)) map.set(atom.site_idx, atom.radius)
906
- }
907
- return map
908
- })
909
-
910
- // Get radius for a site (for highlight fallback when site is hidden/filtered)
911
- // Checks site_radius_overrides first for consistency with visible atoms
912
- const get_site_radius = (site: Site, site_idx: number | null): number => {
913
- const override = site_idx !== null
914
- ? site_radius_overrides?.get(site_idx)
915
- : undefined
916
- const base_radius = same_size_atoms ? 1 : override ?? calc_weighted_radius(site)
917
- return base_radius * atom_radius
918
- }
919
-
920
- // Interpolate between spin-down (#3498db blue) and spin-up (#e74c3c red)
921
- // based on the z-component direction of a magnetic vector
922
- function spin_direction_color(vec: Vec3): string {
923
- const mag = Math.hypot(...vec)
924
- const z_frac = mag > 1e-10 ? (vec[2] / mag + 1) / 2 : 0.5 // 0=down, 1=up
925
- const red = Math.round(52 + (231 - 52) * z_frac)
926
- const grn = Math.round(152 + (76 - 152) * z_frac)
927
- const blu = Math.round(219 + (60 - 219) * z_frac)
928
- return `#${red.toString(16).padStart(2, `0`)}${
929
- grn.toString(16).padStart(2, `0`)
930
- }${blu.toString(16).padStart(2, `0`)}`
931
- }
932
-
933
- // Build one arrow layer per visible vector key. Auto-scales the longest
934
- // vector to 1.8× char_atom_spacing (cube root of volume per atom).
935
- // When vector_normalize is on, effective_max is 1 so all arrows get equal length.
936
- // Single active key preserves legacy coloring (element for force,
937
- // spin-direction for magmom/spin). Multiple keys use flat palette colors.
938
- let vector_layers = $derived.by(() => {
939
- if (!structure?.sites) return []
940
- const keys = get_structure_vector_keys(structure)
941
- const active_keys = keys.filter((key) => vector_configs[key]?.visible !== false)
942
- if (active_keys.length === 0) return []
943
-
944
- // Build per-site lookup; skip hidden sites so they don't contribute
945
- // arrows or affect autoscaling. null entries = hidden site.
946
- const active_set = new Set(active_keys)
947
- let max_mag = 0
948
- const site_vec_maps = structure.sites.map((site, site_idx) => {
949
- if (!is_site_visible(site_idx)) return null
950
- const map = new SvelteMap<string, Vec3>()
951
- for (const { key, vec } of get_all_site_vectors(site)) {
952
- map.set(key, vec)
953
- if (active_set.has(key)) {
954
- max_mag = Math.max(max_mag, Math.hypot(...vec))
955
- }
956
- }
957
- return map
958
- })
959
-
960
- // When normalize is on, treat all magnitudes as 1 so arrows have equal length
961
- const effective_max = vector_normalize ? 1 : max_mag
962
- const auto_scale = effective_max > 1e-10
963
- ? (char_atom_spacing * 1.8) / effective_max
964
- : 1
965
- const is_single = active_keys.length === 1
966
- const effective_global_scale = auto_scale * vector_scale
967
-
968
- // When vector_origin_gap > 0 and multiple vectors exist at a site,
969
- // arrange arrow origins on a regular polygon centered on the atom, in a
970
- // plane perpendicular to the mean vector direction. The gap is a fraction
971
- // of the visual atom radius (0 = center, 0.5 = halfway to surface).
972
- // get_site_radius() returns the uniform scale applied to SphereGeometry(0.5),
973
- // so visual_radius = get_site_radius() * 0.5.
974
- const site_offsets = (vector_origin_gap > 0 && !is_single)
975
- ? structure.sites.map((site, site_idx) => {
976
- const vec_map = site_vec_maps[site_idx]
977
- if (!vec_map) return null
978
- const site_keys = active_keys.filter((key) => vec_map.has(key))
979
- const n_keys = site_keys.length
980
- if (n_keys <= 1) return null
981
- const visual_radius = get_site_radius(site, site_idx) * 0.5
982
- const gap_abs = vector_origin_gap * visual_radius
983
- let mean: Vec3 = [0, 0, 0]
984
- for (const key of site_keys) {
985
- const vec = vec_map.get(key)
986
- if (vec) mean = math.add(mean, math.normalize_vec3(vec)) as Vec3
987
- }
988
- const mean_dir = math.normalize_vec3(mean, [0, 1, 0] as Vec3)
989
- const [u_vec, v_vec] = math.compute_in_plane_basis(mean_dir)
990
- const offsets = new SvelteMap<string, Vec3>()
991
- for (const [idx, key] of site_keys.entries()) {
992
- const angle = (2 * Math.PI * idx) / n_keys
993
- const dx = math.scale(u_vec, gap_abs * Math.cos(angle)) as Vec3
994
- const dy = math.scale(v_vec, gap_abs * Math.sin(angle)) as Vec3
995
- offsets.set(key, math.add(dx, dy) as Vec3)
996
- }
997
- return offsets
998
- })
999
- : null
1000
-
1001
- const mag_interpolator = get_d3_interpolator(vector_color_scale)
1002
-
1003
- return active_keys.map((key, layer_idx) => {
1004
- const layer_cfg = vector_configs[key]
1005
- const layer_scale = effective_global_scale * (layer_cfg?.scale ?? 1.0)
1006
- const layer_color = layer_cfg?.color ??
1007
- VECTOR_PALETTE[layer_idx % VECTOR_PALETTE.length]
1008
-
1009
- const arrows = structure.sites
1010
- .map((site, site_idx) => {
1011
- const vec_map = site_vec_maps[site_idx]
1012
- if (!vec_map) return null
1013
- const vec = vec_map.get(key)
1014
- if (!vec) return null
1015
-
1016
- // Resolve color mode: explicit per-key color always wins,
1017
- // then multi-key uses palette, then mode-based coloring
1018
- let arrow_color: string
1019
- if (layer_cfg?.color) {
1020
- arrow_color = layer_cfg.color
1021
- } else if (!is_single) arrow_color = layer_color
1022
- else {
1023
- const effective_mode = vector_color_mode === `auto`
1024
- ? (key.startsWith(`magmom`) || key.startsWith(`spin`)
1025
- ? `spin_direction`
1026
- : `element`)
1027
- : vector_color_mode
1028
- if (effective_mode === `magnitude`) {
1029
- const mag = Math.hypot(...vec)
1030
- const norm = max_mag > 1e-10 ? mag / max_mag : 0
1031
- arrow_color = mag_interpolator(norm)
1032
- } else if (effective_mode === `spin_direction`) {
1033
- arrow_color = spin_direction_color(vec)
1034
- } else if (effective_mode === `uniform`) {
1035
- arrow_color = vector_color
1036
- } else {
1037
- const majority_element = site.species.length > 0
1038
- ? site.species.reduce((max, spec) =>
1039
- spec.occu > max.occu ? spec : max
1040
- ).element
1041
- : undefined
1042
- arrow_color =
1043
- (majority_element && colors.element?.[majority_element]) ||
1044
- vector_color
1045
- }
1046
- }
1047
-
1048
- const offset = site_offsets?.[site_idx]?.get(key)
1049
- const position = offset ? math.add(site.xyz, offset) as Vec3 : site.xyz
1050
- const arrow_vec = vector_normalize ? math.normalize_vec3(vec) : vec
1051
-
1052
- return {
1053
- site_idx,
1054
- position,
1055
- vector: arrow_vec,
1056
- scale: layer_scale,
1057
- color: arrow_color,
1058
- }
1059
- })
1060
- .filter((item): item is NonNullable<typeof item> => item !== null)
1061
-
1062
- return { key, arrows }
1063
- })
1064
- })
1065
-
1066
- let instanced_atom_groups = $derived(
1067
- Object.values(
1068
- atom_data
1069
- .filter((atom) => !atom.has_partial_occupancy)
1070
- .reduce(
1071
- (groups, atom) => {
1072
- const { element, radius, color, is_image_atom } = atom
1073
- // Separate image atoms into their own groups for distinct styling in edit-atoms mode
1074
- const key = `${element}-${format_num(radius, `.3~`)}-${color}-${
1075
- is_image_atom ? `img` : `base`
1076
- }`
1077
- const bucket = groups[key] ||
1078
- (groups[key] = { element, radius, color, is_image_atom, atoms: [] })
1079
- bucket.atoms.push(atom)
1080
- return groups
1081
- },
1082
- {} as Record<string, InstancedAtomGroup>,
1083
- ),
1084
- ),
1085
- )
1086
-
1087
- let unique_instanced_atoms = $derived(
1088
- Object.values(
1089
- instanced_atom_groups
1090
- .flatMap((group) => group.atoms)
1091
- .reduce((acc, atom) => {
1092
- acc[atom.site_idx] = atom
1093
- return acc
1094
- }, {} as Record<number, (typeof atom_data)[number]>),
1095
- ),
1096
- )
1097
-
1098
- let gizmo_props = $derived.by(() => {
1099
- const axis_options = Object.fromEntries(
1100
- [...AXIS_COLORS, ...NEG_AXIS_COLORS].map(([axis, color, hover_color]) => [
1101
- axis,
1102
- {
1103
- color,
1104
- labelColor: `#111`,
1105
- opacity: axis.startsWith(`n`) ? 0.9 : 0.8,
1106
- hover: {
1107
- color: hover_color,
1108
- labelColor: `#222222`,
1109
- opacity: axis.startsWith(`n`) ? 1 : 0.9,
1110
- },
1111
- },
1112
- ]),
1113
- )
1114
- return {
1115
- background: { enabled: false },
1116
- className: `responsive-gizmo`,
1117
- ...axis_options,
1118
- ...(typeof gizmo === `boolean` ? {} : gizmo),
1119
- offset: { left: 5, bottom: 5 },
1120
- }
1121
- })
1122
-
1123
- let orbit_controls_props = $derived({
1124
- position: [0, 0, 0],
1125
- enableRotate: rotate_speed > 0,
1126
- rotateSpeed: rotate_speed,
1127
- enableZoom: zoom_speed > 0,
1128
- zoomSpeed: camera_projection === `orthographic` ? zoom_speed * 2 : zoom_speed,
1129
- zoomToCursor: zoom_to_cursor,
1130
- enablePan: pan_speed > 0,
1131
- panSpeed: pan_speed,
1132
- target: camera_target ?? rotation_target,
1133
- maxZoom: max_zoom,
1134
- minZoom: min_zoom,
1135
- autoRotate: Boolean(auto_rotate),
1136
- autoRotateSpeed: auto_rotate,
1137
- enableDamping: Boolean(rotation_damping),
1138
- dampingFactor: rotation_damping,
1139
- onstart: () => {
1140
- camera_is_moving = true
1141
- hovered_idx = null
1142
- bond_context_menu = null
1143
- },
1144
- onend: () => {
1145
- camera_is_moving = false
1146
- },
1147
- })
1148
-
1149
- let measure_line_color = $derived.by(() => {
1150
- if (typeof window === `undefined`) return
1151
- const root_styles = getComputedStyle(document.documentElement)
1152
- const text_color = root_styles.getPropertyValue(`--text-color`).trim()
1153
- return text_color || `#808080`
1154
- })
1155
- </script>
1156
-
1157
- {#snippet bond_instanced_mesh_snippet(
1158
- group: ComponentProps<typeof Bond>[`group`],
1159
- )}
1160
- {#key group.instances.length}
1161
- <Bond {group} />
1162
- {/key}
1163
- {/snippet}
1164
-
1165
- {#snippet site_label_snippet(position: Vec3, site_idx: number)}
1166
- {@const site = structure!.sites[site_idx]}
1167
- {@const visual_radius = (radius_by_site_idx.get(site_idx) ?? 1) * 0.5}
1168
- <extras.HTML
1169
- center
1170
- position={position}
1171
- calculatePosition={make_label_position_calculator(
1172
- position,
1173
- () => smart_site_label_offsets.get(site_idx) ?? site_label_offset,
1174
- visual_radius,
1175
- label_screen_margin,
1176
- )}
1177
- >
1178
- {#if atom_label}
1179
- {@render atom_label({ site, site_idx })}
1180
- {:else}
1181
- <span
1182
- class="atom-label"
1183
- style:font-size="{site_label_size * 0.85}em"
1184
- style:background={site_label_bg_color}
1185
- style:padding="{site_label_padding}px"
1186
- style:color={site_label_color}
1187
- >
1188
- {#if show_site_labels}
1189
- {#if site.species.length === 1}
1190
- {site.species[0].element}{#if show_site_indices}-{site_idx + 1}{/if}
1191
- {:else}
1192
- {@html sanitize_html(site.species.map((spec) =>
1193
- `${spec.element}<sub>${
1194
- format_num(spec.occu, `.3~`).replace(`0.`, `.`)
1195
- }</sub>`
1196
- ).join(``))}{#if show_site_indices}-{
1197
- site_idx + 1
1198
- }{/if}
1199
- {/if}
1200
- {:else if show_site_indices}
1201
- {site_idx + 1}
1202
- {/if}
1203
- </span>
1204
- {/if}
1205
- </extras.HTML>
1206
- {/snippet}
1207
-
1208
- {#if camera_projection === `perspective`}
1209
- <T.PerspectiveCamera
1210
- makeDefault
1211
- position={camera_position}
1212
- {fov}
1213
- near={camera_near}
1214
- far={camera_far}
1215
- >
1216
- <extras.OrbitControls bind:ref={orbit_controls} {...orbit_controls_props}>
1217
- {#if gizmo}<extras.Gizmo {...gizmo_props} />{/if}
1218
- </extras.OrbitControls>
1219
- </T.PerspectiveCamera>
1220
- {:else}
1221
- <T.OrthographicCamera
1222
- makeDefault
1223
- position={camera_position}
1224
- zoom={computed_zoom}
1225
- near={-100}
1226
- far={camera_far}
1227
- >
1228
- <extras.OrbitControls bind:ref={orbit_controls} {...orbit_controls_props}>
1229
- {#if gizmo}<extras.Gizmo {...gizmo_props} />{/if}
1230
- </extras.OrbitControls>
1231
- </T.OrthographicCamera>
1232
- {/if}
1233
-
1234
- <T.DirectionalLight position={[3, 10, 10]} intensity={directional_light} />
1235
- <T.AmbientLight intensity={ambient_light} />
1236
-
1237
- <!-- Apply manual rotation around center: translate to origin, rotate, translate back -->
1238
- <T.Group position={rotation_target}>
1239
- <T.Group {rotation}>
1240
- <T.Group position={math.scale(rotation_target, -1)}>
1241
- {#if show_atoms}
1242
- <!-- Instanced rendering for full occupancy atoms -->
1243
- {#each instanced_atom_groups as
1244
- { element, radius, color, is_image_atom, atoms }
1245
- (`${element}-${radius}-${color}-${is_image_atom ? `img` : `base`}`)
1246
- }
1247
- {@const edit_mode_image = measure_mode === `edit-atoms` && is_image_atom}
1248
- <extras.InstancedMesh
1249
- key="{element}-{format_num(radius, `.3~`)}-{color}-{is_image_atom ? `img` : `base`}-{edit_mode_image}"
1250
- limit={atoms.length}
1251
- range={atoms.length}
1252
- frustumCulled={false}
1253
- >
1254
- <T.SphereGeometry args={[0.5, sphere_segments, sphere_segments]} />
1255
- <T.MeshStandardMaterial
1256
- color={edit_mode_image ? desaturate(color) : color}
1257
- opacity={edit_mode_image ? 0.5 : 1}
1258
- transparent={edit_mode_image}
1259
- />
1260
- {#each atoms as atom (atom.site_idx)}
1261
- <extras.Instance
1262
- position={atom.position}
1263
- scale={atom.radius}
1264
- onpointerenter={() => {
1265
- if (edit_mode_image) return
1266
- hovered_idx = atom.site_idx
1267
- active_tooltip = `atom`
1268
- }}
1269
- onpointerleave={() => {
1270
- if (edit_mode_image) return
1271
- hovered_idx = null
1272
- active_tooltip = null
1273
- }}
1274
- onclick={(event: MouseEvent) => {
1275
- if (edit_mode_image) return
1276
- toggle_selection(atom.site_idx, event)
1277
- }}
1278
- />
1279
- {/each}
1280
- </extras.InstancedMesh>
1281
- {/each}
1282
-
1283
- <!-- Regular rendering for partial occupancy atoms -->
1284
- {#each atom_data.filter((atom) => atom.has_partial_occupancy) as
1285
- atom
1286
- (atom.site_idx + atom.element + atom.occupancy)
1287
- }
1288
- {@const partial_edit_image = measure_mode === `edit-atoms` && atom.is_image_atom}
1289
- {@const ghost_opacity = partial_edit_image ? 0.5 : 1}
1290
- <T.Group
1291
- position={atom.position}
1292
- scale={atom.radius}
1293
- onpointerenter={() => {
1294
- if (partial_edit_image) return
1295
- hovered_idx = atom.site_idx
1296
- active_tooltip = `atom`
1297
- }}
1298
- onpointerleave={() => {
1299
- if (partial_edit_image) return
1300
- hovered_idx = null
1301
- active_tooltip = null
1302
- }}
1303
- onclick={(event: MouseEvent) => {
1304
- if (partial_edit_image) return
1305
- toggle_selection(atom.site_idx, event)
1306
- }}
1307
- >
1308
- {@const partial_color = partial_edit_image
1309
- ? desaturate(atom.color)
1310
- : atom.color}
1311
- <T.Mesh>
1312
- <T.SphereGeometry
1313
- args={[
1314
- 0.5,
1315
- sphere_segments,
1316
- sphere_segments,
1317
- atom.start_phi,
1318
- atom.phi_length,
1319
- ]}
1320
- />
1321
- <T.MeshStandardMaterial
1322
- color={partial_color}
1323
- opacity={ghost_opacity}
1324
- transparent={partial_edit_image}
1325
- />
1326
- </T.Mesh>
1327
-
1328
- {#if atom.has_partial_occupancy && atom.render_start_cap}
1329
- <T.Mesh rotation={[0, atom.start_phi, 0]}>
1330
- <T.CircleGeometry
1331
- args={[
1332
- 0.5,
1333
- sphere_segments,
1334
- PARTIAL_OCCUPANCY_CAP_ARC.start_cap_arc_start,
1335
- PARTIAL_OCCUPANCY_CAP_ARC.arc_length,
1336
- ]}
1337
- />
1338
- <T.MeshStandardMaterial
1339
- color={partial_color}
1340
- side={2}
1341
- opacity={ghost_opacity}
1342
- transparent={partial_edit_image}
1343
- />
1344
- </T.Mesh>
1345
- {/if}
1346
- {#if atom.has_partial_occupancy && atom.render_end_cap}
1347
- <T.Mesh rotation={[0, atom.end_phi, 0]}>
1348
- <T.CircleGeometry
1349
- args={[
1350
- 0.5,
1351
- sphere_segments,
1352
- PARTIAL_OCCUPANCY_CAP_ARC.end_cap_arc_start,
1353
- PARTIAL_OCCUPANCY_CAP_ARC.arc_length,
1354
- ]}
1355
- />
1356
- <T.MeshStandardMaterial
1357
- color={partial_color}
1358
- side={2}
1359
- opacity={ghost_opacity}
1360
- transparent={partial_edit_image}
1361
- />
1362
- </T.Mesh>
1363
- {/if}
1364
- </T.Group>
1365
-
1366
- <!-- Render label only for the first species of this site to avoid duplicates -->
1367
- {#if (show_site_labels || show_site_indices) &&
1368
- atom.element === structure!.sites[atom.site_idx].species[0].element}
1369
- {@render site_label_snippet(atom.position, atom.site_idx)}
1370
- {/if}
1371
- {/each}
1372
-
1373
- <!-- Site labels/indices for instanced atoms -->
1374
- {#if show_site_labels || show_site_indices}
1375
- {#each unique_instanced_atoms as atom (atom.site_idx)}
1376
- {@render site_label_snippet(atom.position, atom.site_idx)}
1377
- {/each}
1378
- {/if}
1379
- {/if}
1380
-
1381
- {#each vector_layers as layer (layer.key)}
1382
- {#each layer.arrows as arrow (`${layer.key}-${arrow.site_idx}`)}
1383
- <Arrow
1384
- {...arrow}
1385
- shaft_radius={eff_shaft_radius}
1386
- arrow_head_radius={eff_head_radius}
1387
- arrow_head_length={eff_head_length}
1388
- />
1389
- {/each}
1390
- {/each}
1391
-
1392
- <!-- Instanced bond rendering with gradient colors -->
1393
- {#if instanced_bond_groups.length > 0}
1394
- {#each instanced_bond_groups as group (group.thickness + group.instances.length)}
1395
- {@render bond_instanced_mesh_snippet(group)}
1396
- {/each}
1397
- {/if}
1398
-
1399
- <!-- Clickable bond hit-test cylinders in edit-bonds mode -->
1400
- {#if measure_mode === `edit-bonds` && editable_bond_pairs.length > 0}
1401
- {#each editable_bond_pairs as
1402
- bond
1403
- (`bond-hit-${bond_key_for(bond)}`)
1404
- }
1405
- {@const bond_key = bond_key_for(bond)}
1406
- {@const is_hovered = hovered_bond_key === bond_key}
1407
- <T.Mesh
1408
- matrixAutoUpdate={false}
1409
- oncreate={(ref) => {
1410
- ref.matrix.fromArray(bond.transform_matrix)
1411
- ref.matrixWorldNeedsUpdate = true
1412
- }}
1413
- onpointerdown={(event: PointerEvent & { nativeEvent?: PointerEvent }) => {
1414
- if (event.nativeEvent?.button === 2) return
1415
- event.stopPropagation()
1416
- toggle_bond(bond.site_idx_1, bond.site_idx_2, bond.cell_shift)
1417
- measured_sites = []
1418
- selected_sites = []
1419
- hovered_bond_key = null
1420
- }}
1421
- oncontextmenu={(event: MouseEvent & { nativeEvent?: MouseEvent }) => {
1422
- event.nativeEvent?.preventDefault()
1423
- event.stopPropagation?.()
1424
- open_bond_context_menu(bond)
1425
- }}
1426
- onpointerenter={() => (hovered_bond_key = bond_key)}
1427
- onpointerleave={() => (hovered_bond_key = null)}
1428
- >
1429
- <T.CylinderGeometry args={[bond_thickness * 3, bond_thickness * 3, 1, 6]} />
1430
- <T.MeshBasicMaterial
1431
- transparent
1432
- opacity={is_hovered ? 0.25 : 0}
1433
- color={is_hovered ? `#ff4444` : `white`}
1434
- depthWrite={false}
1435
- />
1436
- </T.Mesh>
1437
- {/each}
1438
- {/if}
1439
-
1440
- {#if measure_mode === `edit-bonds` && bond_context_menu}
1441
- {@const current_order = get_current_bond_order(
1442
- bond_context_menu.site_idx_1,
1443
- bond_context_menu.site_idx_2,
1444
- bond_context_menu.cell_shift,
1445
- )}
1446
- <extras.HTML center position={bond_context_menu.position}>
1447
- <div class="bond-context-menu">
1448
- <strong>Bond Order ({format_bond_order(current_order)})</strong>
1449
- {#each BOND_ORDER_OPTIONS as { order, label } (label)}
1450
- <button
1451
- type="button"
1452
- onpointerdown={(event: PointerEvent) => {
1453
- event.preventDefault()
1454
- event.stopPropagation()
1455
- set_context_bond_order(order)
1456
- }}
1457
- onkeydown={(event: KeyboardEvent) => {
1458
- if (event.key !== `Enter` && event.key !== ` `) return
1459
- event.preventDefault()
1460
- event.stopPropagation()
1461
- set_context_bond_order(order)
1462
- }}
1463
- >
1464
- {label}
1465
- </button>
1466
- {/each}
1467
- <button
1468
- type="button"
1469
- class="remove"
1470
- onpointerdown={(event: PointerEvent) => {
1471
- event.preventDefault()
1472
- event.stopPropagation()
1473
- remove_context_bond()
1474
- }}
1475
- onkeydown={(event: KeyboardEvent) => {
1476
- if (event.key !== `Enter` && event.key !== ` `) return
1477
- event.preventDefault()
1478
- event.stopPropagation()
1479
- remove_context_bond()
1480
- }}
1481
- >
1482
- Remove
1483
- </button>
1484
- <button
1485
- type="button"
1486
- onpointerdown={(event: PointerEvent) => {
1487
- event.preventDefault()
1488
- event.stopPropagation()
1489
- close_bond_context_menu()
1490
- }}
1491
- onkeydown={(event: KeyboardEvent) => {
1492
- if (event.key !== `Enter` && event.key !== ` `) return
1493
- event.preventDefault()
1494
- event.stopPropagation()
1495
- close_bond_context_menu()
1496
- }}
1497
- >
1498
- Close
1499
- </button>
1500
- </div>
1501
- </extras.HTML>
1502
- {/if}
1503
-
1504
- <!-- highlight hovered, active and selected sites -->
1505
- {#each [
1506
- {
1507
- kind: `hover`,
1508
- site: hovered_site,
1509
- opacity: 0.28,
1510
- color: `white`,
1511
- site_idx: hovered_idx,
1512
- },
1513
- ...((selected_sites ?? []).map((idx) => ({
1514
- kind: `selected`,
1515
- site: structure?.sites?.[idx] ?? null,
1516
- site_idx: idx,
1517
- opacity: pulse_opacity,
1518
- color: selection_highlight_color,
1519
- }))),
1520
- ...((active_sites ?? []).map((idx) => ({
1521
- kind: `active`,
1522
- site: structure?.sites?.[idx] ?? null,
1523
- site_idx: idx,
1524
- opacity: pulse_opacity, // Let it pulse freely
1525
- color: active_highlight_color,
1526
- }))),
1527
- ] as
1528
- entry
1529
- (`${entry.kind}-${entry.site_idx}`)
1530
- }
1531
- {@const { site, opacity, color, kind, site_idx } = entry}
1532
- {#if site}
1533
- {@const xyz = site.xyz}
1534
- {@const highlight_radius = site_idx !== null
1535
- ? radius_by_site_idx.get(site_idx) ?? get_site_radius(site, site_idx)
1536
- : get_site_radius(site, site_idx)}
1537
- <T.Mesh
1538
- position={xyz}
1539
- scale={1.2 * highlight_radius}
1540
- onclick={(event: MouseEvent) => {
1541
- if (site_idx !== null && Number.isInteger(site_idx)) {
1542
- toggle_selection(site_idx, event)
1543
- }
1544
- }}
1545
- >
1546
- <T.SphereGeometry args={[0.5, 22, 22]} />
1547
- <T.MeshStandardMaterial
1548
- {color}
1549
- transparent
1550
- {opacity}
1551
- emissive={color}
1552
- emissiveIntensity={kind === `selected` || kind === `active` ? 0.7 : 0.2}
1553
- depthTest={false}
1554
- depthWrite={false}
1555
- />
1556
- </T.Mesh>
1557
- {/if}
1558
- {/each}
1559
-
1560
- <!-- selection order labels (1, 2, 3, ...) for measured sites (hidden in edit-atoms mode) -->
1561
- {#if structure?.sites && (measured_sites?.length ?? 0) > 0 &&
1562
- measure_mode !== `edit-atoms`}
1563
- {#each measured_sites as site_index, loop_idx (site_index)}
1564
- {@const site = structure.sites[site_index]}
1565
- {#if site}
1566
- <!-- shift selected site labels down to avoid overlapping regular site labels-->
1567
- {@const selection_offset = math.add(site_label_offset, [0, -0.5, 0])}
1568
- {@const pos = math.add(site.xyz, selection_offset) as Vec3}
1569
- <extras.HTML center position={pos}>
1570
- <span class="selection-label">{loop_idx + 1}</span>
1571
- </extras.HTML>
1572
- {/if}
1573
- {/each}
1574
- {/if}
1575
-
1576
- <!-- hovered site tooltip -->
1577
- {#if hovered_site && !camera_is_moving &&
1578
- (active_tooltip === `atom` || active_sites.includes(hovered_idx ?? -1))}
1579
- {@const abc = hovered_site.abc.map((val) => format_num(val, float_fmt)).join(
1580
- `, `,
1581
- )}
1582
- {@const xyz = hovered_site.xyz.map((val) => format_num(val, float_fmt)).join(
1583
- `, `,
1584
- )}
1585
- {@const bond_neighbors = (() => {
1586
- if (hovered_idx == null || !structure?.sites) return []
1587
- return filtered_bond_pairs
1588
- .filter((b) =>
1589
- b.site_idx_1 === hovered_idx || b.site_idx_2 === hovered_idx
1590
- )
1591
- .map((b) => {
1592
- const neighbor_idx = b.site_idx_1 === hovered_idx
1593
- ? b.site_idx_2
1594
- : b.site_idx_1
1595
- return structure.sites[neighbor_idx]?.species[0]?.element ?? `?`
1596
- })
1597
- })()}
1598
- {@const bond_summary = (() => {
1599
- if (bond_neighbors.length === 0) return ``
1600
- const counts: Record<string, number> = {}
1601
- for (const elem of bond_neighbors) {
1602
- counts[elem] = (counts[elem] ?? 0) + 1
1603
- }
1604
- const parts = Object.entries(counts)
1605
- .sort(([a], [b]) => a.localeCompare(b))
1606
- .map(([elem, count]) => `${elem}: ${count}`)
1607
- return ` (${parts.join(`, `)})`
1608
- })()}
1609
- <CanvasTooltip position={hovered_site.xyz}>
1610
- <!-- Element symbols with occupancies for disordered sites -->
1611
- <div class="elements">
1612
- {#each hovered_site.species ?? [] as
1613
- { element, occu, oxidation_state: oxi_state },
1614
- idx
1615
- (`${element ?? ``}-${occu ?? ``}-${oxi_state ?? ``}-${idx}`)
1616
- }
1617
- {@const oxi_str = (oxi_state != null && oxi_state !== 0)
1618
- ? `<sup>${Math.abs(oxi_state)}${
1619
- oxi_state > 0 ? `+` : `−`
1620
- }</sup>`
1621
- : ``}
1622
- {@const element_name = element_data.find((elem) =>
1623
- elem.symbol === element
1624
- )?.name ??
1625
- ``}
1626
- {#if idx > 0}&thinsp;{/if}
1627
- {#if occu !== 1}<span class="occupancy">{
1628
- format_num(occu, `.3~f`)
1629
- }</span>{/if}
1630
- <strong>{element}{@html sanitize_html(oxi_str)}</strong>
1631
- {#if element_name}<span class="elem-name">{element_name}</span>{/if}
1632
- {/each}
1633
- </div>
1634
- <div class="coordinates fractional">abc: ({abc})</div>
1635
- <div class="coordinates cartesian">xyz: ({xyz}) Å</div>
1636
- {#if bond_neighbors.length > 0}
1637
- <div class="coordinates">Bonds: {bond_neighbors.length}{bond_summary}</div>
1638
- {/if}
1639
- </CanvasTooltip>
1640
- {/if}
1641
-
1642
- {#if visual_lattice}
1643
- <Lattice matrix={visual_lattice.matrix} {...lattice_props} />
1644
- {/if}
1645
-
1646
- <!-- TransformControls for editing atoms in edit-atoms mode -->
1647
- {#if measure_mode === `edit-atoms` && selected_sites.length > 0 &&
1648
- structure?.sites}
1649
- {@const selected_atoms = selected_sites
1650
- .map((idx) => structure?.sites?.[idx])
1651
- .filter((site): site is Site => site != null)}
1652
- {#if selected_atoms.length > 0}
1653
- {@const avg = (dim: number) =>
1654
- selected_atoms.reduce((sum, atom) => sum + atom.xyz[dim], 0) /
1655
- selected_atoms.length}
1656
- {@const centroid = [avg(0), avg(1), avg(2)] as Vec3}
1657
- <!-- Invisible mesh at centroid for TransformControls to manipulate.
1658
- During drag, use frozen_centroid so Svelte doesn't override TransformControls
1659
- with the wrapped centroid (which jumps on PBC boundary crossings). -->
1660
- <T.Mesh
1661
- position={frozen_centroid ?? centroid}
1662
- bind:ref={transform_object}
1663
- >
1664
- <T.SphereGeometry args={[0.01, 4, 4]} />
1665
- <T.MeshBasicMaterial transparent opacity={0} />
1666
- </T.Mesh>
1667
- <extras.TransformControls
1668
- object={transform_object}
1669
- translationSnap={0.1}
1670
- size={1.2}
1671
- space="world"
1672
- onobjectChange={() => {
1673
- if (!transform_object?.position || !drag_start_centroid) return
1674
- const { x: tx, y: ty, z: tz } = transform_object.position
1675
- const delta: Vec3 = [
1676
- tx - drag_start_centroid[0],
1677
- ty - drag_start_centroid[1],
1678
- tz - drag_start_centroid[2],
1679
- ]
1680
- // Update reference point so deltas are incremental, not cumulative.
1681
- // Without this, each frame compounds: sites already moved by previous
1682
- // delta get the full cumulative delta re-applied.
1683
- drag_start_centroid = [tx, ty, tz]
1684
- on_sites_moved?.(selected_sites, delta)
1685
- }}
1686
- onmouseDown={() => {
1687
- dragging_atoms = true
1688
- drag_start_centroid = frozen_centroid = [...centroid] as Vec3
1689
- on_operation_start?.()
1690
- }}
1691
- onmouseUp={() => {
1692
- dragging_atoms = false
1693
- frozen_centroid = null
1694
- drag_start_centroid = null
1695
- }}
1696
- />
1697
- {/if}
1698
- {/if}
1699
-
1700
- <!-- Invisible plane for click-to-place atom in add-atom mode -->
1701
- <!-- Uses onBeforeRender to orient normal toward camera so raycasts always hit -->
1702
- {#if measure_mode === `edit-atoms` && add_atom_mode}
1703
- {@const center = rotation_target ?? [0, 0, 0]}
1704
- <T.Mesh
1705
- position={center}
1706
- onBeforeRender={(mesh: Mesh) => {
1707
- if (camera) {
1708
- mesh.lookAt(camera.position)
1709
- }
1710
- }}
1711
- onclick={(event: { point: { x: number; y: number; z: number } }) => {
1712
- const { x, y, z } = event.point
1713
- on_add_atom?.([x, y, z] as Vec3, add_element as ElementSymbol)
1714
- }}
1715
- >
1716
- <T.PlaneGeometry
1717
- args={[
1718
- Math.max(200, structure_size * 4),
1719
- Math.max(200, structure_size * 4),
1720
- ]}
1721
- />
1722
- <T.MeshBasicMaterial transparent opacity={0} side={2} depthWrite={false} />
1723
- </T.Mesh>
1724
- {/if}
1725
-
1726
- <!-- Isosurface rendering from volumetric data (CHGCAR, .cube files) -->
1727
- {#if volumetric_data && isosurface_settings}
1728
- <Isosurface volume={volumetric_data} settings={isosurface_settings} />
1729
- {/if}
1730
-
1731
- <!-- Measurement overlays for measured sites -->
1732
- {#if structure?.sites && (measured_sites?.length ?? 0) > 0}
1733
- {#if measure_mode === `distance`}
1734
- {#each measured_sites as idx_i, loop_idx (idx_i)}
1735
- {#each measured_sites.slice(loop_idx + 1) as idx_j (idx_i + `-` + idx_j)}
1736
- {@const site_i = structure.sites[idx_i]}
1737
- {@const site_j = structure.sites[idx_j]}
1738
- {@const pos_i = site_i.xyz}
1739
- {@const pos_j = site_j.xyz}
1740
- <Cylinder
1741
- from={pos_i}
1742
- to={pos_j}
1743
- thickness={0.12}
1744
- color={measure_line_color}
1745
- />
1746
- {@const midpoint = [
1747
- (pos_i[0] + pos_j[0]) / 2,
1748
- (pos_i[1] + pos_j[1]) / 2,
1749
- (pos_i[2] + pos_j[2]) / 2,
1750
- ] as Vec3}
1751
- {@const direct = math.euclidean_dist(pos_i, pos_j)}
1752
- {@const pbc = lattice
1753
- ? measure.distance_pbc(pos_i, pos_j, lattice.matrix)
1754
- : direct}
1755
- {@const differ = lattice ? Math.abs(pbc - direct) > 1e-6 : false}
1756
- <extras.HTML center position={midpoint}>
1757
- <span class="measure-label">
1758
- {#if differ}
1759
- PBC: {format_num(pbc, float_fmt)} Å<br /><small>
1760
- Direct: {format_num(direct, float_fmt)} Å</small>
1761
- {:else}
1762
- {format_num(pbc, float_fmt)} Å
1763
- {/if}
1764
- </span>
1765
- </extras.HTML>
1766
- {/each}
1767
- {/each}
1768
- {:else if measure_mode === `angle` && measured_sites.length >= 3}
1769
- {#each measured_sites as idx_center (idx_center)}
1770
- {@const center = structure.sites[idx_center]}
1771
- {#each measured_sites.filter((idx) => idx !== idx_center) as
1772
- idx_a,
1773
- loop_idx
1774
- (idx_center + `-` + idx_a)
1775
- }
1776
- {#each measured_sites.filter((idx) => idx !== idx_center).slice(loop_idx + 1) as
1777
- idx_b
1778
- (idx_center + `-` + idx_a + `-` + idx_b)
1779
- }
1780
- {@const site_a = structure.sites[idx_a]}
1781
- {@const site_b = structure.sites[idx_b]}
1782
- {@const v1 = measure.displacement_pbc(center.xyz, site_a.xyz, lattice?.matrix)}
1783
- {@const v2 = measure.displacement_pbc(center.xyz, site_b.xyz, lattice?.matrix)}
1784
- {@const n1 = Math.hypot(v1[0], v1[1], v1[2])}
1785
- {@const n2 = Math.hypot(v2[0], v2[1], v2[2])}
1786
- {@const angle_deg = measure.angle_between_vectors(v1, v2, `degrees`)}
1787
- {#if n1 > math.EPS && n2 > math.EPS}
1788
- <!-- draw rays from center to the two sites -->
1789
- <Cylinder
1790
- from={center.xyz}
1791
- to={site_a.xyz}
1792
- thickness={0.05}
1793
- color={measure_line_color}
1794
- />
1795
- <Cylinder
1796
- from={center.xyz}
1797
- to={site_b.xyz}
1798
- thickness={0.05}
1799
- color={measure_line_color}
1800
- />
1801
- {@const bisector = math.add(math.scale(v1, 1 / n1), math.scale(v2, 1 / n2))}
1802
- {@const bis_norm = Math.hypot(...bisector) || 1}
1803
- {@const offset_dir = math.scale(bisector, 1 / bis_norm)}
1804
- {@const label_pos = math.add(center.xyz, math.scale(offset_dir, 0.6))}
1805
- <extras.HTML center position={label_pos}>
1806
- <span class="measure-label">{format_num(angle_deg, float_fmt)}°</span>
1807
- </extras.HTML>
1808
- {/if}
1809
- {/each}
1810
- {/each}
1811
- {/each}
1812
- {/if}
1813
- {/if}
1814
- </T.Group>
1815
- </T.Group>
1816
- </T.Group>
1817
-
1818
- <style>
1819
- :global(.structure .responsive-gizmo) {
1820
- width: clamp(70px, 18cqmin, 100px) !important;
1821
- height: clamp(70px, 18cqmin, 100px) !important;
1822
- }
1823
- .atom-label {
1824
- background: var(--struct-atom-label-bg, rgba(0, 0, 0, 0.1));
1825
- border-radius: var(--struct-atom-label-border-radius, var(--border-radius, 3pt));
1826
- padding: var(--struct-atom-label-padding, 0 3px);
1827
- white-space: nowrap;
1828
- }
1829
- .elements {
1830
- margin-bottom: var(--canvas-tooltip-elements-margin);
1831
- }
1832
- .occupancy {
1833
- font-size: var(--canvas-tooltip-occu-font-size);
1834
- opacity: var(--canvas-tooltip-occu-opacity);
1835
- margin-right: var(--canvas-tooltip-occu-margin);
1836
- }
1837
- .elem-name {
1838
- font-size: var(--canvas-tooltip-elem-name-font-size, 0.85em);
1839
- opacity: var(--canvas-tooltip-elem-name-opacity, 0.7);
1840
- margin: var(--canvas-tooltip-elem-name-margin, 0 0 0 0.3em);
1841
- font-weight: var(--canvas-tooltip-elem-name-font-weight, normal);
1842
- }
1843
- .coordinates {
1844
- font-size: var(--canvas-tooltip-coords-font-size);
1845
- margin: var(--canvas-tooltip-coords-margin);
1846
- }
1847
- .measure-label {
1848
- background: var(--measure-label-bg, var(--surface-bg));
1849
- color: var(--measure-label-color, var(--text-color));
1850
- border-radius: var(--border-radius, 3pt);
1851
- padding: 0 5px;
1852
- user-select: none;
1853
- white-space: pre;
1854
- display: grid;
1855
- place-items: center;
1856
- line-height: 1.2;
1857
- font-size: var(--canvas-tooltip-font-size, clamp(8pt, 2cqmin, 18pt));
1858
- box-shadow: var(--measure-label-shadow, 0 1px 6px rgba(0, 0, 0, 0.2));
1859
- }
1860
- .bond-context-menu {
1861
- display: grid;
1862
- min-width: 8rem;
1863
- gap: 2pt;
1864
- padding: 5pt;
1865
- border-radius: var(--border-radius, 3pt);
1866
- background: var(--surface-bg, Canvas);
1867
- color: var(--text-color, currentColor);
1868
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
1869
- pointer-events: auto;
1870
- strong {
1871
- font-size: 0.85em;
1872
- padding: 0 2pt 2pt;
1873
- white-space: nowrap;
1874
- }
1875
- button {
1876
- border: none;
1877
- border-radius: var(--border-radius, 3pt);
1878
- background: transparent;
1879
- color: inherit;
1880
- cursor: pointer;
1881
- padding: 2pt 5pt;
1882
- text-align: left;
1883
- }
1884
- button:hover {
1885
- background: color-mix(in srgb, currentColor 10%, transparent);
1886
- }
1887
- button.remove {
1888
- color: var(--error-color, #f44336);
1889
- }
1890
- }
1891
- .selection-label {
1892
- display: inline-flex;
1893
- align-items: center;
1894
- justify-content: center;
1895
- min-width: 1.2em;
1896
- height: 1.2em;
1897
- padding: 0 0.25em;
1898
- border-radius: 999px;
1899
- background: var(--pane-btn-bg-hover);
1900
- color: var(--struct-text-color);
1901
- font-size: 0.85em;
1902
- line-height: 1;
1903
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
1904
- }
1905
- </style>