matterviz 0.3.6 → 0.4.0

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 (926) hide show
  1. package/dist/EmptyState.svelte.d.ts +9 -0
  2. package/dist/FilePicker.svelte +360 -0
  3. package/dist/FilePicker.svelte.d.ts +17 -0
  4. package/dist/Icon.svelte +44 -0
  5. package/dist/Icon.svelte.d.ts +13 -0
  6. package/dist/MillerIndexInput.svelte +66 -0
  7. package/dist/MillerIndexInput.svelte.d.ts +7 -0
  8. package/dist/api/mp.d.ts +6 -0
  9. package/dist/api/mp.js +22 -0
  10. package/dist/api/optimade.d.ts +45 -0
  11. package/dist/api/optimade.js +141 -0
  12. package/dist/app.css +244 -0
  13. package/dist/brillouin/BrillouinZone.svelte +554 -0
  14. package/dist/brillouin/BrillouinZone.svelte.d.ts +84 -0
  15. package/dist/brillouin/BrillouinZoneControls.svelte +144 -0
  16. package/dist/brillouin/BrillouinZoneControls.svelte.d.ts +17 -0
  17. package/dist/brillouin/BrillouinZoneExportPane.svelte +146 -0
  18. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +15 -0
  19. package/dist/brillouin/BrillouinZoneInfoPane.svelte +146 -0
  20. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +13 -0
  21. package/dist/brillouin/BrillouinZoneScene.svelte +522 -0
  22. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +49 -0
  23. package/dist/brillouin/BrillouinZoneTooltip.svelte +83 -0
  24. package/dist/brillouin/BrillouinZoneTooltip.svelte.d.ts +8 -0
  25. package/dist/brillouin/compute.d.ts +17 -0
  26. package/dist/brillouin/compute.js +422 -0
  27. package/dist/brillouin/index.d.ts +8 -0
  28. package/dist/brillouin/index.js +7 -0
  29. package/dist/brillouin/types.d.ts +43 -0
  30. package/dist/brillouin/types.js +1 -0
  31. package/dist/chempot-diagram/ChemPotDiagram.svelte +328 -0
  32. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
  33. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +843 -0
  34. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
  35. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +3191 -0
  36. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
  37. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
  38. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  39. package/dist/chempot-diagram/async-compute.svelte.js +80 -0
  40. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  41. package/dist/chempot-diagram/chempot-worker.js +12 -0
  42. package/dist/chempot-diagram/color.d.ts +10 -0
  43. package/dist/chempot-diagram/color.js +32 -0
  44. package/dist/chempot-diagram/compute.d.ts +48 -0
  45. package/dist/chempot-diagram/compute.js +804 -0
  46. package/dist/chempot-diagram/index.d.ts +6 -0
  47. package/dist/chempot-diagram/index.js +6 -0
  48. package/dist/chempot-diagram/pointer.d.ts +16 -0
  49. package/dist/chempot-diagram/pointer.js +40 -0
  50. package/dist/chempot-diagram/temperature.d.ts +15 -0
  51. package/dist/chempot-diagram/temperature.js +34 -0
  52. package/dist/chempot-diagram/types.d.ts +81 -0
  53. package/dist/chempot-diagram/types.js +28 -0
  54. package/dist/colors/index.d.ts +47 -0
  55. package/dist/colors/index.js +204 -0
  56. package/dist/composition/BarChart.svelte +297 -0
  57. package/dist/composition/BarChart.svelte.d.ts +39 -0
  58. package/dist/composition/BubbleChart.svelte +218 -0
  59. package/dist/composition/BubbleChart.svelte.d.ts +28 -0
  60. package/dist/composition/Composition.svelte +165 -0
  61. package/dist/composition/Composition.svelte.d.ts +15 -0
  62. package/dist/composition/Formula.svelte +268 -0
  63. package/dist/composition/Formula.svelte.d.ts +19 -0
  64. package/dist/composition/FormulaFilter.svelte +1263 -0
  65. package/dist/composition/FormulaFilter.svelte.d.ts +51 -0
  66. package/dist/composition/PieChart.svelte +324 -0
  67. package/dist/composition/PieChart.svelte.d.ts +37 -0
  68. package/dist/composition/chem-sys.d.ts +8 -0
  69. package/dist/composition/chem-sys.js +85 -0
  70. package/dist/composition/format.d.ts +15 -0
  71. package/dist/composition/format.js +111 -0
  72. package/dist/composition/index.d.ts +21 -0
  73. package/dist/composition/index.js +15 -0
  74. package/dist/composition/parse.d.ts +56 -0
  75. package/dist/composition/parse.js +486 -0
  76. package/dist/constants.d.ts +29 -0
  77. package/dist/constants.js +99 -0
  78. package/dist/controls.d.ts +14 -0
  79. package/dist/controls.js +30 -0
  80. package/dist/convex-hull/ConvexHull.svelte +157 -0
  81. package/dist/convex-hull/ConvexHull.svelte.d.ts +13 -0
  82. package/dist/convex-hull/ConvexHull2D.svelte +827 -0
  83. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +11 -0
  84. package/dist/convex-hull/ConvexHull3D.svelte +1801 -0
  85. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +8 -0
  86. package/dist/convex-hull/ConvexHull4D.svelte +1394 -0
  87. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +8 -0
  88. package/dist/convex-hull/ConvexHullControls.svelte +535 -0
  89. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +48 -0
  90. package/dist/convex-hull/ConvexHullInfoPane.svelte +125 -0
  91. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +20 -0
  92. package/dist/convex-hull/ConvexHullStats.svelte +929 -0
  93. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +17 -0
  94. package/dist/convex-hull/ConvexHullTooltip.svelte +131 -0
  95. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +33 -0
  96. package/dist/convex-hull/GasPressureControls.svelte +247 -0
  97. package/dist/convex-hull/GasPressureControls.svelte.d.ts +11 -0
  98. package/dist/convex-hull/StructurePopup.svelte +151 -0
  99. package/dist/convex-hull/StructurePopup.svelte.d.ts +18 -0
  100. package/dist/convex-hull/TemperatureSlider.svelte +140 -0
  101. package/dist/convex-hull/TemperatureSlider.svelte.d.ts +8 -0
  102. package/dist/convex-hull/barycentric-coords.d.ts +18 -0
  103. package/dist/convex-hull/barycentric-coords.js +182 -0
  104. package/dist/convex-hull/demo-temperature.d.ts +6 -0
  105. package/dist/convex-hull/demo-temperature.js +38 -0
  106. package/dist/convex-hull/gas-thermodynamics.d.ts +16 -0
  107. package/dist/convex-hull/gas-thermodynamics.js +306 -0
  108. package/dist/convex-hull/helpers.d.ts +117 -0
  109. package/dist/convex-hull/helpers.js +718 -0
  110. package/dist/convex-hull/index.d.ts +119 -0
  111. package/dist/convex-hull/index.js +58 -0
  112. package/dist/convex-hull/thermodynamics.d.ts +67 -0
  113. package/dist/convex-hull/thermodynamics.js +1757 -0
  114. package/dist/convex-hull/types.d.ts +162 -0
  115. package/dist/convex-hull/types.js +36 -0
  116. package/dist/coordination/CoordinationBarPlot.svelte +311 -0
  117. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +30 -0
  118. package/dist/coordination/calc-coordination.d.ts +15 -0
  119. package/dist/coordination/calc-coordination.js +63 -0
  120. package/dist/coordination/index.d.ts +8 -0
  121. package/dist/coordination/index.js +7 -0
  122. package/dist/effects.svelte.d.ts +12 -0
  123. package/dist/effects.svelte.js +37 -0
  124. package/dist/element/BohrAtom.svelte.d.ts +20 -0
  125. package/dist/element/ElementHeading.svelte +26 -0
  126. package/dist/element/ElementHeading.svelte.d.ts +8 -0
  127. package/dist/element/ElementPhoto.svelte +57 -0
  128. package/dist/element/ElementPhoto.svelte.d.ts +9 -0
  129. package/dist/element/ElementStats.svelte +80 -0
  130. package/dist/element/ElementStats.svelte.d.ts +8 -0
  131. package/dist/element/ElementTile.svelte +484 -0
  132. package/dist/element/ElementTile.svelte.d.ts +29 -0
  133. package/dist/element/Nucleus.svelte.d.ts +17 -0
  134. package/dist/element/data.d.ts +2 -0
  135. package/dist/element/data.js +2 -0
  136. package/dist/element/index.d.ts +8 -0
  137. package/dist/element/index.js +7 -0
  138. package/dist/element/types.d.ts +57 -0
  139. package/dist/element/types.js +1 -0
  140. package/dist/feedback/ClickFeedback.svelte +58 -0
  141. package/dist/feedback/ClickFeedback.svelte.d.ts +12 -0
  142. package/dist/feedback/DragOverlay.svelte +42 -0
  143. package/dist/feedback/DragOverlay.svelte.d.ts +7 -0
  144. package/dist/feedback/Spinner.svelte.d.ts +7 -0
  145. package/dist/feedback/StatusMessage.svelte.d.ts +9 -0
  146. package/dist/feedback/index.d.ts +4 -0
  147. package/dist/feedback/index.js +4 -0
  148. package/dist/fermi-surface/FermiSlice.svelte +197 -0
  149. package/dist/fermi-surface/FermiSlice.svelte.d.ts +24 -0
  150. package/dist/fermi-surface/FermiSurface.svelte +606 -0
  151. package/dist/fermi-surface/FermiSurface.svelte.d.ts +83 -0
  152. package/dist/fermi-surface/FermiSurfaceControls.svelte +448 -0
  153. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +35 -0
  154. package/dist/fermi-surface/FermiSurfaceScene.svelte +797 -0
  155. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +50 -0
  156. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +85 -0
  157. package/dist/fermi-surface/FermiSurfaceTooltip.svelte.d.ts +8 -0
  158. package/dist/fermi-surface/compute.d.ts +5 -0
  159. package/dist/fermi-surface/compute.js +538 -0
  160. package/dist/fermi-surface/constants.d.ts +9 -0
  161. package/dist/fermi-surface/constants.js +27 -0
  162. package/dist/fermi-surface/export.d.ts +5 -0
  163. package/dist/fermi-surface/export.js +51 -0
  164. package/dist/fermi-surface/index.d.ts +12 -0
  165. package/dist/fermi-surface/index.js +13 -0
  166. package/dist/fermi-surface/marching-cubes.d.ts +2 -0
  167. package/dist/fermi-surface/marching-cubes.js +2 -0
  168. package/dist/fermi-surface/parse.d.ts +2 -0
  169. package/dist/fermi-surface/parse.js +494 -0
  170. package/dist/fermi-surface/symmetry.d.ts +3 -0
  171. package/dist/fermi-surface/symmetry.js +46 -0
  172. package/dist/fermi-surface/types.d.ts +111 -0
  173. package/dist/fermi-surface/types.js +4 -0
  174. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1547 -0
  175. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
  176. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
  177. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +30 -0
  178. package/dist/heatmap-matrix/index.d.ts +53 -0
  179. package/dist/heatmap-matrix/index.js +100 -0
  180. package/dist/heatmap-matrix/shared.d.ts +2 -0
  181. package/dist/heatmap-matrix/shared.js +4 -0
  182. package/dist/icons.d.ts +569 -0
  183. package/dist/icons.js +648 -0
  184. package/dist/index.d.ts +39 -0
  185. package/dist/index.js +39 -0
  186. package/dist/io/decompress.d.ts +11 -0
  187. package/dist/io/decompress.js +76 -0
  188. package/dist/io/export.d.ts +16 -0
  189. package/dist/io/export.js +338 -0
  190. package/dist/io/fetch.d.ts +5 -0
  191. package/dist/io/fetch.js +43 -0
  192. package/dist/io/file-drop.d.ts +7 -0
  193. package/dist/io/file-drop.js +42 -0
  194. package/dist/io/index.d.ts +7 -0
  195. package/dist/io/index.js +6 -0
  196. package/dist/io/is-binary.d.ts +1 -0
  197. package/dist/io/is-binary.js +20 -0
  198. package/dist/io/types.d.ts +8 -0
  199. package/dist/io/types.js +1 -0
  200. package/dist/io/url-drop.d.ts +2 -0
  201. package/dist/io/url-drop.js +154 -0
  202. package/dist/isosurface/Isosurface.svelte +285 -0
  203. package/dist/isosurface/Isosurface.svelte.d.ts +8 -0
  204. package/dist/isosurface/IsosurfaceControls.svelte +277 -0
  205. package/dist/isosurface/IsosurfaceControls.svelte.d.ts +9 -0
  206. package/dist/isosurface/index.d.ts +5 -0
  207. package/dist/isosurface/index.js +6 -0
  208. package/dist/isosurface/parse.d.ts +6 -0
  209. package/dist/isosurface/parse.js +552 -0
  210. package/dist/isosurface/slice.d.ts +11 -0
  211. package/dist/isosurface/slice.js +141 -0
  212. package/dist/isosurface/types.d.ts +56 -0
  213. package/dist/isosurface/types.js +227 -0
  214. package/dist/keyboard.d.ts +3 -0
  215. package/dist/keyboard.js +23 -0
  216. package/dist/labels.d.ts +53 -0
  217. package/dist/labels.js +278 -0
  218. package/dist/layout/FullscreenToggle.svelte +50 -0
  219. package/dist/layout/FullscreenToggle.svelte.d.ts +7 -0
  220. package/dist/layout/InfoCard.svelte +120 -0
  221. package/dist/layout/InfoCard.svelte.d.ts +21 -0
  222. package/dist/layout/InfoTag.svelte +185 -0
  223. package/dist/layout/InfoTag.svelte.d.ts +19 -0
  224. package/dist/layout/PropertyFilter.svelte +247 -0
  225. package/dist/layout/PropertyFilter.svelte.d.ts +24 -0
  226. package/dist/layout/SettingsSection.svelte +148 -0
  227. package/dist/layout/SettingsSection.svelte.d.ts +17 -0
  228. package/dist/layout/SubpageGrid.svelte +82 -0
  229. package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
  230. package/dist/layout/fullscreen.d.ts +9 -0
  231. package/dist/layout/fullscreen.js +53 -0
  232. package/dist/layout/index.d.ts +10 -0
  233. package/dist/layout/index.js +8 -0
  234. package/dist/layout/json-tree/JsonNode.svelte +548 -0
  235. package/dist/layout/json-tree/JsonNode.svelte.d.ts +11 -0
  236. package/dist/layout/json-tree/JsonTree.svelte +1230 -0
  237. package/dist/layout/json-tree/JsonTree.svelte.d.ts +6 -0
  238. package/dist/layout/json-tree/JsonValue.svelte.d.ts +9 -0
  239. package/dist/layout/json-tree/index.d.ts +3 -0
  240. package/dist/layout/json-tree/index.js +3 -0
  241. package/dist/layout/json-tree/types.d.ts +74 -0
  242. package/dist/layout/json-tree/types.js +2 -0
  243. package/dist/layout/json-tree/utils.d.ts +29 -0
  244. package/dist/layout/json-tree/utils.js +642 -0
  245. package/dist/marching-cubes.d.ts +14 -0
  246. package/dist/marching-cubes.js +535 -0
  247. package/dist/math.d.ts +105 -0
  248. package/dist/math.js +920 -0
  249. package/dist/overlays/ContextMenu.svelte +162 -0
  250. package/dist/overlays/ContextMenu.svelte.d.ts +25 -0
  251. package/dist/overlays/CopyButton.svelte +45 -0
  252. package/dist/overlays/CopyButton.svelte.d.ts +8 -0
  253. package/dist/overlays/DragControlTab.svelte +98 -0
  254. package/dist/overlays/DragControlTab.svelte.d.ts +8 -0
  255. package/dist/overlays/DraggablePane.svelte +487 -0
  256. package/dist/overlays/DraggablePane.svelte.d.ts +36 -0
  257. package/dist/overlays/InfoPaneCards.svelte +149 -0
  258. package/dist/overlays/InfoPaneCards.svelte.d.ts +22 -0
  259. package/dist/overlays/index.d.ts +3 -0
  260. package/dist/overlays/index.js +3 -0
  261. package/dist/periodic-table/PeriodicTable.svelte +480 -0
  262. package/dist/periodic-table/PeriodicTable.svelte.d.ts +55 -0
  263. package/dist/periodic-table/PeriodicTableControls.svelte +557 -0
  264. package/dist/periodic-table/PeriodicTableControls.svelte.d.ts +24 -0
  265. package/dist/periodic-table/PropertySelect.svelte +38 -0
  266. package/dist/periodic-table/PropertySelect.svelte.d.ts +13 -0
  267. package/dist/periodic-table/TableInset.svelte.d.ts +9 -0
  268. package/dist/periodic-table/index.d.ts +10 -0
  269. package/dist/periodic-table/index.js +4 -0
  270. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +1092 -0
  271. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +44 -0
  272. package/dist/phase-diagram/PhaseDiagramControls.svelte +444 -0
  273. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +30 -0
  274. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +127 -0
  275. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
  276. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +184 -0
  277. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +19 -0
  278. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +391 -0
  279. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +16 -0
  280. package/dist/phase-diagram/TdbInfoPanel.svelte +203 -0
  281. package/dist/phase-diagram/TdbInfoPanel.svelte.d.ts +12 -0
  282. package/dist/phase-diagram/build-diagram.d.ts +11 -0
  283. package/dist/phase-diagram/build-diagram.js +160 -0
  284. package/dist/phase-diagram/colors.d.ts +35 -0
  285. package/dist/phase-diagram/colors.js +51 -0
  286. package/dist/phase-diagram/diagram-input.d.ts +29 -0
  287. package/dist/phase-diagram/diagram-input.js +3 -0
  288. package/dist/phase-diagram/index.d.ts +13 -0
  289. package/dist/phase-diagram/index.js +11 -0
  290. package/dist/phase-diagram/parse.d.ts +55 -0
  291. package/dist/phase-diagram/parse.js +273 -0
  292. package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
  293. package/dist/phase-diagram/svg-to-diagram.js +867 -0
  294. package/dist/phase-diagram/types.d.ts +93 -0
  295. package/dist/phase-diagram/types.js +1 -0
  296. package/dist/phase-diagram/utils.d.ts +118 -0
  297. package/dist/phase-diagram/utils.js +600 -0
  298. package/dist/plot/bar/BarPlot.svelte +1755 -0
  299. package/dist/plot/bar/BarPlot.svelte.d.ts +84 -0
  300. package/dist/plot/bar/BarPlotControls.svelte +67 -0
  301. package/dist/plot/bar/BarPlotControls.svelte.d.ts +18 -0
  302. package/dist/plot/bar/SpacegroupBarPlot.svelte +293 -0
  303. package/dist/plot/bar/SpacegroupBarPlot.svelte.d.ts +9 -0
  304. package/dist/plot/bar/data.d.ts +40 -0
  305. package/dist/plot/bar/data.js +154 -0
  306. package/dist/plot/bar/geometry.d.ts +39 -0
  307. package/dist/plot/bar/geometry.js +60 -0
  308. package/dist/plot/bar/index.d.ts +3 -0
  309. package/dist/plot/bar/index.js +3 -0
  310. package/dist/plot/box/BoxPlot.svelte +1462 -0
  311. package/dist/plot/box/BoxPlot.svelte.d.ts +94 -0
  312. package/dist/plot/box/BoxPlotControls.svelte +109 -0
  313. package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
  314. package/dist/plot/box/Violin.svelte +14 -0
  315. package/dist/plot/box/Violin.svelte.d.ts +70 -0
  316. package/dist/plot/box/box-plot.d.ts +55 -0
  317. package/dist/plot/box/box-plot.js +126 -0
  318. package/dist/plot/box/index.d.ts +5 -0
  319. package/dist/plot/box/index.js +5 -0
  320. package/dist/plot/box/kde.d.ts +16 -0
  321. package/dist/plot/box/kde.js +160 -0
  322. package/dist/plot/box/quantile.d.ts +3 -0
  323. package/dist/plot/box/quantile.js +53 -0
  324. package/dist/plot/core/auto-place.d.ts +43 -0
  325. package/dist/plot/core/auto-place.js +122 -0
  326. package/dist/plot/core/axis-utils.d.ts +46 -0
  327. package/dist/plot/core/axis-utils.js +110 -0
  328. package/dist/plot/core/components/AxisLabel.svelte +51 -0
  329. package/dist/plot/core/components/AxisLabel.svelte.d.ts +16 -0
  330. package/dist/plot/core/components/ColorBar.svelte +724 -0
  331. package/dist/plot/core/components/ColorBar.svelte.d.ts +31 -0
  332. package/dist/plot/core/components/ColorScaleSelect.svelte +55 -0
  333. package/dist/plot/core/components/ColorScaleSelect.svelte.d.ts +15 -0
  334. package/dist/plot/core/components/ControlPane.svelte +46 -0
  335. package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
  336. package/dist/plot/core/components/FillArea.svelte +234 -0
  337. package/dist/plot/core/components/FillArea.svelte.d.ts +21 -0
  338. package/dist/plot/core/components/InteractiveAxisLabel.svelte +96 -0
  339. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +14 -0
  340. package/dist/plot/core/components/Line.svelte +101 -0
  341. package/dist/plot/core/components/Line.svelte.d.ts +15 -0
  342. package/dist/plot/core/components/PlotAxis.svelte +171 -0
  343. package/dist/plot/core/components/PlotAxis.svelte.d.ts +25 -0
  344. package/dist/plot/core/components/PlotControls.svelte +525 -0
  345. package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
  346. package/dist/plot/core/components/PlotLegend.svelte +580 -0
  347. package/dist/plot/core/components/PlotLegend.svelte.d.ts +30 -0
  348. package/dist/plot/core/components/PlotTooltip.svelte +83 -0
  349. package/dist/plot/core/components/PlotTooltip.svelte.d.ts +25 -0
  350. package/dist/plot/core/components/PortalSelect.svelte +257 -0
  351. package/dist/plot/core/components/PortalSelect.svelte.d.ts +16 -0
  352. package/dist/plot/core/components/ReferenceLine.svelte +204 -0
  353. package/dist/plot/core/components/ReferenceLine.svelte.d.ts +20 -0
  354. package/dist/plot/core/components/ReferenceLine3D.svelte +156 -0
  355. package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +14 -0
  356. package/dist/plot/core/components/ReferencePlane.svelte +175 -0
  357. package/dist/plot/core/components/ReferencePlane.svelte.d.ts +14 -0
  358. package/dist/plot/core/components/ZeroLines.svelte +97 -0
  359. package/dist/plot/core/components/ZeroLines.svelte.d.ts +33 -0
  360. package/dist/plot/core/components/ZoomRect.svelte +23 -0
  361. package/dist/plot/core/components/ZoomRect.svelte.d.ts +8 -0
  362. package/dist/plot/core/components/index.d.ts +17 -0
  363. package/dist/plot/core/components/index.js +17 -0
  364. package/dist/plot/core/data-cleaning.d.ts +107 -0
  365. package/dist/plot/core/data-cleaning.js +853 -0
  366. package/dist/plot/core/data-transform.d.ts +16 -0
  367. package/dist/plot/core/data-transform.js +45 -0
  368. package/dist/plot/core/fill-utils.d.ts +33 -0
  369. package/dist/plot/core/fill-utils.js +388 -0
  370. package/dist/plot/core/hover-lock.svelte.d.ts +14 -0
  371. package/dist/plot/core/hover-lock.svelte.js +45 -0
  372. package/dist/plot/core/index.d.ts +10 -0
  373. package/dist/plot/core/index.js +11 -0
  374. package/dist/plot/core/interactions.d.ts +35 -0
  375. package/dist/plot/core/interactions.js +195 -0
  376. package/dist/plot/core/layout.d.ts +79 -0
  377. package/dist/plot/core/layout.js +281 -0
  378. package/dist/plot/core/reference-line.d.ts +60 -0
  379. package/dist/plot/core/reference-line.js +301 -0
  380. package/dist/plot/core/scales.d.ts +48 -0
  381. package/dist/plot/core/scales.js +480 -0
  382. package/dist/plot/core/svg.d.ts +2 -0
  383. package/dist/plot/core/svg.js +41 -0
  384. package/dist/plot/core/types.d.ts +771 -0
  385. package/dist/plot/core/types.js +99 -0
  386. package/dist/plot/core/utils/label-placement.d.ts +68 -0
  387. package/dist/plot/core/utils/label-placement.js +326 -0
  388. package/dist/plot/core/utils/series-visibility.d.ts +26 -0
  389. package/dist/plot/core/utils/series-visibility.js +112 -0
  390. package/dist/plot/core/utils.d.ts +11 -0
  391. package/dist/plot/core/utils.js +27 -0
  392. package/dist/plot/histogram/Histogram.svelte +1418 -0
  393. package/dist/plot/histogram/Histogram.svelte.d.ts +50 -0
  394. package/dist/plot/histogram/HistogramControls.svelte +212 -0
  395. package/dist/plot/histogram/HistogramControls.svelte.d.ts +22 -0
  396. package/dist/plot/histogram/index.d.ts +2 -0
  397. package/dist/plot/histogram/index.js +2 -0
  398. package/dist/plot/index.d.ts +8 -0
  399. package/dist/plot/index.js +10 -0
  400. package/dist/plot/sankey/Sankey.svelte +700 -0
  401. package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
  402. package/dist/plot/sankey/SankeyControls.svelte +98 -0
  403. package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
  404. package/dist/plot/sankey/index.d.ts +4 -0
  405. package/dist/plot/sankey/index.js +3 -0
  406. package/dist/plot/sankey/sankey-types.d.ts +42 -0
  407. package/dist/plot/sankey/sankey-types.js +4 -0
  408. package/dist/plot/sankey/sankey.d.ts +52 -0
  409. package/dist/plot/sankey/sankey.js +187 -0
  410. package/dist/plot/scatter/BinnedScatterPlot.svelte +1116 -0
  411. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +66 -0
  412. package/dist/plot/scatter/ElementScatter.svelte +63 -0
  413. package/dist/plot/scatter/ElementScatter.svelte.d.ts +14 -0
  414. package/dist/plot/scatter/ScatterPlot.svelte +2357 -0
  415. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +96 -0
  416. package/dist/plot/scatter/ScatterPlotControls.svelte +307 -0
  417. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +17 -0
  418. package/dist/plot/scatter/ScatterPoint.svelte +182 -0
  419. package/dist/plot/scatter/ScatterPoint.svelte.d.ts +22 -0
  420. package/dist/plot/scatter/adaptive-density.d.ts +79 -0
  421. package/dist/plot/scatter/adaptive-density.js +217 -0
  422. package/dist/plot/scatter/binned-scatter-types.d.ts +59 -0
  423. package/dist/plot/scatter/binned-scatter-types.js +1 -0
  424. package/dist/plot/scatter/index.d.ts +7 -0
  425. package/dist/plot/scatter/index.js +5 -0
  426. package/dist/plot/scatter/scatter-data.d.ts +19 -0
  427. package/dist/plot/scatter/scatter-data.js +212 -0
  428. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +531 -0
  429. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +95 -0
  430. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +438 -0
  431. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +20 -0
  432. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +912 -0
  433. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +74 -0
  434. package/dist/plot/scatter-3d/Surface3D.svelte +197 -0
  435. package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +13 -0
  436. package/dist/plot/scatter-3d/index.d.ts +4 -0
  437. package/dist/plot/scatter-3d/index.js +4 -0
  438. package/dist/plot/sunburst/Sunburst.svelte +1045 -0
  439. package/dist/plot/sunburst/Sunburst.svelte.d.ts +96 -0
  440. package/dist/plot/sunburst/SunburstControls.svelte +200 -0
  441. package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
  442. package/dist/plot/sunburst/index.d.ts +4 -0
  443. package/dist/plot/sunburst/index.js +4 -0
  444. package/dist/plot/sunburst/render.d.ts +34 -0
  445. package/dist/plot/sunburst/render.js +122 -0
  446. package/dist/plot/sunburst/sunburst.d.ts +62 -0
  447. package/dist/plot/sunburst/sunburst.js +266 -0
  448. package/dist/rdf/RdfPlot.svelte +248 -0
  449. package/dist/rdf/RdfPlot.svelte.d.ts +27 -0
  450. package/dist/rdf/calc-rdf.d.ts +4 -0
  451. package/dist/rdf/calc-rdf.js +98 -0
  452. package/dist/rdf/index.d.ts +23 -0
  453. package/dist/rdf/index.js +2 -0
  454. package/dist/sanitize.d.ts +6 -0
  455. package/dist/sanitize.js +116 -0
  456. package/dist/settings.d.ts +319 -0
  457. package/dist/settings.js +1394 -0
  458. package/dist/spectral/Bands.svelte +1050 -0
  459. package/dist/spectral/Bands.svelte.d.ts +39 -0
  460. package/dist/spectral/BandsAndDos.svelte +134 -0
  461. package/dist/spectral/BandsAndDos.svelte.d.ts +18 -0
  462. package/dist/spectral/BrillouinBandsDos.svelte +264 -0
  463. package/dist/spectral/BrillouinBandsDos.svelte.d.ts +20 -0
  464. package/dist/spectral/Dos.svelte +688 -0
  465. package/dist/spectral/Dos.svelte.d.ts +29 -0
  466. package/dist/spectral/helpers.d.ts +121 -0
  467. package/dist/spectral/helpers.js +1098 -0
  468. package/dist/spectral/index.d.ts +6 -0
  469. package/dist/spectral/index.js +6 -0
  470. package/dist/spectral/types.d.ts +84 -0
  471. package/dist/spectral/types.js +2 -0
  472. package/dist/state.svelte.d.ts +25 -0
  473. package/dist/state.svelte.js +45 -0
  474. package/dist/structure/Arrow.svelte +72 -0
  475. package/dist/structure/Arrow.svelte.d.ts +15 -0
  476. package/dist/structure/AtomLegend.svelte +814 -0
  477. package/dist/structure/AtomLegend.svelte.d.ts +35 -0
  478. package/dist/structure/Bond.svelte +140 -0
  479. package/dist/structure/Bond.svelte.d.ts +9 -0
  480. package/dist/structure/CanvasTooltip.svelte +33 -0
  481. package/dist/structure/CanvasTooltip.svelte.d.ts +12 -0
  482. package/dist/structure/CellSelect.svelte +348 -0
  483. package/dist/structure/CellSelect.svelte.d.ts +13 -0
  484. package/dist/structure/Cylinder.svelte +49 -0
  485. package/dist/structure/Cylinder.svelte.d.ts +13 -0
  486. package/dist/structure/Lattice.svelte +196 -0
  487. package/dist/structure/Lattice.svelte.d.ts +17 -0
  488. package/dist/structure/Structure.svelte +2254 -0
  489. package/dist/structure/Structure.svelte.d.ts +89 -0
  490. package/dist/structure/StructureControls.svelte +1273 -0
  491. package/dist/structure/StructureControls.svelte.d.ts +31 -0
  492. package/dist/structure/StructureExportPane.svelte +252 -0
  493. package/dist/structure/StructureExportPane.svelte.d.ts +17 -0
  494. package/dist/structure/StructureInfoPane.svelte +736 -0
  495. package/dist/structure/StructureInfoPane.svelte.d.ts +19 -0
  496. package/dist/structure/StructureScene.svelte +2256 -0
  497. package/dist/structure/StructureScene.svelte.d.ts +111 -0
  498. package/dist/structure/atom-properties.d.ts +37 -0
  499. package/dist/structure/atom-properties.js +200 -0
  500. package/dist/structure/bond-order-perception.d.ts +13 -0
  501. package/dist/structure/bond-order-perception.js +384 -0
  502. package/dist/structure/bonding.d.ts +69 -0
  503. package/dist/structure/bonding.js +724 -0
  504. package/dist/structure/export.d.ts +20 -0
  505. package/dist/structure/export.js +731 -0
  506. package/dist/structure/index.d.ts +124 -0
  507. package/dist/structure/index.js +167 -0
  508. package/dist/structure/label-placement.d.ts +14 -0
  509. package/dist/structure/label-placement.js +72 -0
  510. package/dist/structure/measure.d.ts +7 -0
  511. package/dist/structure/measure.js +30 -0
  512. package/dist/structure/parse.d.ts +66 -0
  513. package/dist/structure/parse.js +1410 -0
  514. package/dist/structure/partial-occupancy.d.ts +25 -0
  515. package/dist/structure/partial-occupancy.js +99 -0
  516. package/dist/structure/pbc.d.ts +9 -0
  517. package/dist/structure/pbc.js +127 -0
  518. package/dist/structure/supercell.d.ts +8 -0
  519. package/dist/structure/supercell.js +170 -0
  520. package/dist/structure/validation.d.ts +2 -0
  521. package/dist/structure/validation.js +10 -0
  522. package/dist/symmetry/SymmetryStats.svelte +226 -0
  523. package/dist/symmetry/SymmetryStats.svelte.d.ts +21 -0
  524. package/dist/symmetry/WyckoffTable.svelte +120 -0
  525. package/dist/symmetry/WyckoffTable.svelte.d.ts +11 -0
  526. package/dist/symmetry/cell-transform.d.ts +12 -0
  527. package/dist/symmetry/cell-transform.js +91 -0
  528. package/dist/symmetry/index.d.ts +43 -0
  529. package/dist/symmetry/index.js +226 -0
  530. package/dist/symmetry/spacegroups.d.ts +16 -0
  531. package/dist/symmetry/spacegroups.js +429 -0
  532. package/dist/table/HeatmapTable.svelte +1885 -0
  533. package/dist/table/HeatmapTable.svelte.d.ts +49 -0
  534. package/dist/table/ToggleMenu.svelte +385 -0
  535. package/dist/table/ToggleMenu.svelte.d.ts +11 -0
  536. package/dist/table/index.d.ts +72 -0
  537. package/dist/table/index.js +38 -0
  538. package/dist/theme/ThemeControl.svelte +53 -0
  539. package/dist/theme/ThemeControl.svelte.d.ts +9 -0
  540. package/dist/theme/index.d.ts +29 -0
  541. package/dist/theme/index.js +79 -0
  542. package/dist/time.d.ts +4 -0
  543. package/dist/time.js +70 -0
  544. package/dist/tooltip/KCoords.svelte +45 -0
  545. package/dist/tooltip/KCoords.svelte.d.ts +8 -0
  546. package/dist/tooltip/TooltipContent.svelte +58 -0
  547. package/dist/tooltip/TooltipContent.svelte.d.ts +31 -0
  548. package/dist/tooltip/index.d.ts +3 -0
  549. package/dist/tooltip/index.js +2 -0
  550. package/dist/tooltip/types.d.ts +8 -0
  551. package/dist/tooltip/types.js +1 -0
  552. package/dist/trajectory/Trajectory.svelte +1571 -0
  553. package/dist/trajectory/Trajectory.svelte.d.ts +78 -0
  554. package/dist/trajectory/TrajectoryError.svelte +128 -0
  555. package/dist/trajectory/TrajectoryError.svelte.d.ts +13 -0
  556. package/dist/trajectory/TrajectoryExportPane.svelte +358 -0
  557. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +17 -0
  558. package/dist/trajectory/TrajectoryInfoPane.svelte +314 -0
  559. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +17 -0
  560. package/dist/trajectory/constants.d.ts +6 -0
  561. package/dist/trajectory/constants.js +7 -0
  562. package/dist/trajectory/extract.d.ts +5 -0
  563. package/dist/trajectory/extract.js +162 -0
  564. package/dist/trajectory/format-detect.d.ts +10 -0
  565. package/dist/trajectory/format-detect.js +90 -0
  566. package/dist/trajectory/frame-reader.d.ts +17 -0
  567. package/dist/trajectory/frame-reader.js +299 -0
  568. package/dist/trajectory/helpers.d.ts +15 -0
  569. package/dist/trajectory/helpers.js +164 -0
  570. package/dist/trajectory/index.d.ts +63 -0
  571. package/dist/trajectory/index.js +126 -0
  572. package/dist/trajectory/parse/ase.d.ts +2 -0
  573. package/dist/trajectory/parse/ase.js +73 -0
  574. package/dist/trajectory/parse/hdf5.d.ts +2 -0
  575. package/dist/trajectory/parse/hdf5.js +127 -0
  576. package/dist/trajectory/parse/index.d.ts +12 -0
  577. package/dist/trajectory/parse/index.js +306 -0
  578. package/dist/trajectory/parse/lammps.d.ts +5 -0
  579. package/dist/trajectory/parse/lammps.js +179 -0
  580. package/dist/trajectory/parse/vasp.d.ts +2 -0
  581. package/dist/trajectory/parse/vasp.js +87 -0
  582. package/dist/trajectory/parse/xyz.d.ts +26 -0
  583. package/dist/trajectory/parse/xyz.js +123 -0
  584. package/dist/trajectory/plotting.d.ts +28 -0
  585. package/dist/trajectory/plotting.js +423 -0
  586. package/dist/trajectory/types.d.ts +11 -0
  587. package/dist/trajectory/types.js +1 -0
  588. package/dist/utils.d.ts +7 -0
  589. package/dist/utils.js +47 -0
  590. package/dist/xrd/XrdPlot.svelte +616 -0
  591. package/dist/xrd/XrdPlot.svelte.d.ts +28 -0
  592. package/dist/xrd/broadening.d.ts +20 -0
  593. package/dist/xrd/broadening.js +97 -0
  594. package/dist/xrd/calc-xrd.d.ts +37 -0
  595. package/dist/xrd/calc-xrd.js +339 -0
  596. package/dist/xrd/index.d.ts +37 -0
  597. package/dist/xrd/index.js +4 -0
  598. package/dist/xrd/parse.d.ts +13 -0
  599. package/dist/xrd/parse.js +749 -0
  600. package/license +1 -1
  601. package/package.json +237 -1458
  602. package/readme.md +98 -171
  603. package/.vscode/launch.json +0 -13
  604. package/.vscodeignore +0 -7
  605. package/dist/assets/STLExporter-BpTH3YHE.js +0 -8
  606. package/dist/assets/browser-DdDecX_W.js +0 -1
  607. package/dist/assets/export-qgn-H9y6.js +0 -2
  608. package/dist/assets/main-DiKYzti2.css +0 -1
  609. package/dist/assets/moyo_wasm_bg-0ocwg7xY.wasm +0 -0
  610. package/dist/extension.js +0 -31293
  611. package/dist/src/lib/FilePicker.svelte +0 -360
  612. package/dist/src/lib/Icon.svelte +0 -41
  613. package/dist/src/lib/MillerIndexInput.svelte +0 -66
  614. package/dist/src/lib/api/mp.ts +0 -26
  615. package/dist/src/lib/api/optimade.ts +0 -204
  616. package/dist/src/lib/app.css +0 -247
  617. package/dist/src/lib/brillouin/BrillouinZone.svelte +0 -549
  618. package/dist/src/lib/brillouin/BrillouinZoneControls.svelte +0 -144
  619. package/dist/src/lib/brillouin/BrillouinZoneExportPane.svelte +0 -146
  620. package/dist/src/lib/brillouin/BrillouinZoneInfoPane.svelte +0 -146
  621. package/dist/src/lib/brillouin/BrillouinZoneScene.svelte +0 -476
  622. package/dist/src/lib/brillouin/BrillouinZoneTooltip.svelte +0 -92
  623. package/dist/src/lib/brillouin/compute.ts +0 -529
  624. package/dist/src/lib/brillouin/index.ts +0 -8
  625. package/dist/src/lib/brillouin/types.ts +0 -51
  626. package/dist/src/lib/chempot-diagram/ChemPotDiagram.svelte +0 -327
  627. package/dist/src/lib/chempot-diagram/ChemPotDiagram2D.svelte +0 -846
  628. package/dist/src/lib/chempot-diagram/ChemPotDiagram3D.svelte +0 -3193
  629. package/dist/src/lib/chempot-diagram/async-compute.svelte.ts +0 -94
  630. package/dist/src/lib/chempot-diagram/chempot-worker.ts +0 -11
  631. package/dist/src/lib/chempot-diagram/color.ts +0 -42
  632. package/dist/src/lib/chempot-diagram/compute.ts +0 -1014
  633. package/dist/src/lib/chempot-diagram/index.ts +0 -6
  634. package/dist/src/lib/chempot-diagram/pointer.ts +0 -56
  635. package/dist/src/lib/chempot-diagram/temperature.ts +0 -77
  636. package/dist/src/lib/chempot-diagram/types.ts +0 -130
  637. package/dist/src/lib/colors/index.ts +0 -249
  638. package/dist/src/lib/composition/BarChart.svelte +0 -297
  639. package/dist/src/lib/composition/BubbleChart.svelte +0 -218
  640. package/dist/src/lib/composition/Composition.svelte +0 -165
  641. package/dist/src/lib/composition/Formula.svelte +0 -268
  642. package/dist/src/lib/composition/FormulaFilter.svelte +0 -1257
  643. package/dist/src/lib/composition/PieChart.svelte +0 -323
  644. package/dist/src/lib/composition/format.ts +0 -155
  645. package/dist/src/lib/composition/index.ts +0 -37
  646. package/dist/src/lib/composition/parse.ts +0 -605
  647. package/dist/src/lib/constants.ts +0 -134
  648. package/dist/src/lib/controls.ts +0 -42
  649. package/dist/src/lib/convex-hull/ConvexHull.svelte +0 -157
  650. package/dist/src/lib/convex-hull/ConvexHull2D.svelte +0 -825
  651. package/dist/src/lib/convex-hull/ConvexHull3D.svelte +0 -1801
  652. package/dist/src/lib/convex-hull/ConvexHull4D.svelte +0 -1398
  653. package/dist/src/lib/convex-hull/ConvexHullControls.svelte +0 -535
  654. package/dist/src/lib/convex-hull/ConvexHullInfoPane.svelte +0 -125
  655. package/dist/src/lib/convex-hull/ConvexHullStats.svelte +0 -929
  656. package/dist/src/lib/convex-hull/ConvexHullTooltip.svelte +0 -131
  657. package/dist/src/lib/convex-hull/GasPressureControls.svelte +0 -247
  658. package/dist/src/lib/convex-hull/StructurePopup.svelte +0 -151
  659. package/dist/src/lib/convex-hull/TemperatureSlider.svelte +0 -140
  660. package/dist/src/lib/convex-hull/barycentric-coords.ts +0 -246
  661. package/dist/src/lib/convex-hull/demo-temperature.ts +0 -63
  662. package/dist/src/lib/convex-hull/gas-thermodynamics.ts +0 -405
  663. package/dist/src/lib/convex-hull/helpers.ts +0 -932
  664. package/dist/src/lib/convex-hull/index.ts +0 -202
  665. package/dist/src/lib/convex-hull/thermodynamics.ts +0 -2192
  666. package/dist/src/lib/convex-hull/types.ts +0 -267
  667. package/dist/src/lib/coordination/CoordinationBarPlot.svelte +0 -311
  668. package/dist/src/lib/coordination/calc-coordination.ts +0 -93
  669. package/dist/src/lib/coordination/index.ts +0 -9
  670. package/dist/src/lib/effects.svelte.ts +0 -48
  671. package/dist/src/lib/element/ElementHeading.svelte +0 -26
  672. package/dist/src/lib/element/ElementPhoto.svelte +0 -57
  673. package/dist/src/lib/element/ElementStats.svelte +0 -80
  674. package/dist/src/lib/element/ElementTile.svelte +0 -484
  675. package/dist/src/lib/element/data.ts +0 -14
  676. package/dist/src/lib/element/index.ts +0 -8
  677. package/dist/src/lib/element/types.ts +0 -62
  678. package/dist/src/lib/feedback/ClickFeedback.svelte +0 -58
  679. package/dist/src/lib/feedback/DragOverlay.svelte +0 -42
  680. package/dist/src/lib/feedback/index.ts +0 -4
  681. package/dist/src/lib/fermi-surface/FermiSlice.svelte +0 -189
  682. package/dist/src/lib/fermi-surface/FermiSurface.svelte +0 -600
  683. package/dist/src/lib/fermi-surface/FermiSurfaceControls.svelte +0 -448
  684. package/dist/src/lib/fermi-surface/FermiSurfaceScene.svelte +0 -794
  685. package/dist/src/lib/fermi-surface/FermiSurfaceTooltip.svelte +0 -111
  686. package/dist/src/lib/fermi-surface/compute.ts +0 -728
  687. package/dist/src/lib/fermi-surface/constants.ts +0 -32
  688. package/dist/src/lib/fermi-surface/export.ts +0 -64
  689. package/dist/src/lib/fermi-surface/index.ts +0 -14
  690. package/dist/src/lib/fermi-surface/marching-cubes.ts +0 -3
  691. package/dist/src/lib/fermi-surface/parse.ts +0 -574
  692. package/dist/src/lib/fermi-surface/symmetry.ts +0 -56
  693. package/dist/src/lib/fermi-surface/types.ts +0 -159
  694. package/dist/src/lib/heatmap-matrix/HeatmapMatrix.svelte +0 -1545
  695. package/dist/src/lib/heatmap-matrix/HeatmapMatrixControls.svelte +0 -225
  696. package/dist/src/lib/heatmap-matrix/index.ts +0 -167
  697. package/dist/src/lib/heatmap-matrix/shared.ts +0 -7
  698. package/dist/src/lib/icons.ts +0 -650
  699. package/dist/src/lib/index.ts +0 -61
  700. package/dist/src/lib/io/decompress.ts +0 -92
  701. package/dist/src/lib/io/export.ts +0 -385
  702. package/dist/src/lib/io/fetch.ts +0 -46
  703. package/dist/src/lib/io/file-drop.ts +0 -51
  704. package/dist/src/lib/io/index.ts +0 -7
  705. package/dist/src/lib/io/is-binary.ts +0 -24
  706. package/dist/src/lib/io/types.ts +0 -8
  707. package/dist/src/lib/io/url-drop.ts +0 -141
  708. package/dist/src/lib/isosurface/Isosurface.svelte +0 -285
  709. package/dist/src/lib/isosurface/IsosurfaceControls.svelte +0 -277
  710. package/dist/src/lib/isosurface/index.ts +0 -7
  711. package/dist/src/lib/isosurface/parse.ts +0 -656
  712. package/dist/src/lib/isosurface/slice.ts +0 -175
  713. package/dist/src/lib/isosurface/types.ts +0 -309
  714. package/dist/src/lib/labels.ts +0 -320
  715. package/dist/src/lib/layout/FullscreenToggle.svelte +0 -50
  716. package/dist/src/lib/layout/InfoCard.svelte +0 -120
  717. package/dist/src/lib/layout/InfoTag.svelte +0 -185
  718. package/dist/src/lib/layout/PropertyFilter.svelte +0 -246
  719. package/dist/src/lib/layout/SettingsSection.svelte +0 -148
  720. package/dist/src/lib/layout/SubpageGrid.svelte +0 -82
  721. package/dist/src/lib/layout/fullscreen.ts +0 -65
  722. package/dist/src/lib/layout/index.ts +0 -11
  723. package/dist/src/lib/layout/json-tree/JsonNode.svelte +0 -548
  724. package/dist/src/lib/layout/json-tree/JsonTree.svelte +0 -1230
  725. package/dist/src/lib/layout/json-tree/index.ts +0 -3
  726. package/dist/src/lib/layout/json-tree/types.ts +0 -126
  727. package/dist/src/lib/layout/json-tree/utils.ts +0 -682
  728. package/dist/src/lib/marching-cubes.ts +0 -614
  729. package/dist/src/lib/math.ts +0 -1081
  730. package/dist/src/lib/overlays/ContextMenu.svelte +0 -162
  731. package/dist/src/lib/overlays/CopyButton.svelte +0 -45
  732. package/dist/src/lib/overlays/DragControlTab.svelte +0 -98
  733. package/dist/src/lib/overlays/DraggablePane.svelte +0 -487
  734. package/dist/src/lib/overlays/InfoPaneCards.svelte +0 -149
  735. package/dist/src/lib/overlays/index.ts +0 -3
  736. package/dist/src/lib/periodic-table/PeriodicTable.svelte +0 -469
  737. package/dist/src/lib/periodic-table/PeriodicTableControls.svelte +0 -557
  738. package/dist/src/lib/periodic-table/PropertySelect.svelte +0 -37
  739. package/dist/src/lib/periodic-table/index.ts +0 -12
  740. package/dist/src/lib/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +0 -1086
  741. package/dist/src/lib/phase-diagram/PhaseDiagramControls.svelte +0 -444
  742. package/dist/src/lib/phase-diagram/PhaseDiagramEditorPane.svelte +0 -126
  743. package/dist/src/lib/phase-diagram/PhaseDiagramExportPane.svelte +0 -184
  744. package/dist/src/lib/phase-diagram/PhaseDiagramTooltip.svelte +0 -391
  745. package/dist/src/lib/phase-diagram/TdbInfoPanel.svelte +0 -203
  746. package/dist/src/lib/phase-diagram/build-diagram.ts +0 -186
  747. package/dist/src/lib/phase-diagram/colors.ts +0 -58
  748. package/dist/src/lib/phase-diagram/diagram-input.ts +0 -40
  749. package/dist/src/lib/phase-diagram/index.ts +0 -13
  750. package/dist/src/lib/phase-diagram/parse.ts +0 -348
  751. package/dist/src/lib/phase-diagram/svg-to-diagram.ts +0 -1023
  752. package/dist/src/lib/phase-diagram/types.ts +0 -144
  753. package/dist/src/lib/phase-diagram/utils.ts +0 -775
  754. package/dist/src/lib/plot/AxisLabel.svelte +0 -51
  755. package/dist/src/lib/plot/BarPlot.svelte +0 -2113
  756. package/dist/src/lib/plot/BarPlotControls.svelte +0 -66
  757. package/dist/src/lib/plot/BinnedScatterPlot.svelte +0 -1114
  758. package/dist/src/lib/plot/ColorBar.svelte +0 -721
  759. package/dist/src/lib/plot/ColorScaleSelect.svelte +0 -54
  760. package/dist/src/lib/plot/ElementScatter.svelte +0 -63
  761. package/dist/src/lib/plot/FillArea.svelte +0 -223
  762. package/dist/src/lib/plot/Histogram.svelte +0 -1558
  763. package/dist/src/lib/plot/HistogramControls.svelte +0 -212
  764. package/dist/src/lib/plot/InteractiveAxisLabel.svelte +0 -96
  765. package/dist/src/lib/plot/Line.svelte +0 -84
  766. package/dist/src/lib/plot/PlotAxis.svelte +0 -169
  767. package/dist/src/lib/plot/PlotControls.svelte +0 -537
  768. package/dist/src/lib/plot/PlotLegend.svelte +0 -569
  769. package/dist/src/lib/plot/PlotTooltip.svelte +0 -67
  770. package/dist/src/lib/plot/PortalSelect.svelte +0 -253
  771. package/dist/src/lib/plot/ReferenceLine.svelte +0 -204
  772. package/dist/src/lib/plot/ReferenceLine3D.svelte +0 -156
  773. package/dist/src/lib/plot/ReferencePlane.svelte +0 -175
  774. package/dist/src/lib/plot/ScatterPlot.svelte +0 -2778
  775. package/dist/src/lib/plot/ScatterPlot3D.svelte +0 -529
  776. package/dist/src/lib/plot/ScatterPlot3DControls.svelte +0 -437
  777. package/dist/src/lib/plot/ScatterPlot3DScene.svelte +0 -912
  778. package/dist/src/lib/plot/ScatterPlotControls.svelte +0 -306
  779. package/dist/src/lib/plot/ScatterPoint.svelte +0 -182
  780. package/dist/src/lib/plot/SpacegroupBarPlot.svelte +0 -293
  781. package/dist/src/lib/plot/Surface3D.svelte +0 -197
  782. package/dist/src/lib/plot/ZeroLines.svelte +0 -97
  783. package/dist/src/lib/plot/ZoomRect.svelte +0 -23
  784. package/dist/src/lib/plot/adaptive-density.ts +0 -316
  785. package/dist/src/lib/plot/auto-place.ts +0 -184
  786. package/dist/src/lib/plot/axis-utils.ts +0 -122
  787. package/dist/src/lib/plot/binned-scatter-types.ts +0 -83
  788. package/dist/src/lib/plot/data-cleaning.ts +0 -1069
  789. package/dist/src/lib/plot/data-transform.ts +0 -69
  790. package/dist/src/lib/plot/defaults.ts +0 -9
  791. package/dist/src/lib/plot/fill-utils.ts +0 -494
  792. package/dist/src/lib/plot/hover-lock.svelte.ts +0 -60
  793. package/dist/src/lib/plot/index.ts +0 -53
  794. package/dist/src/lib/plot/interactions.ts +0 -119
  795. package/dist/src/lib/plot/layout.ts +0 -425
  796. package/dist/src/lib/plot/reference-line.ts +0 -426
  797. package/dist/src/lib/plot/scales.ts +0 -654
  798. package/dist/src/lib/plot/svg.ts +0 -23
  799. package/dist/src/lib/plot/types.ts +0 -1144
  800. package/dist/src/lib/plot/utils/label-placement.ts +0 -541
  801. package/dist/src/lib/plot/utils/series-visibility.ts +0 -140
  802. package/dist/src/lib/plot/utils.ts +0 -11
  803. package/dist/src/lib/rdf/RdfPlot.svelte +0 -247
  804. package/dist/src/lib/rdf/calc-rdf.ts +0 -167
  805. package/dist/src/lib/rdf/index.ts +0 -27
  806. package/dist/src/lib/sanitize.ts +0 -126
  807. package/dist/src/lib/settings.ts +0 -1479
  808. package/dist/src/lib/spectral/Bands.svelte +0 -1040
  809. package/dist/src/lib/spectral/BandsAndDos.svelte +0 -134
  810. package/dist/src/lib/spectral/BrillouinBandsDos.svelte +0 -252
  811. package/dist/src/lib/spectral/Dos.svelte +0 -697
  812. package/dist/src/lib/spectral/helpers.ts +0 -1381
  813. package/dist/src/lib/spectral/index.ts +0 -8
  814. package/dist/src/lib/spectral/types.ts +0 -112
  815. package/dist/src/lib/state.svelte.ts +0 -64
  816. package/dist/src/lib/structure/Arrow.svelte +0 -72
  817. package/dist/src/lib/structure/AtomLegend.svelte +0 -815
  818. package/dist/src/lib/structure/Bond.svelte +0 -140
  819. package/dist/src/lib/structure/CanvasTooltip.svelte +0 -33
  820. package/dist/src/lib/structure/CellSelect.svelte +0 -349
  821. package/dist/src/lib/structure/Cylinder.svelte +0 -45
  822. package/dist/src/lib/structure/Lattice.svelte +0 -196
  823. package/dist/src/lib/structure/Structure.svelte +0 -2248
  824. package/dist/src/lib/structure/StructureControls.svelte +0 -1273
  825. package/dist/src/lib/structure/StructureExportPane.svelte +0 -252
  826. package/dist/src/lib/structure/StructureInfoPane.svelte +0 -737
  827. package/dist/src/lib/structure/StructureScene.svelte +0 -2255
  828. package/dist/src/lib/structure/atom-properties.ts +0 -316
  829. package/dist/src/lib/structure/bond-order-perception.ts +0 -447
  830. package/dist/src/lib/structure/bonding.ts +0 -944
  831. package/dist/src/lib/structure/export.ts +0 -861
  832. package/dist/src/lib/structure/index.ts +0 -291
  833. package/dist/src/lib/structure/label-placement.ts +0 -130
  834. package/dist/src/lib/structure/measure.ts +0 -45
  835. package/dist/src/lib/structure/parse.ts +0 -1705
  836. package/dist/src/lib/structure/partial-occupancy.ts +0 -183
  837. package/dist/src/lib/structure/pbc.ts +0 -164
  838. package/dist/src/lib/structure/supercell.ts +0 -226
  839. package/dist/src/lib/structure/validation.ts +0 -11
  840. package/dist/src/lib/symmetry/SymmetryStats.svelte +0 -226
  841. package/dist/src/lib/symmetry/WyckoffTable.svelte +0 -120
  842. package/dist/src/lib/symmetry/cell-transform.ts +0 -118
  843. package/dist/src/lib/symmetry/index.ts +0 -348
  844. package/dist/src/lib/symmetry/spacegroups.ts +0 -404
  845. package/dist/src/lib/table/HeatmapTable.svelte +0 -1833
  846. package/dist/src/lib/table/ToggleMenu.svelte +0 -385
  847. package/dist/src/lib/table/index.ts +0 -139
  848. package/dist/src/lib/theme/ThemeControl.svelte +0 -53
  849. package/dist/src/lib/theme/index.ts +0 -107
  850. package/dist/src/lib/time.ts +0 -71
  851. package/dist/src/lib/tooltip/TooltipContent.svelte +0 -58
  852. package/dist/src/lib/tooltip/index.ts +0 -2
  853. package/dist/src/lib/tooltip/types.ts +0 -13
  854. package/dist/src/lib/trajectory/Trajectory.svelte +0 -1545
  855. package/dist/src/lib/trajectory/TrajectoryError.svelte +0 -128
  856. package/dist/src/lib/trajectory/TrajectoryExportPane.svelte +0 -357
  857. package/dist/src/lib/trajectory/TrajectoryInfoPane.svelte +0 -313
  858. package/dist/src/lib/trajectory/constants.ts +0 -7
  859. package/dist/src/lib/trajectory/extract.ts +0 -196
  860. package/dist/src/lib/trajectory/format-detect.ts +0 -96
  861. package/dist/src/lib/trajectory/frame-reader.ts +0 -456
  862. package/dist/src/lib/trajectory/helpers.ts +0 -217
  863. package/dist/src/lib/trajectory/index.ts +0 -218
  864. package/dist/src/lib/trajectory/parse/ase.ts +0 -109
  865. package/dist/src/lib/trajectory/parse/hdf5.ts +0 -173
  866. package/dist/src/lib/trajectory/parse/index.ts +0 -411
  867. package/dist/src/lib/trajectory/parse/lammps.ts +0 -215
  868. package/dist/src/lib/trajectory/parse/vasp.ts +0 -102
  869. package/dist/src/lib/trajectory/parse/xyz.ts +0 -143
  870. package/dist/src/lib/trajectory/plotting.ts +0 -599
  871. package/dist/src/lib/trajectory/types.ts +0 -13
  872. package/dist/src/lib/utils.ts +0 -56
  873. package/dist/src/lib/xrd/XrdPlot.svelte +0 -615
  874. package/dist/src/lib/xrd/broadening.ts +0 -130
  875. package/dist/src/lib/xrd/calc-xrd.ts +0 -397
  876. package/dist/src/lib/xrd/index.ts +0 -38
  877. package/dist/src/lib/xrd/parse.ts +0 -858
  878. package/dist/webview.js +0 -29421
  879. package/icon.png +0 -0
  880. package/matterviz-0.3.2.vsix +0 -0
  881. package/matterviz-0.3.4.vsix +0 -0
  882. package/matterviz-0.3.5.vsix +0 -0
  883. package/scripts/sync-config.ts +0 -101
  884. package/src/declarations.d.ts +0 -2
  885. package/src/extension.ts +0 -972
  886. package/src/node-io.ts +0 -65
  887. package/src/types.ts +0 -17
  888. package/src/webview/JsonBrowser.svelte +0 -1079
  889. package/src/webview/PlotPanel.svelte +0 -346
  890. package/src/webview/detect.ts +0 -444
  891. package/src/webview/main.ts +0 -764
  892. package/src/webview/plot-utils.ts +0 -250
  893. package/test-fixtures/all-viz-types.json.gz +0 -0
  894. package/test-fixtures/plot-demo-data.json.gz +0 -0
  895. package/tests/detect.test.ts +0 -604
  896. package/tests/extension.test.ts +0 -2041
  897. package/tests/node-io.test.ts +0 -39
  898. package/tests/plot-utils.test.ts +0 -302
  899. package/tests/vite-plugin-json-gz.test.ts +0 -114
  900. package/tests/vscode-mock.ts +0 -18
  901. package/tests/webview.test.ts +0 -231
  902. package/tsconfig.json +0 -20
  903. package/vite-plugin-json-gz.ts +0 -29
  904. package/vite.config.ts +0 -34
  905. package/vite.extension.config.ts +0 -34
  906. /package/dist/{src/lib/EmptyState.svelte → EmptyState.svelte} +0 -0
  907. /package/dist/{src/lib/chempot-diagram → chempot-diagram}/ChemPotScene3D.svelte +0 -0
  908. /package/dist/{src/lib/colors → colors}/alloy-colors.json +0 -0
  909. /package/dist/{src/lib/colors → colors}/dark-mode-colors.json +0 -0
  910. /package/dist/{src/lib/colors → colors}/jmol-colors.json +0 -0
  911. /package/dist/{src/lib/colors → colors}/muted-colors.json +0 -0
  912. /package/dist/{src/lib/colors → colors}/pastel-colors.json +0 -0
  913. /package/dist/{src/lib/colors → colors}/vesta-colors.json +0 -0
  914. /package/dist/{src/lib/element → element}/BohrAtom.svelte +0 -0
  915. /package/dist/{src/lib/element → element}/Nucleus.svelte +0 -0
  916. /package/dist/{src/lib/element → element}/data.json +0 -0
  917. /package/dist/{src/lib/element → element}/data.json.gz +0 -0
  918. /package/dist/{src/lib/element → element}/data.json.gz.d.ts +0 -0
  919. /package/dist/{src/lib/element → element}/data.schema.json +0 -0
  920. /package/dist/{src/lib/element-image-urls.json → element-image-urls.json} +0 -0
  921. /package/dist/{src/lib/feedback → feedback}/Spinner.svelte +0 -0
  922. /package/dist/{src/lib/feedback → feedback}/StatusMessage.svelte +0 -0
  923. /package/dist/{src/lib/layout → layout}/json-tree/JsonValue.svelte +0 -0
  924. /package/dist/{src/lib/periodic-table → periodic-table}/TableInset.svelte +0 -0
  925. /package/dist/{src/lib/theme → theme}/themes.mjs +0 -0
  926. /package/dist/{src/lib/xrd → xrd}/atomic_scattering_params.json +0 -0
@@ -0,0 +1,1394 @@
1
+ <script lang="ts">
2
+ import type { D3InterpolateName } from '../colors'
3
+ import {
4
+ add_alpha,
5
+ is_dark_mode,
6
+ PLOT_COLORS,
7
+ vesta_hex,
8
+ watch_dark_mode,
9
+ } from '../colors'
10
+ import { normalize_show_controls } from '../controls'
11
+ import { sanitize_html } from '../sanitize'
12
+ import { ClickFeedback, DragOverlay, Spinner } from '../feedback'
13
+ import Icon from '../Icon.svelte'
14
+ import {
15
+ set_fullscreen_bg,
16
+ setup_fullscreen_effect,
17
+ toggle_fullscreen,
18
+ } from '../layout'
19
+ import { ColorBar, PlotTooltip } from '../plot'
20
+ import { create_pulse_animation } from '../effects.svelte'
21
+ import { DEFAULTS } from '../settings'
22
+ import type { AnyStructure } from '../structure'
23
+ import {
24
+ barycentric_to_tetrahedral,
25
+ compute_4d_coords,
26
+ TETRAHEDRON_VERTICES,
27
+ } from './barycentric-coords'
28
+ import ConvexHullControls from './ConvexHullControls.svelte'
29
+ import ConvexHullInfoPane from './ConvexHullInfoPane.svelte'
30
+ import ConvexHullTooltip from './ConvexHullTooltip.svelte'
31
+ import GasPressureControls from './GasPressureControls.svelte'
32
+ import * as helpers from './helpers'
33
+ import type { BaseConvexHullProps, Hull3DProps } from './index'
34
+ import { CONVEX_HULL_STYLE, default_controls, default_hull_config } from './index'
35
+ import StructurePopup from './StructurePopup.svelte'
36
+ import TemperatureSlider from './TemperatureSlider.svelte'
37
+ import type { Point4D } from './thermodynamics'
38
+ import * as thermo from './thermodynamics'
39
+ import type {
40
+ ConvexHullEntry,
41
+ HighlightStyle,
42
+ HoverData3D,
43
+ HullFaceColorMode,
44
+ } from './types'
45
+ import { compute_hull_stability } from './helpers'
46
+
47
+ let {
48
+ entries = [],
49
+ controls = {},
50
+ config = {},
51
+ on_point_click,
52
+ on_point_hover,
53
+ fullscreen = $bindable(DEFAULTS.convex_hull.quaternary.fullscreen),
54
+ enable_fullscreen = true,
55
+ enable_info_pane = true,
56
+ wrapper = $bindable(),
57
+ label_threshold = 50,
58
+ show_stable = $bindable(DEFAULTS.convex_hull.quaternary.show_stable),
59
+ show_unstable = $bindable(DEFAULTS.convex_hull.quaternary.show_unstable),
60
+ show_hull_faces = $bindable(DEFAULTS.convex_hull.quaternary.show_hull_faces),
61
+ hull_face_opacity = $bindable(DEFAULTS.convex_hull.quaternary.hull_face_opacity),
62
+ hull_face_color_mode = $bindable(
63
+ DEFAULTS.convex_hull.quaternary.hull_face_color_mode as HullFaceColorMode,
64
+ ),
65
+ element_colors = vesta_hex,
66
+ color_mode = $bindable(DEFAULTS.convex_hull.quaternary.color_mode),
67
+ color_scale = $bindable(
68
+ DEFAULTS.convex_hull.quaternary.color_scale as D3InterpolateName,
69
+ ),
70
+ info_pane_open = $bindable(DEFAULTS.convex_hull.quaternary.info_pane_open),
71
+ legend_pane_open = $bindable(DEFAULTS.convex_hull.quaternary.legend_pane_open),
72
+ max_hull_dist_show_phases = $bindable(
73
+ DEFAULTS.convex_hull.quaternary.max_hull_dist_show_phases,
74
+ ),
75
+ max_hull_dist_show_labels = $bindable(
76
+ DEFAULTS.convex_hull.quaternary.max_hull_dist_show_labels,
77
+ ),
78
+ show_stable_labels = $bindable(
79
+ DEFAULTS.convex_hull.quaternary.show_stable_labels,
80
+ ),
81
+ show_unstable_labels = $bindable(
82
+ DEFAULTS.convex_hull.quaternary.show_unstable_labels,
83
+ ),
84
+ on_file_drop,
85
+ enable_click_selection = true,
86
+ enable_structure_preview = true,
87
+ energy_source_mode = $bindable(`precomputed`),
88
+ phase_stats = $bindable(null),
89
+ stable_entries = $bindable([]),
90
+ unstable_entries = $bindable([]),
91
+ highlighted_entries = $bindable([]),
92
+ highlight_style = {},
93
+ selected_entry = $bindable(null),
94
+ temperature = $bindable(),
95
+ interpolate_temperature = true,
96
+ max_interpolation_gap = 500,
97
+ gas_config,
98
+ gas_pressures = $bindable({}),
99
+ children,
100
+ tooltip,
101
+ ...rest
102
+ }: BaseConvexHullProps<ConvexHullEntry> & Hull3DProps & {
103
+ highlight_style?: HighlightStyle
104
+ } = $props()
105
+
106
+ const merged_controls = $derived({ ...default_controls, ...controls })
107
+ const controls_config = $derived(normalize_show_controls(merged_controls.show))
108
+ const merged_config = $derived({
109
+ ...default_hull_config,
110
+ ...config,
111
+ colors: { ...default_hull_config.colors, ...config.colors },
112
+ margin: { t: 60, r: 60, b: 60, l: 60, ...config.margin },
113
+ })
114
+
115
+ // Reactive dark mode detection for canvas text color
116
+ let dark_mode = $state(is_dark_mode())
117
+ $effect(() => watch_dark_mode((dark) => dark_mode = dark))
118
+ const text_color = $derived(helpers.get_canvas_text_color(dark_mode))
119
+
120
+ // Temperature-dependent free energy support
121
+ const { has_temp_data, available_temperatures } = $derived(
122
+ helpers.analyze_temperature_data(entries),
123
+ )
124
+
125
+ // Initialize or reset temperature when it's undefined or no longer valid
126
+ $effect(() => {
127
+ if (
128
+ has_temp_data &&
129
+ available_temperatures.length > 0 &&
130
+ (temperature === undefined || !available_temperatures.includes(temperature))
131
+ ) temperature = available_temperatures[0]
132
+ })
133
+
134
+ // Filter entries by temperature when in temperature mode
135
+ const temp_filtered_entries = $derived(
136
+ has_temp_data && temperature !== undefined
137
+ ? helpers.filter_entries_at_temperature(entries, temperature, {
138
+ interpolate: interpolate_temperature,
139
+ max_interpolation_gap,
140
+ })
141
+ : entries,
142
+ )
143
+
144
+ // Gas-dependent chemical potential support (corrections based on T, P)
145
+ const {
146
+ entries: gas_corrected_entries,
147
+ analysis: gas_analysis,
148
+ merged_config: merged_gas_config,
149
+ } = $derived(
150
+ helpers.get_gas_corrected_entries(
151
+ temp_filtered_entries,
152
+ gas_config,
153
+ gas_pressures,
154
+ temperature ?? helpers.DEFAULT_GAS_TEMP,
155
+ ),
156
+ )
157
+
158
+ let { // Compute energy mode information
159
+ has_precomputed_e_form,
160
+ has_precomputed_hull,
161
+ can_compute_e_form,
162
+ can_compute_hull,
163
+ energy_mode,
164
+ unary_refs,
165
+ } = $derived(
166
+ helpers.compute_energy_mode_info(
167
+ gas_corrected_entries,
168
+ thermo.find_lowest_energy_unary_refs,
169
+ energy_source_mode,
170
+ ),
171
+ )
172
+
173
+ const effective_entries = $derived(
174
+ helpers.get_effective_entries(
175
+ gas_corrected_entries,
176
+ energy_mode,
177
+ unary_refs,
178
+ thermo.compute_e_form_per_atom,
179
+ ),
180
+ )
181
+
182
+ // Process convex hull data with unified PhaseData interface using effective entries
183
+ const pd_data = $derived(thermo.process_hull_entries(effective_entries))
184
+
185
+ // Pre-compute polymorph stats once for O(1) tooltip lookups
186
+ const polymorph_stats_map = $derived(
187
+ helpers.compute_all_polymorph_stats(effective_entries),
188
+ )
189
+
190
+ const elements = $derived.by(() => {
191
+ if (pd_data.elements.length > 4) {
192
+ console.error(
193
+ `ConvexHull4D: Dataset contains ${pd_data.elements.length} elements, but quaternary diagrams require exactly 4. Found: [${
194
+ pd_data.elements.join(`, `)
195
+ }]`,
196
+ )
197
+ return []
198
+ }
199
+ return pd_data.elements
200
+ })
201
+
202
+ // Compute 4D hull for visualization (always compute when we have formation energies)
203
+ const hull_4d = $derived.by(() => {
204
+ if (elements.length !== 4) return []
205
+
206
+ try {
207
+ // Get coords with formation energies, excluding entries that don't participate in hull
208
+ const coords = compute_4d_coords(pd_data.entries, elements)
209
+ .filter((ent) => !ent.exclude_from_hull)
210
+
211
+ // Convert to 4D points for hull computation using barycentric coordinates (composition fractions)
212
+ const points_4d: Point4D[] = coords
213
+ .filter(
214
+ (ent) =>
215
+ Number.isFinite(ent.e_form_per_atom) &&
216
+ [ent.x, ent.y, ent.z].every(Number.isFinite),
217
+ )
218
+ .map((ent) => {
219
+ const amounts = elements.map((el) => ent.composition[el] || 0)
220
+ const total = amounts.reduce((sum, amt) => sum + amt, 0)
221
+ if (!(total > 0)) return { x: NaN, y: NaN, z: NaN, w: NaN }
222
+ const [x, y, z] = amounts.map((amt) => amt / total)
223
+ return { x, y, z, w: ent.e_form_per_atom ?? NaN }
224
+ })
225
+ .filter((point) => [point.x, point.y, point.z, point.w].every(Number.isFinite))
226
+
227
+ if (points_4d.length < 5) return [] // Need at least 5 points for 4D hull
228
+
229
+ return thermo.compute_lower_hull_4d(points_4d)
230
+ } catch (error) {
231
+ console.error(`Error computing 4D hull:`, error)
232
+ return []
233
+ }
234
+ })
235
+
236
+ // Enrich coords with e_above_hull (before filtering)
237
+ const all_enriched_entries = $derived.by(() => {
238
+ if (elements.length !== 4) return []
239
+ try {
240
+ const coords = compute_4d_coords(pd_data.entries, elements)
241
+ if (energy_mode !== `on-the-fly` || hull_4d.length === 0) return coords
242
+
243
+ // Build 4D points, tracking original indices for mapping hull distances back
244
+ const valid = coords.flatMap((entry, idx) => {
245
+ if (
246
+ !Number.isFinite(entry.e_form_per_atom) ||
247
+ ![entry.x, entry.y, entry.z].every(Number.isFinite)
248
+ ) return []
249
+ const amounts = elements.map((el) => entry.composition[el] || 0)
250
+ const total = amounts.reduce((sum, amt) => sum + amt, 0)
251
+ if (!(total > 0)) return []
252
+ const [x, y, z] = amounts.map((amt) => amt / total)
253
+ return [x, y, z].every(Number.isFinite)
254
+ ? [{ idx, pt: { x, y, z, w: entry.e_form_per_atom ?? NaN } }]
255
+ : []
256
+ })
257
+ const raw_dists = thermo.compute_e_above_hull_4d(valid.map((item) => item.pt), hull_4d)
258
+ const hull_map = new Map(valid.map((item, hull_idx) => [item.idx, raw_dists[hull_idx]]))
259
+ return coords.map((entry, idx) => {
260
+ const raw = hull_map.get(idx)
261
+ if (raw === undefined) return { ...entry, e_above_hull: raw, is_stable: false }
262
+ return { ...entry, ...compute_hull_stability(raw, entry.exclude_from_hull) }
263
+ })
264
+ } catch (err) {
265
+ console.error(`Error computing quaternary coordinates:`, err)
266
+ return []
267
+ }
268
+ })
269
+
270
+ // Auto threshold: show all for few entries, use default for many, interpolate between
271
+ const max_hull_dist_in_data = $derived(
272
+ helpers.calc_max_hull_dist_in_data(all_enriched_entries),
273
+ )
274
+ const auto_default_threshold = $derived(helpers.compute_auto_hull_dist_threshold(
275
+ all_enriched_entries.length,
276
+ max_hull_dist_in_data,
277
+ DEFAULTS.convex_hull.quaternary.max_hull_dist_show_phases,
278
+ ))
279
+
280
+ const next_auto_threshold = helpers.auto_threshold_reset(
281
+ DEFAULTS.convex_hull.quaternary.max_hull_dist_show_phases,
282
+ )
283
+ $effect(() => {
284
+ max_hull_dist_show_phases = next_auto_threshold(
285
+ entries,
286
+ max_hull_dist_show_phases,
287
+ auto_default_threshold,
288
+ ) ?? max_hull_dist_show_phases
289
+ })
290
+
291
+ // Filter by threshold; visibility is a view predicate, not entry state.
292
+ const plot_entries = $derived(
293
+ all_enriched_entries.filter((entry) => {
294
+ // Always include stable entries and elemental reference points
295
+ if (helpers.entry_is_stable(entry)) return true
296
+ return typeof entry.e_above_hull === `number` &&
297
+ entry.e_above_hull <= max_hull_dist_show_phases
298
+ }),
299
+ )
300
+ const visible_entries = $derived(helpers.visible_entries(
301
+ plot_entries,
302
+ show_stable,
303
+ show_unstable,
304
+ ))
305
+
306
+ // Stable and unstable entries exposed as bindable props
307
+ $effect(() => {
308
+ stable_entries = plot_entries.filter(helpers.entry_is_stable)
309
+ unstable_entries = plot_entries.filter(helpers.entry_is_unstable)
310
+ })
311
+
312
+ let canvas: HTMLCanvasElement | undefined = undefined
313
+ let ctx: CanvasRenderingContext2D | null = null
314
+ let frame_id = 0 // Performance optimization
315
+
316
+ // Camera state - following Materials Project's 3D camera setup
317
+ let camera = $state({
318
+ rotation_x: DEFAULTS.convex_hull.quaternary.camera_rotation_x,
319
+ rotation_y: DEFAULTS.convex_hull.quaternary.camera_rotation_y,
320
+ zoom: DEFAULTS.convex_hull.quaternary.camera_zoom,
321
+ center_x: 0,
322
+ center_y: 20, // Slight offset to avoid legend overlap
323
+ })
324
+
325
+ // Interaction state
326
+ let is_dragging = $state(false)
327
+ let drag_started = $state(false)
328
+ let last_mouse = $state({ x: 0, y: 0 })
329
+ let hover_data = $state.raw<HoverData3D<ConvexHullEntry> | null>(null)
330
+ let copy_feedback = $state({ visible: false, position: { x: 0, y: 0 } })
331
+
332
+ // Drag and drop state
333
+ let drag_over = $state(false)
334
+
335
+ // Structure popup state
336
+ let modal_open = $state(false)
337
+ let selected_structure = $state<AnyStructure | null>(null)
338
+ let modal_place_right = $state(true)
339
+ $effect(() => {
340
+ const current_selection = helpers.current_entry(selected_entry, plot_entries)
341
+ const stale_selection = selected_entry && !current_selection
342
+ if (stale_selection) selected_entry = null
343
+ else if (current_selection && !helpers.same_entry(current_selection, selected_entry)) {
344
+ selected_entry = current_selection
345
+ }
346
+ const current_hover = helpers.current_entry(hover_data?.entry, plot_entries)
347
+ if (hover_data?.entry && !current_hover) {
348
+ hover_data = null
349
+ on_point_hover?.(null)
350
+ } else if (hover_data && current_hover && current_hover !== hover_data.entry) {
351
+ hover_data = { ...hover_data, entry: current_hover }
352
+ }
353
+ if (modal_open) {
354
+ const structure = current_selection && extract_structure_from_entry(current_selection)
355
+ if (structure) selected_structure = structure
356
+ else {
357
+ modal_open = false
358
+ selected_structure = null
359
+ }
360
+ }
361
+ })
362
+
363
+ // Hull face color (customizable via controls)
364
+ let hull_face_color = $state(`#4caf50`)
365
+
366
+ // Pulsating highlight for selected point and highlighted entries
367
+ const pulse = create_pulse_animation(
368
+ () => selected_entry !== null || highlighted_entries.length > 0,
369
+ { on_tick: render_once },
370
+ )
371
+ let pulse_opacity = $derived(0.3 + 0.4 * pulse.unit)
372
+
373
+ // Merge highlight style with defaults
374
+ const merged_highlight_style = $derived(
375
+ helpers.merge_highlight_style(highlight_style),
376
+ )
377
+
378
+ // Helper to check if entry is highlighted
379
+ const is_highlighted = (entry: ConvexHullEntry): boolean =>
380
+ helpers.is_entry_highlighted(entry, highlighted_entries)
381
+
382
+ // Re-render when important state changes
383
+ $effect(() => {
384
+ // oxfmt-ignore
385
+ void [show_hull_faces, color_mode, color_scale, camera.rotation_x, camera.rotation_y, camera.zoom, camera.center_x, camera.center_y, plot_entries, hull_face_color, hull_face_opacity, hull_face_color_mode, element_colors, text_color, elements] // track reactively
386
+
387
+ render_once()
388
+ })
389
+
390
+ // Visibility toggles are now bindable props
391
+
392
+ // Smart label defaults - hide labels if too many entries
393
+ $effect(() => {
394
+ const total_entries = effective_entries.length
395
+ if (total_entries > label_threshold) {
396
+ show_stable_labels = false
397
+ } else {
398
+ // For smaller datasets, show stable labels by default
399
+ show_stable_labels = true
400
+ }
401
+ show_unstable_labels = false
402
+ })
403
+
404
+ // Function to extract structure data from a convex hull entry
405
+ function extract_structure_from_entry(
406
+ entry: ConvexHullEntry,
407
+ ): AnyStructure | null {
408
+ const orig_entry = entries.find((ent) => ent.entry_id === entry.entry_id)
409
+ return orig_entry?.structure as AnyStructure || null
410
+ }
411
+
412
+ const reset_camera = () => {
413
+ camera.rotation_x = DEFAULTS.convex_hull.quaternary.camera_rotation_x
414
+ camera.rotation_y = DEFAULTS.convex_hull.quaternary.camera_rotation_y
415
+ camera.zoom = DEFAULTS.convex_hull.quaternary.camera_zoom
416
+ camera.center_x = 0
417
+ camera.center_y = 20 // Slight offset to avoid legend overlap
418
+ }
419
+ function reset_all() {
420
+ reset_camera()
421
+ fullscreen = DEFAULTS.convex_hull.quaternary.fullscreen
422
+ info_pane_open = DEFAULTS.convex_hull.quaternary.info_pane_open
423
+ legend_pane_open = DEFAULTS.convex_hull.quaternary.legend_pane_open
424
+ color_mode = DEFAULTS.convex_hull.quaternary.color_mode
425
+ color_scale = DEFAULTS.convex_hull.quaternary.color_scale as D3InterpolateName
426
+ show_stable = DEFAULTS.convex_hull.quaternary.show_stable
427
+ show_unstable = DEFAULTS.convex_hull.quaternary.show_unstable
428
+ show_stable_labels = DEFAULTS.convex_hull.quaternary.show_stable_labels
429
+ show_unstable_labels = DEFAULTS.convex_hull.quaternary.show_unstable_labels
430
+ // Use auto-computed threshold based on entry count instead of static default
431
+ max_hull_dist_show_phases = auto_default_threshold
432
+ max_hull_dist_show_labels =
433
+ DEFAULTS.convex_hull.quaternary.max_hull_dist_show_labels
434
+ show_hull_faces = DEFAULTS.convex_hull.quaternary.show_hull_faces
435
+ hull_face_color = DEFAULTS.convex_hull.quaternary.hull_face_color
436
+ hull_face_opacity = DEFAULTS.convex_hull.quaternary.hull_face_opacity
437
+ hull_face_color_mode = DEFAULTS.convex_hull.quaternary
438
+ .hull_face_color_mode as HullFaceColorMode
439
+ }
440
+
441
+ const handle_keydown = (event: KeyboardEvent) => {
442
+ const target = event.target
443
+ // Skip if focus is on an interactive element that handles Enter natively
444
+ const interactive_selector =
445
+ `input,textarea,select,button,a,[contenteditable="true"],[role="button"],[tabindex]:not([tabindex="-1"])`
446
+ if (
447
+ target instanceof HTMLElement &&
448
+ target.matches(interactive_selector) &&
449
+ target !== canvas
450
+ ) return
451
+
452
+ // Prevent double handling from canvas + wrapper bubbling
453
+ if (event.target !== event.currentTarget && event.currentTarget !== canvas) return
454
+
455
+ // Handle Enter for keyboard accessibility - select hovered entry
456
+ if (event.key === `Enter`) {
457
+ const entry = hover_data?.entry
458
+ if (entry) {
459
+ on_point_click?.(entry)
460
+ if (enable_click_selection) {
461
+ selected_entry = entry
462
+ if (enable_structure_preview) {
463
+ const structure = extract_structure_from_entry(entry)
464
+ if (structure) {
465
+ selected_structure = structure
466
+ modal_place_right = helpers.calculate_modal_side(wrapper)
467
+ modal_open = true
468
+ }
469
+ }
470
+ }
471
+ } else if (modal_open) {
472
+ close_structure_popup()
473
+ }
474
+ return
475
+ }
476
+
477
+ const actions: Record<string, () => void> = {
478
+ r: reset_camera,
479
+ b: () => color_mode = color_mode === `stability` ? `energy` : `stability`,
480
+ s: () => show_stable = !show_stable,
481
+ u: () => show_unstable = !show_unstable,
482
+ h: () => show_hull_faces = !show_hull_faces,
483
+ l: () => show_stable_labels = !show_stable_labels,
484
+ }
485
+ actions[event.key.toLowerCase()]?.()
486
+ }
487
+
488
+ async function handle_file_drop(event: DragEvent): Promise<void> {
489
+ drag_over = false
490
+ const data = await helpers.parse_hull_entries_from_drop(event)
491
+ if (data) on_file_drop?.(data)
492
+ }
493
+
494
+ async function copy_entry_data(
495
+ entry: ConvexHullEntry,
496
+ position: { x: number; y: number },
497
+ ) {
498
+ await helpers.copy_entry_to_clipboard(entry, position, (visible, pos) => {
499
+ copy_feedback.visible = visible
500
+ copy_feedback.position = pos
501
+ })
502
+ }
503
+
504
+ const get_point_color = (entry: ConvexHullEntry): string =>
505
+ helpers.get_point_color_for_entry(
506
+ entry,
507
+ color_mode,
508
+ merged_config.colors,
509
+ energy_color_scale,
510
+ )
511
+
512
+ // Cache energy color scale per frame/setting
513
+ const energy_color_scale = $derived.by(() =>
514
+ helpers.get_energy_color_scale(color_mode, color_scale, plot_entries)
515
+ )
516
+
517
+ // Convex hull statistics - compute internally and expose via bindable prop
518
+ $effect(() => {
519
+ phase_stats = thermo.get_convex_hull_stats(plot_entries, elements, 4)
520
+ })
521
+
522
+ // 3D to 2D projection following Materials Project approach
523
+ function project_3d_point(
524
+ x: number,
525
+ y: number,
526
+ z: number,
527
+ ): { x: number; y: number; depth: number } {
528
+ if (!canvas) return { x: 0, y: 0, depth: 0 }
529
+
530
+ // Center coordinates around tetrahedron/triangle centroid
531
+ let [centered_x, centered_y, centered_z] = [x, y, z]
532
+
533
+ // Tetrahedron centroid: average of vertices (1,0,0), (0.5,√3/2,0), (0.5,√3/6,√6/3), (0,0,0)
534
+ const centroid_x = (1 + 0.5 + 0.5 + 0) / 4 // = 0.5
535
+ const centroid_y = (0 + Math.sqrt(3) / 2 + Math.sqrt(3) / 6 + 0) / 4 // = √3/6
536
+ const centroid_z = (0 + 0 + Math.sqrt(6) / 3 + 0) / 4 // = √6/12
537
+ centered_x = x - centroid_x
538
+ centered_y = y - centroid_y
539
+ centered_z = z - centroid_z
540
+
541
+ // Apply 3D transformations around the centered coordinates
542
+ const cos_x = Math.cos(camera.rotation_x)
543
+ const sin_x = Math.sin(camera.rotation_x)
544
+ const cos_y = Math.cos(camera.rotation_y)
545
+ const sin_y = Math.sin(camera.rotation_y)
546
+
547
+ // Rotate around Y axis first
548
+ const x1 = centered_x * cos_y - centered_z * sin_y
549
+ const z1 = centered_x * sin_y + centered_z * cos_y
550
+
551
+ // Then rotate around X axis
552
+ const y2 = centered_y * cos_x - z1 * sin_x
553
+ const z2 = centered_y * sin_x + z1 * cos_x
554
+
555
+ // Apply perspective projection using cached canvas dimensions for consistency
556
+ const scale = Math.min(canvas_dims.width, canvas_dims.height) * 0.6 * camera.zoom
557
+ const center_x = canvas_dims.width / 2 + camera.center_x
558
+ const center_y = canvas_dims.height / 2 + camera.center_y
559
+
560
+ return {
561
+ x: center_x + x1 * scale,
562
+ y: center_y - y2 * scale, // Flip Y for canvas coordinates
563
+ depth: z2, // For depth sorting
564
+ }
565
+ }
566
+
567
+ function draw_structure_outline(): void {
568
+ if (!ctx || !canvas) return
569
+
570
+ const styles = getComputedStyle(canvas)
571
+ // Match gray dashed structure lines used in 3D
572
+ ctx.strokeStyle = CONVEX_HULL_STYLE.structure_line.color
573
+ ctx.lineWidth = CONVEX_HULL_STYLE.structure_line.line_width
574
+ ctx.setLineDash(CONVEX_HULL_STYLE.structure_line.dash)
575
+
576
+ // Draw tetrahedron edges
577
+ draw_tetrahedron()
578
+
579
+ // Reset dash and stroke for subsequent drawings
580
+ ctx.setLineDash([])
581
+ ctx.strokeStyle = styles.getPropertyValue(`--hull-edge-color`) || `#212121`
582
+ }
583
+
584
+ function draw_tetrahedron(): void {
585
+ if (!ctx) return
586
+
587
+ // Convert vertices to Point3D objects
588
+ const vertices = TETRAHEDRON_VERTICES.map(([x, y, z]) => ({ x, y, z }))
589
+
590
+ // Tetrahedron edges (connecting vertices)
591
+ const edges = [
592
+ [0, 1],
593
+ [0, 2],
594
+ [0, 3], // From vertex 0
595
+ [1, 2],
596
+ [1, 3], // From vertex 1
597
+ [2, 3], // From vertex 2
598
+ ]
599
+
600
+ // Draw edges
601
+ ctx.beginPath()
602
+ for (const [start, end] of edges) {
603
+ const v1 = vertices[start]
604
+ const v2 = vertices[end]
605
+
606
+ const proj1 = project_3d_point(v1.x, v1.y, v1.z)
607
+ const proj2 = project_3d_point(v2.x, v2.y, v2.z)
608
+
609
+ ctx.moveTo(proj1.x, proj1.y)
610
+ ctx.lineTo(proj2.x, proj2.y)
611
+ }
612
+ ctx.stroke()
613
+
614
+ // Corner element labels: place just outside along line towards tetrahedron centroid
615
+ if (elements.length === 4) {
616
+ // Tetrahedron centroid in barycentric space maps to average of vertices
617
+ const centroid = {
618
+ x: (vertices[0].x + vertices[1].x + vertices[2].x + vertices[3].x) / 4,
619
+ y: (vertices[0].y + vertices[1].y + vertices[2].y + vertices[3].y) / 4,
620
+ z: (vertices[0].z + vertices[1].z + vertices[2].z + vertices[3].z) / 4,
621
+ }
622
+
623
+ ctx.fillStyle = text_color
624
+ ctx.font = `bold 18px Arial`
625
+ ctx.textAlign = `center`
626
+ ctx.textBaseline = `middle`
627
+
628
+ const distance = 0.06
629
+ for (let idx = 0; idx < 4; idx++) {
630
+ const vx = vertices[idx]
631
+ // Direction from centroid to vertex
632
+ const { x: cx, y: cy, z: cz } = centroid
633
+ const dir = { x: vx.x - cx, y: vx.y - cy, z: vx.z - cz }
634
+ const len = Math.hypot(dir.x, dir.y, dir.z) || 1
635
+ const label_pos = {
636
+ x: vx.x + (dir.x / len) * distance,
637
+ y: vx.y + (dir.y / len) * distance,
638
+ z: vx.z + (dir.z / len) * distance,
639
+ }
640
+ const proj = project_3d_point(label_pos.x, label_pos.y, label_pos.z)
641
+ ctx.fillText(elements[idx], proj.x, proj.y)
642
+ }
643
+ }
644
+ }
645
+
646
+ // Draw convex hull faces connecting stable points
647
+ function draw_convex_hull_faces(): void {
648
+ if (!ctx || !show_hull_faces || hull_4d.length === 0) return
649
+
650
+ // Get stable points to determine which hull facets to draw
651
+ const stable_points = plot_entries.filter(helpers.entry_is_stable)
652
+ if (stable_points.length === 0) return
653
+
654
+ // Each tetrahedral facet has 4 triangular faces - we need to draw these
655
+ // Collect all triangular faces with depth for sorting
656
+ type TriangleFace = {
657
+ vertices: [
658
+ { x: number; y: number; depth: number },
659
+ { x: number; y: number; depth: number },
660
+ { x: number; y: number; depth: number },
661
+ ]
662
+ avg_depth: number
663
+ avg_w: number // Average formation energy for coloring
664
+ tet_idx: number // Tetrahedron index for facet_index mode
665
+ centroid_bary: number[] // Barycentric centroid [el0, el1, el2, el3] for dominant_element mode
666
+ }
667
+
668
+ const triangles: TriangleFace[] = []
669
+
670
+ for (let tet_idx = 0; tet_idx < hull_4d.length; tet_idx++) {
671
+ const tet = hull_4d[tet_idx]
672
+ const [p0, p1, p2, p3] = tet.vertices
673
+
674
+ // Convert barycentric coordinates to tetrahedral 3D coordinates
675
+ const tet0 = barycentric_to_tetrahedral([
676
+ p0.x,
677
+ p0.y,
678
+ p0.z,
679
+ 1 - p0.x - p0.y - p0.z,
680
+ ])
681
+ const tet1 = barycentric_to_tetrahedral([
682
+ p1.x,
683
+ p1.y,
684
+ p1.z,
685
+ 1 - p1.x - p1.y - p1.z,
686
+ ])
687
+ const tet2 = barycentric_to_tetrahedral([
688
+ p2.x,
689
+ p2.y,
690
+ p2.z,
691
+ 1 - p2.x - p2.y - p2.z,
692
+ ])
693
+ const tet3 = barycentric_to_tetrahedral([
694
+ p3.x,
695
+ p3.y,
696
+ p3.z,
697
+ 1 - p3.x - p3.y - p3.z,
698
+ ])
699
+
700
+ // Project to 2D screen space
701
+ const proj0 = project_3d_point(tet0.x, tet0.y, tet0.z)
702
+ const proj1 = project_3d_point(tet1.x, tet1.y, tet1.z)
703
+ const proj2 = project_3d_point(tet2.x, tet2.y, tet2.z)
704
+ const proj3 = project_3d_point(tet3.x, tet3.y, tet3.z)
705
+
706
+ // Compute tetrahedron centroid in barycentric coords (for dominant_element mode)
707
+ // All 4 faces share the same tetrahedron, so they get the same color for facet_index
708
+ const tet_centroid_bary = [
709
+ (p0.x + p1.x + p2.x + p3.x) / 4,
710
+ (p0.y + p1.y + p2.y + p3.y) / 4,
711
+ (p0.z + p1.z + p2.z + p3.z) / 4,
712
+ ((1 - p0.x - p0.y - p0.z) + (1 - p1.x - p1.y - p1.z) +
713
+ (1 - p2.x - p2.y - p2.z) + (1 - p3.x - p3.y - p3.z)) / 4,
714
+ ]
715
+
716
+ // Each tetrahedron has 4 triangular faces
717
+ const faces: [typeof proj0, typeof proj1, typeof proj2, number][] = [
718
+ [proj0, proj1, proj2, (p0.w + p1.w + p2.w) / 3],
719
+ [proj0, proj1, proj3, (p0.w + p1.w + p3.w) / 3],
720
+ [proj0, proj2, proj3, (p0.w + p2.w + p3.w) / 3],
721
+ [proj1, proj2, proj3, (p1.w + p2.w + p3.w) / 3],
722
+ ]
723
+
724
+ for (const [v0, v1, v2, avg_w] of faces) {
725
+ triangles.push({
726
+ vertices: [v0, v1, v2],
727
+ avg_depth: (v0.depth + v1.depth + v2.depth) / 3,
728
+ avg_w,
729
+ tet_idx,
730
+ centroid_bary: tet_centroid_bary,
731
+ })
732
+ }
733
+ }
734
+
735
+ // Sort by depth (back to front)
736
+ triangles.sort((a, b) => a.avg_depth - b.avg_depth)
737
+
738
+ // Lazy computation for uniform mode: normalize alpha by formation energy
739
+ let norm_alpha: ((w: number) => number) | null = null
740
+ if (hull_face_color_mode === `uniform`) {
741
+ norm_alpha = (energy: number) => {
742
+ const t = Math.max(
743
+ 0,
744
+ Math.min(1, (0 - energy) / Math.max(1e-6, 0 - formation_energy_min)),
745
+ )
746
+ return t * hull_face_opacity
747
+ }
748
+ }
749
+
750
+ // Lazy computation for formation_energy mode
751
+ let energy_face_scale: ((val: number) => string) | null = null
752
+ let min_w = 0
753
+ if (hull_face_color_mode === `formation_energy`) {
754
+ const all_avg_w = triangles.map((tri) => tri.avg_w)
755
+ min_w = Math.min(...all_avg_w)
756
+ energy_face_scale = helpers.get_energy_color_scale(
757
+ `energy`,
758
+ color_scale,
759
+ all_avg_w.map((energy) => ({ e_above_hull: energy - min_w })), // Normalize to 0-based
760
+ )
761
+ }
762
+
763
+ // Helper to get face color based on mode
764
+ const get_face_color = (tri: TriangleFace): string => {
765
+ if (hull_face_color_mode === `uniform`) {
766
+ return hull_face_color
767
+ }
768
+ if (hull_face_color_mode === `formation_energy`) {
769
+ return energy_face_scale?.(tri.avg_w - min_w) ?? hull_face_color
770
+ }
771
+ if (hull_face_color_mode === `dominant_element`) {
772
+ // Find element with highest fraction
773
+ const max_idx = tri.centroid_bary.indexOf(Math.max(...tri.centroid_bary))
774
+ const el = elements[max_idx]
775
+ return element_colors[el] ?? `#888888`
776
+ }
777
+ if (hull_face_color_mode === `facet_index`) {
778
+ return PLOT_COLORS[tri.tet_idx % PLOT_COLORS.length]
779
+ }
780
+ return hull_face_color
781
+ }
782
+
783
+ // Draw each triangle
784
+ for (const tri of triangles) {
785
+ const [v0, v1, v2] = tri.vertices
786
+ // Uniform mode uses variable opacity; other modes use fixed opacity
787
+ const alpha = hull_face_color_mode === `uniform`
788
+ ? (norm_alpha?.(tri.avg_w) ?? hull_face_opacity)
789
+ : hull_face_opacity
790
+ const face_color = get_face_color(tri)
791
+
792
+ ctx.save()
793
+ ctx.beginPath()
794
+ ctx.moveTo(v0.x, v0.y)
795
+ ctx.lineTo(v1.x, v1.y)
796
+ ctx.lineTo(v2.x, v2.y)
797
+ ctx.closePath()
798
+
799
+ ctx.fillStyle = add_alpha(face_color, alpha)
800
+ ctx.fill()
801
+
802
+ // Edge lines more pronounced with higher opacity
803
+ ctx.strokeStyle = add_alpha(face_color, Math.min(0.4, alpha * 4))
804
+ ctx.lineWidth = 1
805
+ ctx.stroke()
806
+ ctx.restore()
807
+ }
808
+ }
809
+
810
+ function draw_data_points(): void {
811
+ if (!ctx || sorted_points_cache.length === 0) return
812
+
813
+ for (const { entry, projected } of sorted_points_cache) {
814
+ const is_stable = helpers.entry_is_stable(entry)
815
+ const is_entry_highlighted = is_highlighted(entry)
816
+ const color = get_point_color(entry)
817
+ const size = (entry.size || (is_stable ? 6 : 4)) * canvas_dims.scale
818
+ const marker = entry.marker || `circle`
819
+
820
+ // Shadow
821
+ const shadow_offset = Math.abs(entry.z) * 2 * canvas_dims.scale
822
+ ctx.fillStyle = `rgba(0, 0, 0, 0.2)`
823
+ const shadow_path = helpers.create_marker_path(size * 0.8, marker)
824
+ ctx.save()
825
+ ctx.translate(projected.x + shadow_offset, projected.y + shadow_offset)
826
+ ctx.fill(shadow_path)
827
+ ctx.restore()
828
+
829
+ // Highlights
830
+ if (selected_entry && entry.entry_id === selected_entry.entry_id) {
831
+ helpers.draw_selection_highlight(
832
+ ctx,
833
+ projected,
834
+ size,
835
+ canvas_dims.scale,
836
+ pulse.time,
837
+ pulse_opacity,
838
+ )
839
+ }
840
+ if (is_entry_highlighted) {
841
+ helpers.draw_highlight_effect(
842
+ ctx,
843
+ projected,
844
+ size,
845
+ canvas_dims.scale,
846
+ pulse.time,
847
+ merged_highlight_style,
848
+ )
849
+ }
850
+
851
+ // Main point with marker symbol
852
+ ctx.fillStyle =
853
+ is_entry_highlighted && merged_highlight_style.effect === `color`
854
+ ? merged_highlight_style.color
855
+ : color
856
+ ctx.strokeStyle = is_stable ? `#ffffff` : `#000000`
857
+ ctx.lineWidth = 0.5 * canvas_dims.scale
858
+ const marker_path = helpers.create_marker_path(size, marker)
859
+ ctx.save()
860
+ ctx.translate(projected.x, projected.y)
861
+ ctx.fill(marker_path)
862
+ ctx.stroke(marker_path)
863
+ ctx.restore()
864
+ }
865
+
866
+ if (!merged_config.show_labels) return
867
+
868
+ const label_entries = helpers.get_composition_label_entries(
869
+ sorted_points_cache
870
+ .map(({ entry }) => entry)
871
+ .filter((entry) => {
872
+ if (entry.is_element) return false
873
+ const is_stable = helpers.entry_is_stable(entry)
874
+ return (is_stable && show_stable_labels) ||
875
+ (!is_stable && show_unstable_labels &&
876
+ (entry.e_above_hull ?? 0) <= max_hull_dist_show_labels)
877
+ }),
878
+ )
879
+
880
+ ctx.fillStyle = text_color
881
+ ctx.font = `${Math.round(12 * canvas_dims.scale)}px Arial`
882
+ ctx.textAlign = `center`
883
+ ctx.textBaseline = `middle`
884
+
885
+ for (const entry of label_entries) {
886
+ const is_stable = helpers.entry_is_stable(entry)
887
+ const size = (entry.size || (is_stable ? 6 : 4)) * canvas_dims.scale
888
+ const projected = project_3d_point(entry.x, entry.y, entry.z)
889
+ const label = helpers.get_entry_label(entry, elements)
890
+ ctx.fillText(label, projected.x, projected.y + size + 6 * canvas_dims.scale)
891
+ }
892
+ }
893
+
894
+ function render_frame(): void {
895
+ if (!ctx || !canvas) return
896
+
897
+ // Use CSS dimensions for rendering (already scaled by DPR in context)
898
+ const display_width = canvas.clientWidth || 600
899
+ const display_height = canvas.clientHeight || 600
900
+
901
+ ctx.clearRect(0, 0, display_width, display_height) // Clear canvas
902
+
903
+ ctx.fillStyle = `transparent` // Set background - use transparent to inherit from container
904
+ ctx.fillRect(0, 0, display_width, display_height)
905
+
906
+ if (elements.length !== 4) {
907
+ if (elements.length > 0) {
908
+ ctx.fillStyle = text_color
909
+ ctx.font = `16px Arial`
910
+ ctx.textAlign = `center`
911
+ ctx.textBaseline = `middle`
912
+ ctx.fillText(
913
+ `Quaternary convex hull requires exactly 4 elements (got ${elements.length})`,
914
+ display_width / 2,
915
+ display_height / 2,
916
+ )
917
+ }
918
+ return
919
+ }
920
+
921
+ draw_structure_outline() // Draw tetrahedron outline
922
+
923
+ draw_convex_hull_faces() // Draw convex hull faces (before points so they appear behind)
924
+
925
+ draw_data_points() // Draw data points (on top)
926
+ }
927
+
928
+ function handle_mouse_down(event: MouseEvent) {
929
+ is_dragging = true
930
+ drag_started = false
931
+ hover_data = null
932
+ on_point_hover?.(null)
933
+ last_mouse = { x: event.clientX, y: event.clientY }
934
+ }
935
+
936
+ const handle_mouse_move = (event: MouseEvent) => {
937
+ if (!is_dragging) return
938
+ const [dx, dy] = [event.clientX - last_mouse.x, event.clientY - last_mouse.y]
939
+
940
+ // Mark as drag if any movement occurred
941
+ if (dx !== 0 || dy !== 0) drag_started = true
942
+
943
+ // With Cmd/Ctrl held: pan the view instead of rotating
944
+ if (event.metaKey || event.ctrlKey) {
945
+ camera.center_x += dx
946
+ camera.center_y += dy
947
+ } else {
948
+ camera.rotation_y += dx * 0.005
949
+ camera.rotation_x = Math.max(
950
+ -Math.PI / 3,
951
+ Math.min(Math.PI / 3, camera.rotation_x - dy * 0.005),
952
+ )
953
+ }
954
+ last_mouse = { x: event.clientX, y: event.clientY }
955
+ }
956
+
957
+ const handle_wheel = (event: WheelEvent) => {
958
+ event.preventDefault()
959
+ camera.zoom = Math.max(
960
+ 1.0,
961
+ Math.min(15, camera.zoom * (event.deltaY > 0 ? 0.98 : 1.02)),
962
+ )
963
+ }
964
+
965
+ const handle_hover = (event: MouseEvent) => {
966
+ if (is_dragging) return
967
+ const entry = find_entry_at_mouse(event)
968
+ hover_data = entry
969
+ ? { entry, position: { x: event.clientX, y: event.clientY } }
970
+ : null
971
+ on_point_hover?.(hover_data)
972
+ }
973
+
974
+ const find_entry_at_mouse = (event: MouseEvent): ConvexHullEntry | null =>
975
+ helpers.find_hull_entry_at_mouse(
976
+ canvas,
977
+ event,
978
+ visible_entries,
979
+ (x: number, y: number, z: number) => {
980
+ const projected = project_3d_point(x, y, z)
981
+ return { x: projected.x, y: projected.y }
982
+ },
983
+ )
984
+
985
+ const handle_click = (event: MouseEvent) => {
986
+ event.stopPropagation()
987
+
988
+ // Check if this was a drag operation (any mouse movement during drag)
989
+ const was_drag = drag_started
990
+ drag_started = false // Reset for next interaction
991
+ if (was_drag) return // Don't trigger click if this was a drag
992
+
993
+ const entry = find_entry_at_mouse(event)
994
+ if (entry) {
995
+ on_point_click?.(entry)
996
+ if (enable_click_selection) {
997
+ selected_entry = entry
998
+ if (enable_structure_preview) {
999
+ const structure = extract_structure_from_entry(entry)
1000
+ if (structure) {
1001
+ selected_structure = structure
1002
+ modal_place_right = helpers.calculate_modal_side(wrapper)
1003
+ modal_open = true
1004
+ }
1005
+ }
1006
+ }
1007
+ } else if (modal_open) close_structure_popup()
1008
+ }
1009
+
1010
+ function close_structure_popup() {
1011
+ modal_open = false
1012
+ selected_structure = null
1013
+ selected_entry = null
1014
+ }
1015
+
1016
+ const handle_double_click = (event: MouseEvent) => {
1017
+ const entry = find_entry_at_mouse(event)
1018
+ if (entry) {
1019
+ copy_entry_data(entry, {
1020
+ x: event.clientX,
1021
+ y: event.clientY,
1022
+ })
1023
+ }
1024
+ }
1025
+
1026
+ function render_once() {
1027
+ if (!frame_id) {
1028
+ frame_id = requestAnimationFrame(() => {
1029
+ render_frame()
1030
+ frame_id = 0
1031
+ })
1032
+ }
1033
+ }
1034
+
1035
+ function update_canvas_size() {
1036
+ if (!canvas) return
1037
+ const dpr = globalThis.devicePixelRatio || 1
1038
+ const container = canvas.parentElement
1039
+ const rect = container?.getBoundingClientRect()
1040
+ const [width, height] = rect ? [rect.width, rect.height] : [400, 400]
1041
+
1042
+ const new_width = Math.max(0, Math.round(width * dpr))
1043
+ const new_height = Math.max(0, Math.round(height * dpr))
1044
+ canvas_dims = { width, height, scale: Math.min(width, height) / 600 }
1045
+
1046
+ if (!ctx || canvas.width !== new_width || canvas.height !== new_height) {
1047
+ canvas.width = new_width
1048
+ canvas.height = new_height
1049
+ ctx = canvas.getContext(`2d`)
1050
+ if (ctx) {
1051
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0)
1052
+ ctx.imageSmoothingEnabled = true
1053
+ ctx.imageSmoothingQuality = `high`
1054
+ }
1055
+ }
1056
+ render_once()
1057
+ }
1058
+
1059
+ $effect(() => {
1060
+ if (!canvas) return
1061
+
1062
+ // Initial setup
1063
+ update_canvas_size()
1064
+
1065
+ // Watch for resize events - only update canvas, don't reset camera
1066
+ const resize_observer = new ResizeObserver(update_canvas_size)
1067
+
1068
+ const container = canvas.parentElement
1069
+ if (container) resize_observer.observe(container)
1070
+
1071
+ return () => { // Cleanup on unmount
1072
+ if (frame_id) cancelAnimationFrame(frame_id)
1073
+ resize_observer.disconnect()
1074
+ }
1075
+ })
1076
+
1077
+ // Fullscreen handling with camera reset
1078
+ let was_fullscreen = $state(fullscreen)
1079
+ $effect(() => {
1080
+ setup_fullscreen_effect(fullscreen, wrapper, (entering_fullscreen) => {
1081
+ if (entering_fullscreen !== was_fullscreen) {
1082
+ camera.center_x = 0
1083
+ camera.center_y = 20
1084
+ was_fullscreen = entering_fullscreen
1085
+ }
1086
+ })
1087
+ set_fullscreen_bg(wrapper, fullscreen, `--hull-4d-bg-fullscreen`)
1088
+ })
1089
+
1090
+ // Performance: Cache canvas dimensions and pre-compute sorted point projections
1091
+ let canvas_dims = $state({ width: 600, height: 600, scale: 1 })
1092
+ const formation_energy_min = $derived.by(() => {
1093
+ let min_energy = 0
1094
+ for (const entry of all_enriched_entries) {
1095
+ min_energy = Math.min(min_energy, entry.e_form_per_atom ?? 0)
1096
+ }
1097
+ return min_energy
1098
+ })
1099
+ const sorted_points_cache = $derived.by(() => {
1100
+ if (!canvas || visible_entries.length === 0) return []
1101
+ return visible_entries
1102
+ .map((entry) => ({
1103
+ entry,
1104
+ projected: project_3d_point(entry.x, entry.y, entry.z),
1105
+ }))
1106
+ .sort((a, b) => a.projected.depth - b.projected.depth)
1107
+ })
1108
+
1109
+ let style = $derived(
1110
+ `--hull-stable-color:${merged_config.colors?.stable || `#0072B2`};
1111
+ --hull-unstable-color:${merged_config.colors?.unstable || `#E69F00`};
1112
+ --hull-edge-color:${merged_config.colors?.edge || `var(--text-color, #212121)`};
1113
+ --hull-text-color:${
1114
+ merged_config.colors?.annotation || `var(--text-color, #212121)`
1115
+ }`,
1116
+ )
1117
+ </script>
1118
+
1119
+ <svelte:document
1120
+ onfullscreenchange={() => {
1121
+ fullscreen = Boolean(document.fullscreenElement)
1122
+ }}
1123
+ onmousemove={handle_mouse_move}
1124
+ onmouseup={() => [is_dragging, drag_started] = [false, false]}
1125
+ />
1126
+
1127
+ <div
1128
+ {...rest}
1129
+ class="convex-hull-4d {rest.class ?? ``}"
1130
+ class:dragover={drag_over}
1131
+ style={`${style}; ${rest.style ?? ``}`}
1132
+ data-has-selection={selected_entry !== null}
1133
+ data-has-hover={hover_data !== null}
1134
+ data-is-dragging={is_dragging}
1135
+ data-rotation-x={camera.rotation_x.toFixed(4)}
1136
+ data-rotation-y={camera.rotation_y.toFixed(4)}
1137
+ bind:this={wrapper}
1138
+ role="application"
1139
+ tabindex="-1"
1140
+ onkeydown={handle_keydown}
1141
+ ondrop={handle_file_drop}
1142
+ ondragover={(event) => {
1143
+ event.preventDefault()
1144
+ drag_over = true
1145
+ }}
1146
+ ondragleave={(event) => {
1147
+ event.preventDefault()
1148
+ drag_over = false
1149
+ }}
1150
+ aria-label="Convex hull visualization"
1151
+ >
1152
+ {@render children?.({
1153
+ stable_entries,
1154
+ unstable_entries,
1155
+ highlighted_entries,
1156
+ selected_entry,
1157
+ })}
1158
+ <h3 style="position: absolute; left: 1em; top: 1ex; margin: 0">
1159
+ {@html sanitize_html(merged_controls.title || phase_stats?.chemical_system || ``)}
1160
+ </h3>
1161
+
1162
+ <canvas
1163
+ bind:this={canvas}
1164
+ tabindex="0"
1165
+ aria-label={merged_controls.title || phase_stats?.chemical_system || `4D Convex Hull`}
1166
+ onmousedown={handle_mouse_down}
1167
+ onmousemove={handle_hover}
1168
+ onclick={handle_click}
1169
+ onkeydown={handle_keydown}
1170
+ ondblclick={handle_double_click}
1171
+ onwheel={handle_wheel}
1172
+ ></canvas>
1173
+
1174
+ {#if entries.length === 0}
1175
+ <Spinner
1176
+ text="Loading data..."
1177
+ style="position: absolute; inset: 0; display: flex; align-items: center; justify-content: center"
1178
+ />
1179
+ {/if}
1180
+
1181
+ <!-- Energy above hull Color Bar -->
1182
+ {#if color_mode === `energy` && plot_entries.length > 0}
1183
+ {@const hull_distances = plot_entries
1184
+ .map((entry) => entry.e_above_hull)
1185
+ .filter((val): val is number => typeof val === `number`)}
1186
+ {@const min_energy = hull_distances.length > 0 ? Math.min(...hull_distances) : 0}
1187
+ {@const max_energy = hull_distances.length > 0 ? Math.max(...hull_distances, 0.1) : 0.1}
1188
+ <ColorBar
1189
+ title="Energy above hull (eV/atom)"
1190
+ range={[min_energy, max_energy]}
1191
+ {color_scale}
1192
+ wrapper_style="position: absolute; bottom: 2em; left: 1em; width: 200px;"
1193
+ bar_style="height: 12px;"
1194
+ title_style="margin-bottom: 4px;"
1195
+ />
1196
+ {/if}
1197
+
1198
+ <!-- Control buttons (top-right corner like Structure.svelte) -->
1199
+ {#if controls_config.mode !== `never`}
1200
+ <section class="control-buttons {controls_config.class}">
1201
+ {#if controls_config.visible(`reset`)}
1202
+ <button
1203
+ type="button"
1204
+ onclick={reset_all}
1205
+ title="Reset camera view (R key)"
1206
+ class="reset-camera-btn"
1207
+ >
1208
+ <Icon icon="Reset" />
1209
+ </button>
1210
+ {/if}
1211
+
1212
+ {#if enable_info_pane && phase_stats && controls_config.visible(`info-pane`)}
1213
+ <ConvexHullInfoPane
1214
+ bind:pane_open={info_pane_open}
1215
+ {phase_stats}
1216
+ {stable_entries}
1217
+ {unstable_entries}
1218
+ {show_stable}
1219
+ {show_unstable}
1220
+ {max_hull_dist_show_phases}
1221
+ {max_hull_dist_show_labels}
1222
+ {label_threshold}
1223
+ toggle_props={{ class: `info-btn` }}
1224
+ />
1225
+ {/if}
1226
+
1227
+ {#if enable_fullscreen && controls_config.visible(`fullscreen`)}
1228
+ <button
1229
+ type="button"
1230
+ onclick={() => toggle_fullscreen(wrapper)}
1231
+ title="{fullscreen ? `Exit` : `Enter`} fullscreen"
1232
+ class="fullscreen-btn"
1233
+ >
1234
+ <Icon icon="{fullscreen ? `Exit` : ``}Fullscreen" />
1235
+ </button>
1236
+ {/if}
1237
+
1238
+ <!-- Legend controls pane -->
1239
+ {#if controls_config.visible(`controls`)}
1240
+ <ConvexHullControls
1241
+ bind:controls_open={legend_pane_open}
1242
+ bind:color_mode
1243
+ bind:color_scale
1244
+ bind:show_stable
1245
+ bind:show_unstable
1246
+ bind:show_stable_labels
1247
+ bind:show_unstable_labels
1248
+ bind:max_hull_dist_show_phases
1249
+ bind:max_hull_dist_show_labels
1250
+ {max_hull_dist_in_data}
1251
+ {stable_entries}
1252
+ {unstable_entries}
1253
+ {camera}
1254
+ {merged_controls}
1255
+ toggle_props={{ class: `legend-controls-btn` }}
1256
+ {show_hull_faces}
1257
+ on_hull_faces_change={(value: boolean) => show_hull_faces = value}
1258
+ {hull_face_color}
1259
+ on_hull_face_color_change={(value: string) => hull_face_color = value}
1260
+ {hull_face_opacity}
1261
+ on_hull_face_opacity_change={(value: number) => hull_face_opacity = value}
1262
+ {hull_face_color_mode}
1263
+ on_hull_face_color_mode_change={(value: HullFaceColorMode) =>
1264
+ hull_face_color_mode = value}
1265
+ bind:energy_source_mode
1266
+ {has_precomputed_e_form}
1267
+ {can_compute_e_form}
1268
+ {has_precomputed_hull}
1269
+ {can_compute_hull}
1270
+ />
1271
+ {/if}
1272
+ </section>
1273
+ {/if}
1274
+
1275
+ {#if has_temp_data && temperature !== undefined}
1276
+ <TemperatureSlider {available_temperatures} bind:temperature />
1277
+ {/if}
1278
+
1279
+ {#if gas_analysis.has_gas_dependent_elements && merged_gas_config}
1280
+ <GasPressureControls
1281
+ config={merged_gas_config}
1282
+ bind:pressures={gas_pressures}
1283
+ temperature={temperature ?? 300}
1284
+ />
1285
+ {/if}
1286
+
1287
+ <!-- Hover tooltip -->
1288
+ {#if hover_data}
1289
+ {@const { entry, position } = hover_data}
1290
+ {@const entry_highlight = is_highlighted(entry) ? merged_highlight_style : undefined}
1291
+ {@const tooltip_style =
1292
+ `z-index: ${CONVEX_HULL_STYLE.z_index.tooltip}; backdrop-filter: blur(4px);
1293
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);`}
1294
+ <PlotTooltip
1295
+ x={position.x}
1296
+ y={position.y}
1297
+ offset={{ x: 10, y: -10 }}
1298
+ bg_color={get_point_color(entry)}
1299
+ fixed
1300
+ style={tooltip_style}
1301
+ >
1302
+ <ConvexHullTooltip
1303
+ {entry}
1304
+ {polymorph_stats_map}
1305
+ highlight_style={entry_highlight}
1306
+ {tooltip}
1307
+ />
1308
+ </PlotTooltip>
1309
+ {/if}
1310
+
1311
+ <!-- Copy-to-clipboard feedback (double-click on point) -->
1312
+ <ClickFeedback bind:visible={copy_feedback.visible} position={copy_feedback.position} />
1313
+
1314
+ <!-- Drag over overlay -->
1315
+ <DragOverlay visible={drag_over} />
1316
+
1317
+ {#if modal_open && selected_structure}
1318
+ <StructurePopup
1319
+ structure={selected_structure}
1320
+ place_right={modal_place_right}
1321
+ stats={{
1322
+ id: selected_entry?.entry_id,
1323
+ e_above_hull: selected_entry?.e_above_hull,
1324
+ e_form: selected_entry?.e_form_per_atom,
1325
+ }}
1326
+ onclose={close_structure_popup}
1327
+ />
1328
+ {/if}
1329
+ </div>
1330
+
1331
+ <style>
1332
+ .convex-hull-4d {
1333
+ position: relative;
1334
+ container-type: size; /* enable cqh/cqw for responsive sizing */
1335
+ width: 100%;
1336
+ height: var(--hull-height, 500px);
1337
+ background: var(--hull-4d-bg, var(--hull-bg));
1338
+ border-radius: var(--hull-border-radius, var(--border-radius, 3pt));
1339
+ }
1340
+ .convex-hull-4d:fullscreen {
1341
+ border-radius: 0;
1342
+ background: var(--hull-4d-bg-fullscreen, var(--hull-4d-bg, var(--hull-bg)));
1343
+ overflow: hidden;
1344
+ }
1345
+ .convex-hull-4d.dragover {
1346
+ border: 2px dashed var(--accent-color, #1976d2);
1347
+ }
1348
+ canvas {
1349
+ width: 100%;
1350
+ height: 100%;
1351
+ cursor: grab;
1352
+ }
1353
+ canvas:active {
1354
+ cursor: grabbing;
1355
+ }
1356
+ .control-buttons {
1357
+ position: absolute;
1358
+ top: 1ex;
1359
+ right: 1ex;
1360
+ display: flex;
1361
+ gap: 8px;
1362
+ transition: opacity 0.2s ease-in-out;
1363
+ }
1364
+ .control-buttons.hover-visible {
1365
+ opacity: 0;
1366
+ pointer-events: none;
1367
+ }
1368
+ .convex-hull-4d:hover .control-buttons.hover-visible,
1369
+ .convex-hull-4d:focus-within .control-buttons.hover-visible {
1370
+ opacity: 1;
1371
+ pointer-events: auto;
1372
+ }
1373
+ .control-buttons.always-visible {
1374
+ opacity: 1;
1375
+ pointer-events: auto;
1376
+ }
1377
+ .control-buttons :global(.draggable-pane) {
1378
+ z-index: 1001 !important;
1379
+ }
1380
+ .control-buttons :global(button) {
1381
+ background: transparent;
1382
+ border: none;
1383
+ padding: 4px;
1384
+ cursor: pointer;
1385
+ border-radius: 3px;
1386
+ color: var(--text-color, currentColor);
1387
+ transition: background-color 0.2s;
1388
+ display: flex;
1389
+ font-size: clamp(0.85em, 2cqmin, 1.3em);
1390
+ }
1391
+ .control-buttons :global(button):hover {
1392
+ background-color: color-mix(in srgb, currentColor 8%, transparent);
1393
+ }
1394
+ </style>