matterviz 0.3.2 → 0.3.4

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 (281) hide show
  1. package/dist/EmptyState.svelte +10 -2
  2. package/dist/FilePicker.svelte +123 -82
  3. package/dist/Icon.svelte +18 -12
  4. package/dist/MillerIndexInput.svelte +27 -21
  5. package/dist/api/optimade.js +6 -6
  6. package/dist/app.css +216 -207
  7. package/dist/brillouin/BrillouinZone.svelte +292 -149
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +69 -42
  11. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte +275 -163
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  15. package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
  16. package/dist/brillouin/compute.js +11 -6
  17. package/dist/chempot-diagram/ChemPotDiagram.svelte +162 -27
  18. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +451 -281
  19. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2148 -1642
  20. package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -5
  21. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  22. package/dist/chempot-diagram/async-compute.svelte.js +77 -0
  23. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  24. package/dist/chempot-diagram/chempot-worker.js +11 -0
  25. package/dist/chempot-diagram/color.js +1 -2
  26. package/dist/chempot-diagram/compute.d.ts +10 -0
  27. package/dist/chempot-diagram/compute.js +250 -88
  28. package/dist/chempot-diagram/index.d.ts +2 -1
  29. package/dist/chempot-diagram/index.js +2 -1
  30. package/dist/chempot-diagram/temperature.js +8 -9
  31. package/dist/chempot-diagram/types.d.ts +3 -0
  32. package/dist/chempot-diagram/types.js +1 -0
  33. package/dist/colors/index.d.ts +1 -1
  34. package/dist/colors/index.js +5 -3
  35. package/dist/composition/BarChart.svelte +128 -55
  36. package/dist/composition/BubbleChart.svelte +102 -49
  37. package/dist/composition/Composition.svelte +100 -79
  38. package/dist/composition/Formula.svelte +108 -62
  39. package/dist/composition/FormulaFilter.svelte +665 -537
  40. package/dist/composition/PieChart.svelte +183 -108
  41. package/dist/composition/format.d.ts +5 -0
  42. package/dist/composition/format.js +20 -3
  43. package/dist/composition/parse.js +14 -9
  44. package/dist/convex-hull/ConvexHull.svelte +93 -40
  45. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  46. package/dist/convex-hull/ConvexHull2D.svelte +549 -360
  47. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  48. package/dist/convex-hull/ConvexHull3D.svelte +1296 -827
  49. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  50. package/dist/convex-hull/ConvexHull4D.svelte +1004 -688
  51. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  52. package/dist/convex-hull/ConvexHullControls.svelte +115 -28
  53. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +1 -1
  54. package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
  55. package/dist/convex-hull/ConvexHullStats.svelte +425 -328
  56. package/dist/convex-hull/ConvexHullTooltip.svelte +40 -16
  57. package/dist/convex-hull/GasPressureControls.svelte +104 -61
  58. package/dist/convex-hull/StructurePopup.svelte +25 -4
  59. package/dist/convex-hull/TemperatureSlider.svelte +45 -25
  60. package/dist/convex-hull/barycentric-coords.js +13 -7
  61. package/dist/convex-hull/demo-temperature.js +8 -4
  62. package/dist/convex-hull/gas-thermodynamics.js +17 -12
  63. package/dist/convex-hull/helpers.d.ts +9 -0
  64. package/dist/convex-hull/helpers.js +77 -34
  65. package/dist/convex-hull/thermodynamics.js +61 -56
  66. package/dist/convex-hull/types.d.ts +9 -14
  67. package/dist/convex-hull/types.js +0 -17
  68. package/dist/coordination/CoordinationBarPlot.svelte +227 -154
  69. package/dist/element/BohrAtom.svelte +55 -12
  70. package/dist/element/ElementHeading.svelte +7 -2
  71. package/dist/element/ElementPhoto.svelte +15 -9
  72. package/dist/element/ElementStats.svelte +10 -4
  73. package/dist/element/ElementTile.svelte +137 -73
  74. package/dist/element/Nucleus.svelte +39 -11
  75. package/dist/element/data.js +1 -1
  76. package/dist/feedback/ClickFeedback.svelte +16 -5
  77. package/dist/feedback/DragOverlay.svelte +10 -2
  78. package/dist/feedback/Spinner.svelte +4 -2
  79. package/dist/feedback/StatusMessage.svelte +8 -2
  80. package/dist/fermi-surface/FermiSlice.svelte +118 -88
  81. package/dist/fermi-surface/FermiSurface.svelte +328 -187
  82. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  83. package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
  84. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  85. package/dist/fermi-surface/FermiSurfaceScene.svelte +535 -342
  86. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  87. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
  88. package/dist/fermi-surface/compute.js +16 -20
  89. package/dist/fermi-surface/parse.js +24 -14
  90. package/dist/fermi-surface/symmetry.js +2 -7
  91. package/dist/fermi-surface/types.d.ts +3 -5
  92. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1019 -765
  93. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +1 -1
  94. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +76 -22
  95. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +2 -3
  96. package/dist/icons.js +47 -0
  97. package/dist/index.d.ts +2 -1
  98. package/dist/index.js +2 -1
  99. package/dist/io/decompress.js +1 -1
  100. package/dist/io/export.d.ts +3 -0
  101. package/dist/io/export.js +129 -143
  102. package/dist/io/is-binary.js +2 -3
  103. package/dist/io/url-drop.js +1 -2
  104. package/dist/isosurface/Isosurface.svelte +202 -148
  105. package/dist/isosurface/IsosurfaceControls.svelte +46 -28
  106. package/dist/isosurface/parse.js +34 -29
  107. package/dist/isosurface/slice.js +5 -10
  108. package/dist/isosurface/types.d.ts +2 -1
  109. package/dist/isosurface/types.js +61 -12
  110. package/dist/labels.js +11 -8
  111. package/dist/layout/FullscreenToggle.svelte +11 -2
  112. package/dist/layout/InfoCard.svelte +38 -6
  113. package/dist/layout/InfoTag.svelte +63 -32
  114. package/dist/layout/PropertyFilter.svelte +82 -37
  115. package/dist/layout/SettingsSection.svelte +85 -55
  116. package/dist/layout/SubpageGrid.svelte +10 -2
  117. package/dist/layout/json-tree/JsonNode.svelte +183 -138
  118. package/dist/layout/json-tree/JsonTree.svelte +499 -413
  119. package/dist/layout/json-tree/JsonValue.svelte +127 -99
  120. package/dist/layout/json-tree/utils.js +4 -2
  121. package/dist/marching-cubes.js +25 -2
  122. package/dist/math.d.ts +13 -17
  123. package/dist/math.js +133 -67
  124. package/dist/overlays/ContextMenu.svelte +65 -40
  125. package/dist/overlays/DraggablePane.svelte +211 -139
  126. package/dist/periodic-table/PeriodicTable.svelte +278 -145
  127. package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
  128. package/dist/periodic-table/PropertySelect.svelte +25 -7
  129. package/dist/periodic-table/TableInset.svelte +8 -3
  130. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +446 -309
  131. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  132. package/dist/phase-diagram/PhaseDiagramControls.svelte +102 -43
  133. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  134. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +63 -40
  135. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +71 -28
  136. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +1 -1
  137. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +158 -101
  138. package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
  139. package/dist/phase-diagram/build-diagram.js +9 -9
  140. package/dist/phase-diagram/colors.js +1 -3
  141. package/dist/phase-diagram/parse.js +10 -9
  142. package/dist/phase-diagram/svg-to-diagram.js +53 -49
  143. package/dist/phase-diagram/utils.d.ts +1 -0
  144. package/dist/phase-diagram/utils.js +80 -25
  145. package/dist/plot/AxisLabel.svelte +28 -3
  146. package/dist/plot/BarPlot.svelte +1182 -734
  147. package/dist/plot/BarPlot.svelte.d.ts +2 -2
  148. package/dist/plot/BarPlotControls.svelte +31 -5
  149. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  150. package/dist/plot/ColorBar.svelte +479 -329
  151. package/dist/plot/ColorScaleSelect.svelte +27 -6
  152. package/dist/plot/ElementScatter.svelte +36 -15
  153. package/dist/plot/FillArea.svelte +152 -95
  154. package/dist/plot/Histogram.svelte +934 -571
  155. package/dist/plot/Histogram.svelte.d.ts +1 -1
  156. package/dist/plot/HistogramControls.svelte +53 -9
  157. package/dist/plot/HistogramControls.svelte.d.ts +1 -1
  158. package/dist/plot/InteractiveAxisLabel.svelte +34 -11
  159. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  160. package/dist/plot/Line.svelte +63 -28
  161. package/dist/plot/PlotControls.svelte +157 -114
  162. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  163. package/dist/plot/PlotLegend.svelte +174 -91
  164. package/dist/plot/PlotTooltip.svelte +45 -6
  165. package/dist/plot/PortalSelect.svelte +175 -147
  166. package/dist/plot/ReferenceLine.svelte +76 -22
  167. package/dist/plot/ReferenceLine3D.svelte +132 -107
  168. package/dist/plot/ReferencePlane.svelte +146 -121
  169. package/dist/plot/ScatterPlot.svelte +1681 -1091
  170. package/dist/plot/ScatterPlot.svelte.d.ts +2 -2
  171. package/dist/plot/ScatterPlot3D.svelte +256 -131
  172. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  173. package/dist/plot/ScatterPlot3DControls.svelte +113 -63
  174. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
  175. package/dist/plot/ScatterPlot3DScene.svelte +608 -403
  176. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  177. package/dist/plot/ScatterPlotControls.svelte +65 -25
  178. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  179. package/dist/plot/ScatterPoint.svelte +98 -26
  180. package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
  181. package/dist/plot/SpacegroupBarPlot.svelte +142 -85
  182. package/dist/plot/Surface3D.svelte +159 -108
  183. package/dist/plot/ZeroLines.svelte +55 -3
  184. package/dist/plot/ZoomRect.svelte +4 -2
  185. package/dist/plot/axis-utils.js +1 -3
  186. package/dist/plot/data-cleaning.js +12 -28
  187. package/dist/plot/data-transform.js +2 -1
  188. package/dist/plot/fill-utils.js +2 -0
  189. package/dist/plot/layout.d.ts +4 -1
  190. package/dist/plot/layout.js +33 -14
  191. package/dist/plot/reference-line.d.ts +2 -2
  192. package/dist/plot/reference-line.js +7 -5
  193. package/dist/plot/scales.js +24 -36
  194. package/dist/plot/types.d.ts +11 -23
  195. package/dist/plot/types.js +6 -11
  196. package/dist/plot/utils/label-placement.d.ts +32 -15
  197. package/dist/plot/utils/label-placement.js +227 -66
  198. package/dist/plot/utils/series-visibility.js +2 -3
  199. package/dist/rdf/RdfPlot.svelte +143 -91
  200. package/dist/rdf/calc-rdf.js +4 -5
  201. package/dist/sanitize.d.ts +4 -0
  202. package/dist/sanitize.js +107 -0
  203. package/dist/settings.d.ts +18 -6
  204. package/dist/settings.js +46 -16
  205. package/dist/spectral/Bands.svelte +632 -453
  206. package/dist/spectral/BandsAndDos.svelte +90 -49
  207. package/dist/spectral/BrillouinBandsDos.svelte +151 -93
  208. package/dist/spectral/Dos.svelte +389 -258
  209. package/dist/spectral/helpers.js +55 -43
  210. package/dist/state.svelte.d.ts +1 -1
  211. package/dist/state.svelte.js +3 -2
  212. package/dist/structure/Arrow.svelte +59 -20
  213. package/dist/structure/AtomLegend.svelte +215 -134
  214. package/dist/structure/Bond.svelte +73 -47
  215. package/dist/structure/CanvasTooltip.svelte +10 -2
  216. package/dist/structure/CellSelect.svelte +72 -45
  217. package/dist/structure/Cylinder.svelte +33 -17
  218. package/dist/structure/Lattice.svelte +88 -33
  219. package/dist/structure/Structure.svelte +1063 -797
  220. package/dist/structure/Structure.svelte.d.ts +1 -1
  221. package/dist/structure/StructureControls.svelte +349 -118
  222. package/dist/structure/StructureExportPane.svelte +124 -89
  223. package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
  224. package/dist/structure/StructureInfoPane.svelte +304 -237
  225. package/dist/structure/StructureScene.svelte +879 -443
  226. package/dist/structure/StructureScene.svelte.d.ts +15 -7
  227. package/dist/structure/atom-properties.js +8 -8
  228. package/dist/structure/bonding.js +6 -7
  229. package/dist/structure/export.js +14 -29
  230. package/dist/structure/ferrox-wasm.js +1 -1
  231. package/dist/structure/index.d.ts +13 -3
  232. package/dist/structure/index.js +83 -23
  233. package/dist/structure/measure.d.ts +2 -2
  234. package/dist/structure/measure.js +4 -44
  235. package/dist/structure/parse.js +113 -141
  236. package/dist/structure/partial-occupancy.js +7 -10
  237. package/dist/structure/pbc.d.ts +1 -0
  238. package/dist/structure/pbc.js +16 -6
  239. package/dist/structure/supercell.d.ts +2 -2
  240. package/dist/structure/supercell.js +12 -22
  241. package/dist/structure/validation.js +1 -2
  242. package/dist/symmetry/SymmetryStats.svelte +84 -41
  243. package/dist/symmetry/WyckoffTable.svelte +26 -6
  244. package/dist/symmetry/cell-transform.js +5 -3
  245. package/dist/symmetry/index.js +8 -7
  246. package/dist/symmetry/spacegroups.js +148 -148
  247. package/dist/table/HeatmapTable.svelte +790 -554
  248. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  249. package/dist/table/ToggleMenu.svelte +125 -92
  250. package/dist/table/index.js +2 -4
  251. package/dist/theme/ThemeControl.svelte +21 -12
  252. package/dist/time.js +4 -1
  253. package/dist/tooltip/TooltipContent.svelte +33 -8
  254. package/dist/trajectory/Trajectory.svelte +758 -558
  255. package/dist/trajectory/TrajectoryError.svelte +14 -3
  256. package/dist/trajectory/TrajectoryExportPane.svelte +137 -83
  257. package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
  258. package/dist/trajectory/extract.js +10 -26
  259. package/dist/trajectory/format-detect.js +5 -5
  260. package/dist/trajectory/frame-reader.d.ts +1 -1
  261. package/dist/trajectory/frame-reader.js +5 -12
  262. package/dist/trajectory/helpers.d.ts +0 -1
  263. package/dist/trajectory/helpers.js +2 -17
  264. package/dist/trajectory/index.js +14 -12
  265. package/dist/trajectory/parse/ase.js +5 -4
  266. package/dist/trajectory/parse/hdf5.js +26 -18
  267. package/dist/trajectory/parse/index.js +13 -18
  268. package/dist/trajectory/parse/lammps.js +17 -7
  269. package/dist/trajectory/parse/vasp.js +5 -2
  270. package/dist/trajectory/parse/xyz.js +8 -7
  271. package/dist/trajectory/plotting.js +13 -8
  272. package/dist/utils.d.ts +1 -0
  273. package/dist/utils.js +13 -0
  274. package/dist/xrd/XrdPlot.svelte +337 -247
  275. package/dist/xrd/broadening.js +14 -9
  276. package/dist/xrd/calc-xrd.js +12 -18
  277. package/dist/xrd/parse.d.ts +1 -1
  278. package/dist/xrd/parse.js +17 -17
  279. package/package.json +99 -103
  280. package/readme.md +1 -1
  281. /package/dist/theme/{themes.js → themes.mjs} +0 -0
@@ -1,175 +1,317 @@
1
- <script lang="ts">import { normalize_show_controls } from '../controls';
2
- import EmptyState from '../EmptyState.svelte';
3
- import { StatusMessage } from '../feedback';
4
- import Spinner from '../feedback/Spinner.svelte';
5
- import Icon from '../Icon.svelte';
6
- import { create_file_drop_handler, load_from_url } from '../io';
7
- import { set_fullscreen_bg, toggle_fullscreen } from '../layout';
8
- import { PlotTooltip } from '../plot';
9
- import { DEFAULTS } from '../settings';
10
- import { parse_any_structure } from '../structure/parse';
11
- import { analyze_structure_symmetry } from '../symmetry';
12
- import { Canvas } from '@threlte/core';
13
- import { untrack } from 'svelte';
14
- import { tooltip } from 'svelte-multiselect/attachments';
15
- import BrillouinZoneControls from './BrillouinZoneControls.svelte';
16
- import BrillouinZoneExportPane from './BrillouinZoneExportPane.svelte';
17
- import BrillouinZoneInfoPane from './BrillouinZoneInfoPane.svelte';
18
- import BrillouinZoneScene from './BrillouinZoneScene.svelte';
19
- import BrillouinZoneTooltip from './BrillouinZoneTooltip.svelte';
20
- import { compute_brillouin_zone, compute_irreducible_bz, extract_point_group_from_operations, reciprocal_lattice, } from './compute';
21
- let { structure = $bindable(), bz_order = $bindable(1), bz_data = $bindable(), controls_open = $bindable(false), info_pane_open = $bindable(false), surface_color = $bindable(`#4488ff`), surface_opacity = $bindable(0.3), edge_color = $bindable(`#000000`), edge_width = $bindable(0.05), show_vectors = $bindable(true), vector_scale = $bindable(1.0), camera_projection = $bindable(`perspective`),
22
- // Irreducible BZ options
23
- show_ibz = $bindable(false), ibz_color = $bindable(`#ff8844`), ibz_opacity = $bindable(0.5), ibz_data = $bindable(null), show_controls, fullscreen = $bindable(false), wrapper = $bindable(), width = $bindable(0), height = $bindable(0), hovered = $bindable(false), dragover = $bindable(false), allow_file_drop = true, png_dpi = $bindable(150), fullscreen_toggle = DEFAULTS.structure.fullscreen_toggle, data_url, structure_string, on_file_drop, spinner_props = {}, loading = $bindable(false), error_msg = $bindable(), k_path_points = [], k_path_labels = [], hovered_k_point = null, hovered_qpoint_index = null, children, tooltip_config, on_file_load, on_error, on_fullscreen_change, on_hover, ...rest } = $props();
24
- let scene = $state(undefined);
25
- let camera = $state(undefined);
26
- let export_pane_open = $state(false);
27
- let current_filename = $state(undefined);
28
- let hover_data = $state(null);
29
- // Call on_hover callback when hover_data changes
30
- $effect(() => {
31
- on_hover?.(hover_data);
32
- });
33
- // Normalize show_controls prop into consistent config
34
- let controls_config = $derived(normalize_show_controls(show_controls));
35
- // Parse and load structure from content
36
- function parse_structure(content, filename) {
1
+ <script lang="ts">
2
+ import type { ShowControlsProp } from '../controls'
3
+ import { normalize_show_controls } from '../controls'
4
+ import EmptyState from '../EmptyState.svelte'
5
+ import { StatusMessage } from '../feedback'
6
+ import Spinner from '../feedback/Spinner.svelte'
7
+ import Icon from '../Icon.svelte'
8
+ import { create_file_drop_handler, load_from_url } from '../io'
9
+ import { set_fullscreen_bg, toggle_fullscreen } from '../layout'
10
+ import type { Vec3 } from '../math'
11
+ import { PlotTooltip } from '../plot'
12
+ import { type CameraProjection, DEFAULTS } from '../settings'
13
+ import type { Crystal } from '../structure'
14
+ import { parse_any_structure } from '../structure/parse'
15
+ import { analyze_structure_symmetry } from '../symmetry'
16
+ import { Canvas } from '@threlte/core'
17
+ import type { ComponentProps, Snippet } from 'svelte'
18
+ import { untrack } from 'svelte'
19
+ import { tooltip } from 'svelte-multiselect/attachments'
20
+ import type { HTMLAttributes } from 'svelte/elements'
21
+ import BrillouinZoneControls from './BrillouinZoneControls.svelte'
22
+ import BrillouinZoneExportPane from './BrillouinZoneExportPane.svelte'
23
+ import BrillouinZoneInfoPane from './BrillouinZoneInfoPane.svelte'
24
+ import BrillouinZoneScene from './BrillouinZoneScene.svelte'
25
+ import BrillouinZoneTooltip from './BrillouinZoneTooltip.svelte'
26
+ import {
27
+ compute_brillouin_zone,
28
+ compute_irreducible_bz,
29
+ extract_point_group_from_operations,
30
+ reciprocal_lattice,
31
+ } from './compute'
32
+ import type {
33
+ BrillouinZoneData,
34
+ BZHoverData,
35
+ BZTooltipProp,
36
+ IrreducibleBZData,
37
+ } from './types'
38
+
39
+ type BZHandlerData = {
40
+ structure?: Crystal
41
+ bz_data?: BrillouinZoneData
42
+ bz_order?: number
43
+ filename?: string
44
+ file_size?: number
45
+ error_msg?: string
46
+ fullscreen?: boolean
47
+ }
48
+ let {
49
+ structure = $bindable(),
50
+ bz_order = $bindable(1),
51
+ bz_data = $bindable(),
52
+ controls_open = $bindable(false),
53
+ info_pane_open = $bindable(false),
54
+ surface_color = $bindable(`#4488ff`),
55
+ surface_opacity = $bindable(0.3),
56
+ edge_color = $bindable(`#000000`),
57
+ edge_width = $bindable(0.05),
58
+ show_vectors = $bindable(true),
59
+ vector_scale = $bindable(1.0),
60
+ camera_projection = $bindable(`perspective`),
61
+ // Irreducible BZ options
62
+ show_ibz = $bindable(false),
63
+ ibz_color = $bindable(`#ff8844`),
64
+ ibz_opacity = $bindable(0.5),
65
+ ibz_data = $bindable<IrreducibleBZData | null>(null),
66
+ show_controls,
67
+ fullscreen = $bindable(false),
68
+ wrapper = $bindable(),
69
+ width = $bindable(0),
70
+ height = $bindable(0),
71
+ hovered = $bindable(false),
72
+ dragover = $bindable(false),
73
+ allow_file_drop = true,
74
+ png_dpi = $bindable(150),
75
+ fullscreen_toggle = DEFAULTS.structure.fullscreen_toggle,
76
+ data_url,
77
+ structure_string,
78
+ on_file_drop,
79
+ spinner_props = {},
80
+ loading = $bindable(false),
81
+ error_msg = $bindable(),
82
+ k_path_points = [],
83
+ k_path_labels = [],
84
+ hovered_k_point = null,
85
+ hovered_qpoint_index = null,
86
+ children,
87
+ tooltip_config,
88
+ on_file_load,
89
+ on_error,
90
+ on_fullscreen_change,
91
+ on_hover,
92
+ ...rest
93
+ }:
94
+ & {
95
+ structure?: Crystal
96
+ bz_order?: number
97
+ bz_data?: BrillouinZoneData
98
+ controls_open?: boolean
99
+ info_pane_open?: boolean
100
+ surface_color?: string
101
+ surface_opacity?: number
102
+ edge_color?: string
103
+ edge_width?: number
104
+ show_vectors?: boolean
105
+ vector_scale?: number
106
+ camera_projection?: CameraProjection
107
+ // Irreducible BZ options
108
+ show_ibz?: boolean
109
+ ibz_color?: string
110
+ ibz_opacity?: number
111
+ ibz_data?: IrreducibleBZData | null
112
+ /**
113
+ * Controls visibility configuration.
114
+ * - 'always': controls always visible
115
+ * - 'hover': controls visible on component hover (default)
116
+ * - 'never': controls never visible
117
+ * - object: { mode, hidden, style } for fine-grained control
118
+ *
119
+ * Control names: 'filename', 'fullscreen', 'info-pane', 'export-pane', 'controls'
120
+ */
121
+ show_controls?: ShowControlsProp
122
+ fullscreen?: boolean
123
+ width?: number
124
+ height?: number
125
+ wrapper?: HTMLDivElement
126
+ png_dpi?: number
127
+ hovered?: boolean
128
+ dragover?: boolean
129
+ allow_file_drop?: boolean
130
+ fullscreen_toggle?: Snippet<[{ fullscreen: boolean }]> | boolean
131
+ data_url?: string
132
+ on_file_drop?: (content: string | ArrayBuffer, filename: string) => void
133
+ spinner_props?: ComponentProps<typeof Spinner>
134
+ loading?: boolean
135
+ error_msg?: string
136
+ structure_string?: string
137
+ // K-path points in Cartesian reciprocal space coordinates (not fractional coords)
138
+ // Should be computed using the reciprocal lattice matrix (includes 2π factor)
139
+ k_path_points?: Vec3[]
140
+ // K-path labels with positions in Cartesian reciprocal space coordinates
141
+ // Each position should match a corresponding point in k_path_points
142
+ k_path_labels?: { position: Vec3; label: string | null }[]
143
+ // Currently hovered k-point in Cartesian reciprocal space coordinates
144
+ hovered_k_point?: Vec3 | null
145
+ // Index of the currently hovered q-point in the band structure
146
+ hovered_qpoint_index?: number | null
147
+ children?: Snippet<
148
+ [{ structure?: Crystal; bz_data?: BrillouinZoneData }]
149
+ >
150
+ tooltip_config?: BZTooltipProp
151
+ on_file_load?: (data: BZHandlerData) => void
152
+ on_error?: (data: BZHandlerData) => void
153
+ on_fullscreen_change?: (data: BZHandlerData) => void
154
+ on_hover?: (data: BZHoverData | null) => void
155
+ }
156
+ & HTMLAttributes<HTMLDivElement> = $props()
157
+
158
+ let scene = $state(undefined)
159
+ let camera = $state(undefined)
160
+ let export_pane_open = $state(false)
161
+ let current_filename = $state<string | undefined>(undefined)
162
+ let hover_data = $state<BZHoverData | null>(null)
163
+
164
+ // Call on_hover callback when hover_data changes
165
+ $effect(() => {
166
+ on_hover?.(hover_data)
167
+ })
168
+
169
+ // Normalize show_controls prop into consistent config
170
+ let controls_config = $derived(normalize_show_controls(show_controls))
171
+
172
+ // Parse and load structure from content
173
+ function parse_structure(content: string | ArrayBuffer, filename: string) {
37
174
  const text = content instanceof ArrayBuffer
38
- ? new TextDecoder().decode(content)
39
- : content;
40
- const parsed = parse_any_structure(text, filename);
41
- if (!parsed)
42
- throw new Error(`Failed to parse structure from ${filename}`);
43
- structure = parsed;
44
- current_filename = filename;
45
- const file_size = new Blob([content]).size;
46
- on_file_load?.({ structure, bz_data, bz_order, filename, file_size });
47
- }
48
- // Load with error handling
49
- function safe_parse(content, filename) {
175
+ ? new TextDecoder().decode(content)
176
+ : content
177
+ const parsed = parse_any_structure(text, filename)
178
+ if (!parsed) throw new Error(`Failed to parse structure from ${filename}`)
179
+
180
+ structure = parsed as Crystal
181
+ current_filename = filename
182
+ const file_size = new Blob([content]).size
183
+ on_file_load?.({ structure, bz_data, bz_order, filename, file_size })
184
+ }
185
+
186
+ // Load with error handling
187
+ function safe_parse(content: string | ArrayBuffer, filename: string) {
50
188
  try {
51
- parse_structure(content, filename);
189
+ parse_structure(content, filename)
190
+ } catch (err) {
191
+ error_msg = `Failed to parse ${filename}: ${
192
+ err instanceof Error ? err.message : err
193
+ }`
194
+ on_error?.({ error_msg, filename })
52
195
  }
53
- catch (err) {
54
- error_msg = `Failed to parse ${filename}: ${err instanceof Error ? err.message : err}`;
55
- on_error?.({ error_msg, filename });
56
- }
57
- }
58
- // Compute BZ when structure/order changes
59
- $effect(() => {
196
+ }
197
+
198
+ // Compute BZ when structure/order changes
199
+ $effect(() => {
60
200
  // Skip if bz_data was already provided externally (has valid vertices)
61
- if (bz_data?.vertices?.length)
62
- return;
201
+ if (bz_data?.vertices?.length) return
202
+
63
203
  if (!structure || !(`lattice` in structure) || !structure.lattice) {
64
- bz_data = undefined;
65
- return;
204
+ bz_data = undefined
205
+ return
66
206
  }
207
+
67
208
  try {
68
- const k_lattice = reciprocal_lattice(structure.lattice.matrix);
69
- // Ensure bz_order is 1, 2, or 3
70
- const valid_order = Math.min(Math.max(1, bz_order), 3);
71
- bz_data = compute_brillouin_zone(k_lattice, valid_order);
72
- }
73
- catch (err) {
74
- const msg = err instanceof Error ? err.message : String(err);
75
- error_msg = `BZ computation failed: ${msg}`;
76
- bz_data = undefined;
77
- untrack(() => on_error?.({ error_msg, structure, bz_order }));
209
+ const k_lattice = reciprocal_lattice(structure.lattice.matrix)
210
+ // Ensure bz_order is 1, 2, or 3
211
+ const valid_order = Math.min(Math.max(1, bz_order), 3) as 1 | 2 | 3
212
+ bz_data = compute_brillouin_zone(k_lattice, valid_order)
213
+ } catch (err) {
214
+ const msg = err instanceof Error ? err.message : String(err)
215
+ error_msg = `BZ computation failed: ${msg}`
216
+ bz_data = undefined
217
+ untrack(() => on_error?.({ error_msg, structure, bz_order }))
78
218
  }
79
- });
80
- // Compute IBZ when show_ibz is enabled and structure changes
81
- $effect(() => {
219
+ })
220
+
221
+ // Compute IBZ when show_ibz is enabled and structure changes
222
+ $effect(() => {
82
223
  if (!show_ibz || !bz_data || !structure?.lattice) {
83
- ibz_data = null;
84
- return;
224
+ ibz_data = null
225
+ return
85
226
  }
86
- let stale = false;
87
- const captured_bz = bz_data;
227
+
228
+ let stale = false
229
+ const captured_bz = bz_data
230
+
88
231
  analyze_structure_symmetry(structure, {})
89
- .then((sym_data) => {
90
- if (stale)
91
- return;
92
- const point_group_ops = extract_point_group_from_operations(sym_data.operations);
93
- ibz_data = compute_irreducible_bz(captured_bz, point_group_ops);
94
- })
95
- .catch((err) => {
96
- if (stale)
97
- return;
98
- console.warn(`IBZ computation failed:`, err);
99
- ibz_data = null;
100
- });
232
+ .then((sym_data) => {
233
+ if (stale) return
234
+ const point_group_ops = extract_point_group_from_operations(
235
+ sym_data.operations,
236
+ )
237
+ ibz_data = compute_irreducible_bz(captured_bz, point_group_ops)
238
+ })
239
+ .catch((err) => {
240
+ if (stale) return
241
+ console.warn(`IBZ computation failed:`, err)
242
+ ibz_data = null
243
+ })
244
+
101
245
  return () => {
102
- stale = true;
103
- };
104
- });
105
- // Load structure from URL or string
106
- $effect(() => {
107
- const handle_error = (err, source) => {
108
- error_msg = err instanceof Error ? err.message : String(err);
109
- on_error?.({ error_msg, filename: source });
110
- };
246
+ stale = true
247
+ }
248
+ })
249
+
250
+ // Load structure from URL or string
251
+ $effect(() => {
252
+ const handle_error = (err: unknown, source: string) => {
253
+ error_msg = err instanceof Error ? err.message : String(err)
254
+ on_error?.({ error_msg, filename: source })
255
+ }
256
+
111
257
  if (data_url && !structure) {
112
- loading = true;
113
- error_msg = undefined;
114
- load_from_url(data_url, (content, filename) => on_file_drop
258
+ loading = true
259
+ error_msg = undefined
260
+ load_from_url(
261
+ data_url,
262
+ (content, filename) =>
263
+ on_file_drop
115
264
  ? on_file_drop(content, filename)
116
- : safe_parse(content, filename))
117
- .catch((err) => handle_error(err, data_url))
118
- .finally(() => (loading = false));
265
+ : safe_parse(content, filename),
266
+ )
267
+ .catch((err) => handle_error(err, data_url))
268
+ .finally(() => (loading = false))
269
+ } else if (structure_string && !data_url) {
270
+ loading = true
271
+ error_msg = undefined
272
+ try {
273
+ safe_parse(structure_string, `string`)
274
+ } catch (err) {
275
+ handle_error(err, `string`)
276
+ } finally {
277
+ loading = false
278
+ }
119
279
  }
120
- else if (structure_string && !data_url) {
121
- loading = true;
122
- error_msg = undefined;
123
- try {
124
- safe_parse(structure_string, `string`);
125
- }
126
- catch (err) {
127
- handle_error(err, `string`);
128
- }
129
- finally {
130
- loading = false;
131
- }
132
- }
133
- });
134
- const handle_file_drop = create_file_drop_handler({
280
+ })
281
+
282
+ const handle_file_drop = create_file_drop_handler({
135
283
  allow: () => allow_file_drop,
136
284
  on_drop: (content, filename) => (on_file_drop || safe_parse)(content, filename),
137
285
  on_error: (msg) => {
138
- error_msg = msg;
139
- on_error?.({ error_msg: msg });
286
+ error_msg = msg
287
+ on_error?.({ error_msg: msg })
140
288
  },
141
289
  set_loading: (val) => {
142
- loading = val;
143
- if (val)
144
- [error_msg, dragover] = [undefined, false];
290
+ loading = val
291
+ if (val) [error_msg, dragover] = [undefined, false]
145
292
  },
146
- });
147
- function onkeydown(event) {
148
- const target = event.target;
149
- if (target.tagName === `INPUT` || target.tagName === `TEXTAREA`)
150
- return;
151
- if (event.key === `f` && fullscreen_toggle)
152
- toggle_fullscreen(wrapper);
153
- else if (event.key === `i`)
154
- info_pane_open = !info_pane_open;
293
+ })
294
+
295
+ function onkeydown(event: KeyboardEvent) {
296
+ const target = event.target as HTMLElement
297
+ if (target.tagName === `INPUT` || target.tagName === `TEXTAREA`) return
298
+
299
+ if (event.key === `f` && fullscreen_toggle) toggle_fullscreen(wrapper)
300
+ else if (event.key === `i`) info_pane_open = !info_pane_open
155
301
  else if (event.key === `Escape`) {
156
- if (info_pane_open)
157
- info_pane_open = false;
158
- else
159
- controls_open = false;
302
+ if (info_pane_open) info_pane_open = false
303
+ else controls_open = false
160
304
  }
161
- }
162
- $effect(() => {
163
- if (typeof window === `undefined`)
164
- return;
165
- const fs_el = document.fullscreenElement;
305
+ }
306
+
307
+ $effect(() => { // fullscreen and background
308
+ if (typeof window === `undefined`) return
309
+ const fs_el = document.fullscreenElement
166
310
  if (fullscreen && fs_el !== wrapper && wrapper) {
167
- wrapper.requestFullscreen().catch(console.error);
168
- }
169
- else if (!fullscreen && fs_el === wrapper)
170
- document.exitFullscreen();
171
- set_fullscreen_bg(wrapper, fullscreen, `--bz-bg-fullscreen`);
172
- });
311
+ wrapper.requestFullscreen().catch(console.error)
312
+ } else if (!fullscreen && fs_el === wrapper) document.exitFullscreen()
313
+ set_fullscreen_bg(wrapper, fullscreen, `--bz-bg-fullscreen`)
314
+ })
173
315
  </script>
174
316
 
175
317
  <svelte:document
@@ -367,7 +509,8 @@ $effect(() => {
367
509
  pointer-events: auto;
368
510
  }
369
511
  /* Mode: hover - controls visible on component hover */
370
- .brillouin-zone:hover section.control-buttons.hover-visible {
512
+ .brillouin-zone:hover section.control-buttons.hover-visible,
513
+ .brillouin-zone:focus-within section.control-buttons.hover-visible {
371
514
  opacity: 1;
372
515
  pointer-events: auto;
373
516
  }
@@ -78,6 +78,6 @@ type $$ComponentProps = {
78
78
  on_fullscreen_change?: (data: BZHandlerData) => void;
79
79
  on_hover?: (data: BZHoverData | null) => void;
80
80
  } & HTMLAttributes<HTMLDivElement>;
81
- declare const BrillouinZone: import("svelte").Component<$$ComponentProps, {}, "structure" | "height" | "width" | "dragover" | "controls_open" | "loading" | "fullscreen" | "hovered" | "camera_projection" | "info_pane_open" | "wrapper" | "error_msg" | "png_dpi" | "bz_order" | "surface_color" | "surface_opacity" | "edge_color" | "edge_width" | "show_vectors" | "show_ibz" | "ibz_color" | "ibz_opacity" | "bz_data" | "vector_scale" | "ibz_data">;
81
+ declare const BrillouinZone: import("svelte").Component<$$ComponentProps, {}, "structure" | "height" | "width" | "dragover" | "fullscreen" | "hovered" | "controls_open" | "loading" | "camera_projection" | "vector_scale" | "info_pane_open" | "wrapper" | "png_dpi" | "error_msg" | "bz_order" | "surface_color" | "surface_opacity" | "edge_color" | "edge_width" | "show_vectors" | "show_ibz" | "ibz_color" | "ibz_opacity" | "bz_data" | "ibz_data">;
82
82
  type BrillouinZone = ReturnType<typeof BrillouinZone>;
83
83
  export default BrillouinZone;
@@ -1,8 +1,35 @@
1
- <script lang="ts">import SettingsSection from '../layout/SettingsSection.svelte';
2
- import DraggablePane from '../overlays/DraggablePane.svelte';
3
- let { controls_open = $bindable(false), bz_order = $bindable(1), surface_color = $bindable(`#4488ff`), surface_opacity = $bindable(0.3), edge_color = $bindable(`#000000`), edge_width = $bindable(0.05), show_vectors = $bindable(true), camera_projection = $bindable(`perspective`),
4
- // Irreducible BZ options
5
- show_ibz = $bindable(false), ibz_color = $bindable(`#ff8844`), ibz_opacity = $bindable(0.5), } = $props();
1
+ <script lang="ts">
2
+ import SettingsSection from '../layout/SettingsSection.svelte'
3
+ import DraggablePane from '../overlays/DraggablePane.svelte'
4
+ import type { CameraProjection } from '../settings'
5
+
6
+ let {
7
+ controls_open = $bindable(false),
8
+ bz_order = $bindable(1),
9
+ surface_color = $bindable(`#4488ff`),
10
+ surface_opacity = $bindable(0.3),
11
+ edge_color = $bindable(`#000000`),
12
+ edge_width = $bindable(0.05),
13
+ show_vectors = $bindable(true),
14
+ camera_projection = $bindable(`perspective`),
15
+ // Irreducible BZ options
16
+ show_ibz = $bindable(false),
17
+ ibz_color = $bindable(`#ff8844`),
18
+ ibz_opacity = $bindable(0.5),
19
+ }: {
20
+ controls_open?: boolean
21
+ bz_order?: number
22
+ surface_color?: string
23
+ surface_opacity?: number
24
+ edge_color?: string
25
+ edge_width?: number
26
+ show_vectors?: boolean
27
+ camera_projection?: CameraProjection
28
+ // Irreducible BZ options
29
+ show_ibz?: boolean
30
+ ibz_color?: string
31
+ ibz_opacity?: number
32
+ } = $props()
6
33
  </script>
7
34
 
8
35
  <DraggablePane
@@ -1,47 +1,74 @@
1
- <script lang="ts">import { export_canvas_as_png } from '../io/export';
2
- import DraggablePane from '../overlays/DraggablePane.svelte';
3
- import { CopyButton } from 'svelte-multiselect';
4
- import { tooltip } from 'svelte-multiselect/attachments';
5
- let { export_pane_open = $bindable(false), bz_data, wrapper, scene, camera, filename = `brillouin-zone`, png_dpi = $bindable(150), ...rest } = $props();
6
- let json_copy_state = $state(`ready`);
7
- function export_as_png() {
8
- const canvas = wrapper?.querySelector(`canvas`);
9
- if (!canvas || !scene || !camera)
10
- return;
11
- const dpi = Math.max(50, Math.min(600, Math.trunc(png_dpi)));
12
- const png_name = `${filename}-${bz_data?.order ?? `1`}.png`;
13
- export_canvas_as_png(canvas, png_name, dpi, scene, camera);
14
- }
15
- function export_as_json() {
16
- const json_data = get_json_data();
17
- if (!json_data || !bz_data)
18
- return;
1
+ <script lang="ts">
2
+ import { export_canvas_as_png } from '../io/export'
3
+ import DraggablePane from '../overlays/DraggablePane.svelte'
4
+ import type { ComponentProps } from 'svelte'
5
+ import { CopyButton } from 'svelte-multiselect'
6
+ import { tooltip } from 'svelte-multiselect/attachments'
7
+ import type { HTMLAttributes } from 'svelte/elements'
8
+ import type { Camera, Scene } from 'three'
9
+ import type { BrillouinZoneData } from './types'
10
+
11
+ let {
12
+ export_pane_open = $bindable(false),
13
+ bz_data,
14
+ wrapper,
15
+ scene,
16
+ camera,
17
+ filename = `brillouin-zone`,
18
+ png_dpi = $bindable(150),
19
+ ...rest
20
+ }: HTMLAttributes<HTMLDivElement> & {
21
+ export_pane_open?: boolean
22
+ bz_data?: BrillouinZoneData
23
+ wrapper?: HTMLDivElement
24
+ scene?: Scene
25
+ camera?: Camera
26
+ filename?: string
27
+ png_dpi?: number
28
+ } = $props()
29
+
30
+ let json_copy_state = $state<ComponentProps<typeof CopyButton>[`state`]>(`ready`)
31
+
32
+ function export_as_png() {
33
+ const canvas = wrapper?.querySelector(`canvas`)
34
+ if (!canvas || !scene || !camera) return
35
+
36
+ const dpi = Math.max(50, Math.min(600, Math.trunc(png_dpi)))
37
+ const png_name = `${filename}-${bz_data?.order ?? `1`}.png`
38
+ export_canvas_as_png(canvas, png_name, dpi, scene, camera)
39
+ }
40
+
41
+ function export_as_json() {
42
+ const json_data = get_json_data()
43
+ if (!json_data || !bz_data) return
44
+
19
45
  const blob = new Blob([JSON.stringify(json_data, null, 2)], {
20
- type: `application/json`,
21
- });
22
- const url = URL.createObjectURL(blob);
23
- const link = document.createElement(`a`);
24
- link.href = url;
25
- link.download = `${filename}-bz-order-${bz_data.order}.json`;
26
- link.click();
27
- URL.revokeObjectURL(url);
28
- }
29
- function get_json_data() {
30
- if (!bz_data)
31
- return null;
46
+ type: `application/json`,
47
+ })
48
+ const url = URL.createObjectURL(blob)
49
+ const link = document.createElement(`a`)
50
+ link.href = url
51
+ link.download = `${filename}-bz-order-${bz_data.order}.json`
52
+ link.click()
53
+ URL.revokeObjectURL(url)
54
+ }
55
+
56
+ function get_json_data() {
57
+ if (!bz_data) return null
32
58
  return {
33
- order: bz_data.order,
34
- volume: bz_data.volume,
35
- vertices: bz_data.vertices,
36
- faces: bz_data.faces,
37
- edges: bz_data.edges,
38
- reciprocal_lattice: bz_data.k_lattice,
39
- };
40
- }
41
- let json_string = $derived.by(() => {
42
- const json_data = get_json_data();
43
- return json_data ? JSON.stringify(json_data, null, 2) : null;
44
- });
59
+ order: bz_data.order,
60
+ volume: bz_data.volume,
61
+ vertices: bz_data.vertices,
62
+ faces: bz_data.faces,
63
+ edges: bz_data.edges,
64
+ reciprocal_lattice: bz_data.k_lattice,
65
+ }
66
+ }
67
+
68
+ let json_string = $derived.by(() => {
69
+ const json_data = get_json_data()
70
+ return json_data ? JSON.stringify(json_data, null, 2) : null
71
+ })
45
72
  </script>
46
73
 
47
74
  <DraggablePane
@@ -10,6 +10,6 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
10
10
  filename?: string;
11
11
  png_dpi?: number;
12
12
  };
13
- declare const BrillouinZoneExportPane: import("svelte").Component<$$ComponentProps, {}, "export_pane_open" | "png_dpi">;
13
+ declare const BrillouinZoneExportPane: import("svelte").Component<$$ComponentProps, {}, "png_dpi" | "export_pane_open">;
14
14
  type BrillouinZoneExportPane = ReturnType<typeof BrillouinZoneExportPane>;
15
15
  export default BrillouinZoneExportPane;