matterviz 0.3.2 → 0.3.3

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 (280) 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/feedback/ClickFeedback.svelte +16 -5
  76. package/dist/feedback/DragOverlay.svelte +10 -2
  77. package/dist/feedback/Spinner.svelte +4 -2
  78. package/dist/feedback/StatusMessage.svelte +8 -2
  79. package/dist/fermi-surface/FermiSlice.svelte +118 -88
  80. package/dist/fermi-surface/FermiSurface.svelte +328 -187
  81. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  82. package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
  83. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  84. package/dist/fermi-surface/FermiSurfaceScene.svelte +535 -342
  85. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  86. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
  87. package/dist/fermi-surface/compute.js +16 -20
  88. package/dist/fermi-surface/parse.js +24 -14
  89. package/dist/fermi-surface/symmetry.js +2 -7
  90. package/dist/fermi-surface/types.d.ts +3 -5
  91. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1019 -765
  92. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +1 -1
  93. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +76 -22
  94. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +2 -3
  95. package/dist/icons.js +47 -0
  96. package/dist/index.d.ts +2 -1
  97. package/dist/index.js +2 -1
  98. package/dist/io/decompress.js +1 -1
  99. package/dist/io/export.d.ts +3 -0
  100. package/dist/io/export.js +129 -143
  101. package/dist/io/is-binary.js +2 -3
  102. package/dist/io/url-drop.js +1 -2
  103. package/dist/isosurface/Isosurface.svelte +202 -148
  104. package/dist/isosurface/IsosurfaceControls.svelte +46 -28
  105. package/dist/isosurface/parse.js +34 -29
  106. package/dist/isosurface/slice.js +5 -10
  107. package/dist/isosurface/types.d.ts +2 -1
  108. package/dist/isosurface/types.js +61 -12
  109. package/dist/labels.js +11 -8
  110. package/dist/layout/FullscreenToggle.svelte +11 -2
  111. package/dist/layout/InfoCard.svelte +38 -6
  112. package/dist/layout/InfoTag.svelte +63 -32
  113. package/dist/layout/PropertyFilter.svelte +82 -37
  114. package/dist/layout/SettingsSection.svelte +85 -55
  115. package/dist/layout/SubpageGrid.svelte +10 -2
  116. package/dist/layout/json-tree/JsonNode.svelte +183 -138
  117. package/dist/layout/json-tree/JsonTree.svelte +499 -413
  118. package/dist/layout/json-tree/JsonValue.svelte +127 -99
  119. package/dist/layout/json-tree/utils.js +4 -2
  120. package/dist/marching-cubes.js +25 -2
  121. package/dist/math.d.ts +13 -17
  122. package/dist/math.js +133 -67
  123. package/dist/overlays/ContextMenu.svelte +65 -40
  124. package/dist/overlays/DraggablePane.svelte +211 -139
  125. package/dist/periodic-table/PeriodicTable.svelte +278 -145
  126. package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
  127. package/dist/periodic-table/PropertySelect.svelte +25 -7
  128. package/dist/periodic-table/TableInset.svelte +8 -3
  129. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +446 -309
  130. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  131. package/dist/phase-diagram/PhaseDiagramControls.svelte +102 -43
  132. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  133. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +63 -40
  134. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +71 -28
  135. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +1 -1
  136. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +158 -101
  137. package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
  138. package/dist/phase-diagram/build-diagram.js +9 -9
  139. package/dist/phase-diagram/colors.js +1 -3
  140. package/dist/phase-diagram/parse.js +10 -9
  141. package/dist/phase-diagram/svg-to-diagram.js +53 -49
  142. package/dist/phase-diagram/utils.d.ts +1 -0
  143. package/dist/phase-diagram/utils.js +80 -25
  144. package/dist/plot/AxisLabel.svelte +28 -3
  145. package/dist/plot/BarPlot.svelte +1182 -734
  146. package/dist/plot/BarPlot.svelte.d.ts +2 -2
  147. package/dist/plot/BarPlotControls.svelte +31 -5
  148. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  149. package/dist/plot/ColorBar.svelte +479 -329
  150. package/dist/plot/ColorScaleSelect.svelte +27 -6
  151. package/dist/plot/ElementScatter.svelte +36 -15
  152. package/dist/plot/FillArea.svelte +152 -95
  153. package/dist/plot/Histogram.svelte +934 -571
  154. package/dist/plot/Histogram.svelte.d.ts +1 -1
  155. package/dist/plot/HistogramControls.svelte +53 -9
  156. package/dist/plot/HistogramControls.svelte.d.ts +1 -1
  157. package/dist/plot/InteractiveAxisLabel.svelte +34 -11
  158. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  159. package/dist/plot/Line.svelte +63 -28
  160. package/dist/plot/PlotControls.svelte +157 -114
  161. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  162. package/dist/plot/PlotLegend.svelte +174 -91
  163. package/dist/plot/PlotTooltip.svelte +45 -6
  164. package/dist/plot/PortalSelect.svelte +175 -147
  165. package/dist/plot/ReferenceLine.svelte +76 -22
  166. package/dist/plot/ReferenceLine3D.svelte +132 -107
  167. package/dist/plot/ReferencePlane.svelte +146 -121
  168. package/dist/plot/ScatterPlot.svelte +1681 -1091
  169. package/dist/plot/ScatterPlot.svelte.d.ts +2 -2
  170. package/dist/plot/ScatterPlot3D.svelte +256 -131
  171. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  172. package/dist/plot/ScatterPlot3DControls.svelte +113 -63
  173. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
  174. package/dist/plot/ScatterPlot3DScene.svelte +608 -403
  175. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  176. package/dist/plot/ScatterPlotControls.svelte +65 -25
  177. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  178. package/dist/plot/ScatterPoint.svelte +98 -26
  179. package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
  180. package/dist/plot/SpacegroupBarPlot.svelte +142 -85
  181. package/dist/plot/Surface3D.svelte +159 -108
  182. package/dist/plot/ZeroLines.svelte +55 -3
  183. package/dist/plot/ZoomRect.svelte +4 -2
  184. package/dist/plot/axis-utils.js +1 -3
  185. package/dist/plot/data-cleaning.js +12 -28
  186. package/dist/plot/data-transform.js +2 -1
  187. package/dist/plot/fill-utils.js +2 -0
  188. package/dist/plot/layout.d.ts +4 -1
  189. package/dist/plot/layout.js +33 -14
  190. package/dist/plot/reference-line.d.ts +2 -2
  191. package/dist/plot/reference-line.js +7 -5
  192. package/dist/plot/scales.js +24 -36
  193. package/dist/plot/types.d.ts +11 -23
  194. package/dist/plot/types.js +6 -11
  195. package/dist/plot/utils/label-placement.d.ts +32 -15
  196. package/dist/plot/utils/label-placement.js +227 -66
  197. package/dist/plot/utils/series-visibility.js +2 -3
  198. package/dist/rdf/RdfPlot.svelte +143 -91
  199. package/dist/rdf/calc-rdf.js +4 -5
  200. package/dist/sanitize.d.ts +4 -0
  201. package/dist/sanitize.js +107 -0
  202. package/dist/settings.d.ts +18 -6
  203. package/dist/settings.js +46 -16
  204. package/dist/spectral/Bands.svelte +632 -453
  205. package/dist/spectral/BandsAndDos.svelte +90 -49
  206. package/dist/spectral/BrillouinBandsDos.svelte +151 -93
  207. package/dist/spectral/Dos.svelte +389 -258
  208. package/dist/spectral/helpers.js +55 -43
  209. package/dist/state.svelte.d.ts +1 -1
  210. package/dist/state.svelte.js +3 -2
  211. package/dist/structure/Arrow.svelte +59 -20
  212. package/dist/structure/AtomLegend.svelte +215 -134
  213. package/dist/structure/Bond.svelte +73 -47
  214. package/dist/structure/CanvasTooltip.svelte +10 -2
  215. package/dist/structure/CellSelect.svelte +72 -45
  216. package/dist/structure/Cylinder.svelte +33 -17
  217. package/dist/structure/Lattice.svelte +88 -33
  218. package/dist/structure/Structure.svelte +1063 -797
  219. package/dist/structure/Structure.svelte.d.ts +1 -1
  220. package/dist/structure/StructureControls.svelte +349 -118
  221. package/dist/structure/StructureExportPane.svelte +124 -89
  222. package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
  223. package/dist/structure/StructureInfoPane.svelte +304 -237
  224. package/dist/structure/StructureScene.svelte +879 -443
  225. package/dist/structure/StructureScene.svelte.d.ts +15 -7
  226. package/dist/structure/atom-properties.js +8 -8
  227. package/dist/structure/bonding.js +6 -7
  228. package/dist/structure/export.js +14 -29
  229. package/dist/structure/ferrox-wasm.js +1 -1
  230. package/dist/structure/index.d.ts +13 -3
  231. package/dist/structure/index.js +83 -23
  232. package/dist/structure/measure.d.ts +2 -2
  233. package/dist/structure/measure.js +4 -44
  234. package/dist/structure/parse.js +113 -141
  235. package/dist/structure/partial-occupancy.js +7 -10
  236. package/dist/structure/pbc.d.ts +1 -0
  237. package/dist/structure/pbc.js +16 -6
  238. package/dist/structure/supercell.d.ts +2 -2
  239. package/dist/structure/supercell.js +12 -22
  240. package/dist/structure/validation.js +1 -2
  241. package/dist/symmetry/SymmetryStats.svelte +84 -41
  242. package/dist/symmetry/WyckoffTable.svelte +26 -6
  243. package/dist/symmetry/cell-transform.js +5 -3
  244. package/dist/symmetry/index.js +8 -7
  245. package/dist/symmetry/spacegroups.js +148 -148
  246. package/dist/table/HeatmapTable.svelte +790 -554
  247. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  248. package/dist/table/ToggleMenu.svelte +125 -92
  249. package/dist/table/index.js +2 -4
  250. package/dist/theme/ThemeControl.svelte +21 -12
  251. package/dist/time.js +4 -1
  252. package/dist/tooltip/TooltipContent.svelte +33 -8
  253. package/dist/trajectory/Trajectory.svelte +758 -558
  254. package/dist/trajectory/TrajectoryError.svelte +14 -3
  255. package/dist/trajectory/TrajectoryExportPane.svelte +137 -83
  256. package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
  257. package/dist/trajectory/extract.js +10 -26
  258. package/dist/trajectory/format-detect.js +5 -5
  259. package/dist/trajectory/frame-reader.d.ts +1 -1
  260. package/dist/trajectory/frame-reader.js +5 -12
  261. package/dist/trajectory/helpers.d.ts +0 -1
  262. package/dist/trajectory/helpers.js +2 -17
  263. package/dist/trajectory/index.js +14 -12
  264. package/dist/trajectory/parse/ase.js +5 -4
  265. package/dist/trajectory/parse/hdf5.js +26 -18
  266. package/dist/trajectory/parse/index.js +13 -18
  267. package/dist/trajectory/parse/lammps.js +17 -7
  268. package/dist/trajectory/parse/vasp.js +5 -2
  269. package/dist/trajectory/parse/xyz.js +8 -7
  270. package/dist/trajectory/plotting.js +13 -8
  271. package/dist/utils.d.ts +1 -0
  272. package/dist/utils.js +13 -0
  273. package/dist/xrd/XrdPlot.svelte +337 -247
  274. package/dist/xrd/broadening.js +14 -9
  275. package/dist/xrd/calc-xrd.js +12 -18
  276. package/dist/xrd/parse.d.ts +1 -1
  277. package/dist/xrd/parse.js +17 -17
  278. package/package.json +99 -103
  279. package/readme.md +1 -1
  280. /package/dist/theme/{themes.js → themes.mjs} +0 -0
@@ -1,152 +1,233 @@
1
- <script lang="ts">import { contrast_color, default_element_colors } from '../colors';
2
- import { element_data } from '../element';
3
- import Icon from '../Icon.svelte';
4
- import { ELEM_SYMBOLS, format_num } from '../labels';
5
- import { ColorBar } from '../plot';
6
- import { SETTINGS_CONFIG } from '../settings';
7
- import { colors } from '../state.svelte';
8
- import { atomic_radii } from './';
9
- import { click_outside, tooltip } from 'svelte-multiselect/attachments';
10
- import { SvelteMap, SvelteSet } from 'svelte/reactivity';
11
- let { atom_color_config = $bindable({
12
- mode: `element`,
13
- scale: undefined,
14
- scale_type: `continuous`,
15
- }), property_colors = null, elements, elem_color_picker_title = `Double click to reset color`, labels = $bindable([]), amount_format = `.3~f`, show_amounts = true, get_element_label, hidden_elements = $bindable(new SvelteSet()), hidden_prop_vals = $bindable(new SvelteSet()),
16
- // Element remapping: maps original element symbols to new ones
17
- element_mapping = $bindable(),
18
- // Per-element and per-site radius overrides
19
- element_radius_overrides = $bindable({}), site_radius_overrides = $bindable(new SvelteMap()), selected_sites = [], title = ``, sym_data = null, structure = undefined, children, ...rest } = $props();
20
- const titles = {
1
+ <script lang="ts">
2
+ import { contrast_color, default_element_colors } from '../colors'
3
+ import type { CompositionType } from '../composition'
4
+ import type { ElementSymbol } from '../element'
5
+ import { element_data } from '../element'
6
+ import Icon from '../Icon.svelte'
7
+ import { ELEM_SYMBOLS, format_num } from '../labels'
8
+ import { ColorBar } from '../plot'
9
+ import { SETTINGS_CONFIG } from '../settings'
10
+ import { colors } from '../state.svelte'
11
+ import type { AnyStructure } from './'
12
+ import { atomic_radii } from './'
13
+ import type {
14
+ AtomColorConfig,
15
+ AtomPropertyColors,
16
+ } from './atom-properties'
17
+ import type { MoyoDataset } from '@spglib/moyo-wasm'
18
+ import type { Snippet } from 'svelte'
19
+ import { click_outside, tooltip } from 'svelte-multiselect/attachments'
20
+ import type { HTMLAttributes } from 'svelte/elements'
21
+ import { SvelteMap, SvelteSet } from 'svelte/reactivity'
22
+
23
+ let {
24
+ atom_color_config = $bindable({
25
+ mode: `element`,
26
+ scale: undefined,
27
+ scale_type: `continuous`,
28
+ }),
29
+ property_colors = null,
30
+ elements,
31
+ elem_color_picker_title = `Double click to reset color`,
32
+ labels = $bindable([]),
33
+ amount_format = `.3~f`,
34
+ show_amounts = true,
35
+ get_element_label,
36
+ hidden_elements = $bindable(new SvelteSet()),
37
+ hidden_prop_vals = $bindable(new SvelteSet<number | string>()),
38
+ // Element remapping: maps original element symbols to new ones
39
+ element_mapping = $bindable(),
40
+ // Per-element and per-site radius overrides
41
+ element_radius_overrides = $bindable<Partial<Record<ElementSymbol, number>>>({}),
42
+ site_radius_overrides = $bindable<SvelteMap<number, number>>(new SvelteMap()),
43
+ selected_sites = [] as number[],
44
+ title = ``,
45
+ sym_data = null,
46
+ structure = undefined,
47
+ children,
48
+ ...rest
49
+ }: Omit<HTMLAttributes<HTMLDivElement>, `children`> & {
50
+ atom_color_config?: Partial<AtomColorConfig>
51
+ property_colors?: AtomPropertyColors | null
52
+ elements?: CompositionType
53
+ elem_color_picker_title?: string
54
+ labels?: HTMLLabelElement[]
55
+ amount_format?: string // Float formatting for element amounts (default: 3 significant digits)
56
+ show_amounts?: boolean // Whether to show element amounts
57
+ get_element_label?: (element: string, amount: number) => string // Custom label function
58
+ hidden_elements?: Set<ElementSymbol>
59
+ hidden_prop_vals?: Set<number | string> // Track hidden property values (e.g. Wyckoff positions, coordination numbers)
60
+ // Element remapping: maps original element symbols to new ones (e.g. {'H': 'Na', 'He': 'Cl'})
61
+ element_mapping?: Partial<Record<ElementSymbol, ElementSymbol>>
62
+ // Per-element and per-site radius overrides (absolute values in Angstroms)
63
+ element_radius_overrides?: Partial<Record<ElementSymbol, number>>
64
+ site_radius_overrides?: Map<number, number> | SvelteMap<number, number>
65
+ selected_sites?: number[] // Currently selected site indices
66
+ title?: string
67
+ sym_data?: MoyoDataset | null
68
+ structure?: AnyStructure | null
69
+ children?: Snippet<[{ mode_menu_open: boolean; structure?: AnyStructure | null }]>
70
+ } = $props()
71
+
72
+ const titles = {
21
73
  coordination: `Coordination`,
22
74
  wyckoff: `Wyckoff Position`,
23
- };
24
- let show_element_legend = $derived(atom_color_config.mode === `element` && elements &&
25
- Object.keys(elements).length > 0);
26
- let show_property_legend = $derived(atom_color_config.mode !== `element` && property_colors?.colors.length);
27
- let legend_title = $derived(title || titles[atom_color_config.mode] || ``);
28
- // Dropdown state
29
- let mode_menu_open = $state(false);
30
- // Clear hidden property values when switching modes (since they may not be valid)
31
- let previous_mode = $state(atom_color_config.mode);
32
- $effect(() => {
75
+ }
76
+
77
+ let show_element_legend = $derived(
78
+ atom_color_config.mode === `element` && elements &&
79
+ Object.keys(elements).length > 0,
80
+ )
81
+ let show_property_legend = $derived(
82
+ atom_color_config.mode !== `element` && property_colors?.colors.length,
83
+ )
84
+ let legend_title = $derived(
85
+ title || titles[atom_color_config.mode as keyof typeof titles] || ``,
86
+ )
87
+
88
+ // Dropdown state
89
+ let mode_menu_open = $state(false)
90
+
91
+ // Clear hidden property values when switching modes (since they may not be valid)
92
+ let previous_mode = $state(atom_color_config.mode)
93
+ $effect(() => {
33
94
  if (atom_color_config.mode !== previous_mode) {
34
- hidden_prop_vals.clear();
35
- previous_mode = atom_color_config.mode;
95
+ hidden_prop_vals.clear()
96
+ previous_mode = atom_color_config.mode
36
97
  }
37
- });
38
- // Normalize incoming Map to SvelteMap at boundary for reactivity
39
- // This preserves identity for bindings while ensuring SvelteMap methods work
40
- $effect(() => {
98
+ })
99
+
100
+ // Normalize incoming Map to SvelteMap at boundary for reactivity
101
+ // This preserves identity for bindings while ensuring SvelteMap methods work
102
+ $effect(() => {
41
103
  if (site_radius_overrides && !(site_radius_overrides instanceof SvelteMap)) {
42
- site_radius_overrides = new SvelteMap(site_radius_overrides);
104
+ site_radius_overrides = new SvelteMap(site_radius_overrides)
43
105
  }
44
- });
45
- // Format display values based on mode
46
- let format_value = (val) => {
47
- if (typeof val === `number`)
48
- return format_num(val, `.3~f`);
106
+ })
107
+ // Format display values based on mode
108
+ let format_value = (val: number | string): string => {
109
+ if (typeof val === `number`) return format_num(val, `.3~f`)
110
+
49
111
  if (typeof val === `string` && val.includes(`|`)) { // Format Wyckoff orbit IDs
50
- const [wyckoff, element] = val.split(`|`, 2);
51
- // Count how many sites have this wyckoff+element combination
52
- const count = property_colors?.values.filter((v) => v === val).length ?? 0;
53
- return `${element}:${count}${wyckoff}`;
112
+ const [wyckoff, element] = val.split(`|`, 2)
113
+ // Count how many sites have this wyckoff+element combination
114
+ const count = property_colors?.values.filter((v) => v === val).length ?? 0
115
+ return `${element}:${count}${wyckoff}`
54
116
  }
55
- return String(val);
56
- };
57
- // Map from property value to color (computed once, reused in categorical legend)
58
- let color_map = $derived(new Map(
59
- // Use unique_values instead of values to avoid undefined colors from duplicates
60
- property_colors?.unique_values?.flatMap((val) => {
61
- const idx = property_colors.values.indexOf(val);
62
- return idx >= 0 ? [[val, property_colors.colors[idx]]] : [];
63
- }) ?? []));
64
- function toggle_visibility(set, value, event) {
65
- event.preventDefault();
66
- event.stopPropagation();
67
- const new_set = new SvelteSet(set);
68
- if (new_set.has(value))
69
- new_set.delete(value);
70
- else
71
- new_set.add(value);
72
- return new_set;
73
- }
74
- // Element remapping state
75
- let remap_menu_open = $state(null);
76
- let remap_search = $state(``);
77
- // Filtered elements based on search
78
- let filtered_elements = $derived.by(() => {
79
- if (!remap_search)
80
- return ELEM_SYMBOLS;
81
- const query = remap_search.toLowerCase();
117
+ return String(val)
118
+ }
119
+
120
+ // Map from property value to color (computed once, reused in categorical legend)
121
+ let color_map = $derived(
122
+ new Map(
123
+ // Use unique_values instead of values to avoid undefined colors from duplicates
124
+ property_colors?.unique_values?.flatMap((val) => {
125
+ const idx = property_colors.values.indexOf(val)
126
+ return idx >= 0 ? [[val, property_colors.colors[idx]]] : []
127
+ }) ?? [],
128
+ ),
129
+ )
130
+
131
+ function toggle_visibility<T>(
132
+ set: Set<T>,
133
+ value: T,
134
+ event: MouseEvent,
135
+ ): Set<T> {
136
+ event.preventDefault()
137
+ event.stopPropagation()
138
+ const new_set = new SvelteSet(set)
139
+ if (new_set.has(value)) new_set.delete(value)
140
+ else new_set.add(value)
141
+ return new_set
142
+ }
143
+
144
+ // Element remapping state
145
+ let remap_menu_open = $state<ElementSymbol | null>(null)
146
+ let remap_search = $state(``)
147
+
148
+ // Filtered elements based on search
149
+ let filtered_elements = $derived.by(() => {
150
+ if (!remap_search) return ELEM_SYMBOLS
151
+ const query = remap_search.toLowerCase()
82
152
  return ELEM_SYMBOLS.filter((elem) => {
83
- const data = element_data?.find((el) => el.symbol === elem);
84
- return elem.toLowerCase().includes(query) ||
85
- data?.name?.toLowerCase().includes(query);
86
- });
87
- });
88
- const known_element_symbols = new Set(ELEM_SYMBOLS);
89
- let sorted_element_entries = $derived.by(() => {
90
- if (!elements)
91
- return [];
92
- const element_amounts = elements;
153
+ const data = element_data?.find((el) => el.symbol === elem)
154
+ return elem.toLowerCase().includes(query) ||
155
+ data?.name?.toLowerCase().includes(query)
156
+ })
157
+ })
158
+
159
+ const known_element_symbols = new Set(ELEM_SYMBOLS)
160
+ let sorted_element_entries = $derived.by(() => {
161
+ if (!elements) return []
162
+ const element_amounts = elements as Record<string, number>
93
163
  const ordered_known_entries = ELEM_SYMBOLS
94
- .flatMap((element_symbol) => {
95
- const amount = element_amounts[element_symbol];
96
- return amount === undefined ? [] : [[element_symbol, amount]];
97
- });
164
+ .flatMap((element_symbol) => {
165
+ const amount = element_amounts[element_symbol]
166
+ return amount === undefined ? [] : [[element_symbol, amount] as const]
167
+ })
98
168
  const unknown_entries = Object.entries(element_amounts)
99
- .filter(([element_symbol]) => !known_element_symbols.has(element_symbol))
100
- .sort(([element_a], [element_b]) => element_a.localeCompare(element_b));
101
- return [...ordered_known_entries, ...unknown_entries];
102
- });
103
- function remap_element(from, to) {
169
+ .filter(([element_symbol]) =>
170
+ !known_element_symbols.has(element_symbol as ElementSymbol)
171
+ )
172
+ .sort(([element_a], [element_b]) => element_a.localeCompare(element_b))
173
+ return [...ordered_known_entries, ...unknown_entries]
174
+ })
175
+
176
+ function remap_element(from: ElementSymbol, to: ElementSymbol) {
104
177
  if (from === to && element_mapping?.[from]) {
105
- // Remove mapping if mapping back to original element
106
- const { [from]: _, ...rest } = element_mapping;
107
- element_mapping = Object.keys(rest).length > 0 ? rest : undefined;
178
+ // Remove mapping if mapping back to original element
179
+ const { [from]: _, ...rest } = element_mapping
180
+ element_mapping = Object.keys(rest).length > 0 ? rest : undefined
181
+ } else if (from !== to) {
182
+ element_mapping = { ...element_mapping, [from]: to }
108
183
  }
109
- else if (from !== to) {
110
- element_mapping = { ...element_mapping, [from]: to };
111
- }
112
- remap_menu_open = null;
113
- remap_search = ``;
114
- }
115
- // Radius bounds (Angstroms) - max accommodates largest atomic radii (~2.6Å for Cs)
116
- const MIN_RADIUS = 0.1;
117
- const MAX_RADIUS = 5;
118
- const parse_radius = (value) => {
119
- const num = parseFloat(value);
120
- return !isNaN(num) && num >= MIN_RADIUS && num <= MAX_RADIUS ? num : null;
121
- };
122
- function update_element_radius(elem, value) {
123
- const radius = parse_radius(value);
184
+ remap_menu_open = null
185
+ remap_search = ``
186
+ }
187
+
188
+ // Radius bounds (Angstroms) - max accommodates largest atomic radii (~2.6Å for Cs)
189
+ const MIN_RADIUS = 0.1
190
+ const MAX_RADIUS = 5
191
+
192
+ const parse_radius = (value: string): number | null => {
193
+ const num = parseFloat(value)
194
+ return !isNaN(num) && num >= MIN_RADIUS && num <= MAX_RADIUS ? num : null
195
+ }
196
+
197
+ function update_element_radius(elem: ElementSymbol, value: string) {
198
+ const radius = parse_radius(value)
124
199
  if (radius !== null) {
125
- element_radius_overrides = { ...element_radius_overrides, [elem]: radius };
200
+ element_radius_overrides = { ...element_radius_overrides, [elem]: radius }
126
201
  }
127
- }
128
- function clear_element_radius(elem) {
129
- const { [elem]: _, ...rest } = element_radius_overrides ?? {};
130
- element_radius_overrides = rest;
131
- }
132
- const get_element_radius = (elem) => element_radius_overrides?.[elem] ?? atomic_radii[elem] ?? 1;
133
- // Mutate in-place to preserve map identity for bindings (aligns with Structure.svelte pattern)
134
- function update_site_radius(site_idx, value) {
135
- const radius = parse_radius(value);
136
- if (radius === null)
137
- return;
138
- site_radius_overrides?.set(site_idx, radius);
139
- }
140
- function clear_site_radius(site_idx) {
141
- site_radius_overrides?.delete(site_idx);
142
- }
143
- const get_site_radius = (site_idx) => {
144
- const override = site_radius_overrides?.get(site_idx);
145
- if (override !== undefined)
146
- return override;
147
- const element = structure?.sites?.[site_idx]?.species[0]?.element;
148
- return element ? get_element_radius(element) : 1;
149
- };
202
+ }
203
+
204
+ function clear_element_radius(elem: ElementSymbol) {
205
+ const { [elem]: _, ...rest } = element_radius_overrides ?? {}
206
+ element_radius_overrides = rest
207
+ }
208
+
209
+ const get_element_radius = (elem: ElementSymbol): number =>
210
+ element_radius_overrides?.[elem] ?? atomic_radii[elem] ?? 1
211
+
212
+ // Mutate in-place to preserve map identity for bindings (aligns with Structure.svelte pattern)
213
+ function update_site_radius(site_idx: number, value: string) {
214
+ const radius = parse_radius(value)
215
+ if (radius === null) return
216
+ site_radius_overrides?.set(site_idx, radius)
217
+ }
218
+
219
+ function clear_site_radius(site_idx: number) {
220
+ site_radius_overrides?.delete(site_idx)
221
+ }
222
+
223
+ const get_site_radius = (site_idx: number): number => {
224
+ const override = site_radius_overrides?.get(site_idx)
225
+ if (override !== undefined) return override
226
+ const element = structure?.sites?.[site_idx]?.species[0]?.element as
227
+ | ElementSymbol
228
+ | undefined
229
+ return element ? get_element_radius(element) : 1
230
+ }
150
231
  </script>
151
232
 
152
233
  {#snippet mode_selector_snippet()}
@@ -1,11 +1,21 @@
1
- <script lang="ts">import { T } from '@threlte/core';
2
- import { Color, InstancedBufferAttribute, Matrix4, ShaderMaterial } from 'three';
3
- let { group, saturation = 0.5, brightness = 0.7 } = $props();
4
- let mesh = $state();
5
- // Reusable buffers to avoid reallocation on every update
6
- let colors_start = new Float32Array(0);
7
- let colors_end = new Float32Array(0);
8
- const vertex_shader = `
1
+ <script lang="ts">
2
+ import type { BondGroupWithGradients } from './'
3
+ import { T } from '@threlte/core'
4
+ import type { InstancedMesh } from 'three'
5
+ import { Color, InstancedBufferAttribute, Matrix4, ShaderMaterial } from 'three'
6
+
7
+ let { group, saturation = 0.5, brightness = 0.7 }: {
8
+ group: BondGroupWithGradients
9
+ saturation?: number
10
+ brightness?: number
11
+ } = $props()
12
+
13
+ let mesh: InstancedMesh | undefined = $state()
14
+ // Reusable buffers to avoid reallocation on every update
15
+ let colors_start = new Float32Array(0)
16
+ let colors_end = new Float32Array(0)
17
+
18
+ const vertex_shader = `
9
19
  attribute vec3 instanceColorStart;
10
20
  attribute vec3 instanceColorEnd;
11
21
  varying vec3 vColorStart;
@@ -20,8 +30,9 @@ const vertex_shader = `
20
30
  vNormal = normalize(normalMatrix * normal);
21
31
  gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position, 1.0);
22
32
  }
23
- `;
24
- const fragment_shader = `
33
+ `
34
+
35
+ const fragment_shader = `
25
36
  uniform float ambientIntensity;
26
37
  uniform float directionalIntensity;
27
38
  uniform float saturation;
@@ -53,57 +64,72 @@ const fragment_shader = `
53
64
 
54
65
  gl_FragColor = vec4(linearTosRGB(final_color), 1.0);
55
66
  }
56
- `;
57
- function set_color_buffer(buffer, idx, color, temp_color) {
58
- temp_color.set(color).convertSRGBToLinear();
59
- buffer[idx * 3] = temp_color.r;
60
- buffer[idx * 3 + 1] = temp_color.g;
61
- buffer[idx * 3 + 2] = temp_color.b;
62
- }
63
- $effect(() => {
64
- if (!mesh)
65
- return;
66
- const count = group.instances.length;
67
- const matrix = new Matrix4();
68
- const temp_color = new Color();
67
+ `
68
+
69
+ function set_color_buffer(
70
+ buffer: Float32Array,
71
+ idx: number,
72
+ color: string,
73
+ temp_color: Color,
74
+ ) {
75
+ temp_color.set(color).convertSRGBToLinear()
76
+ buffer[idx * 3] = temp_color.r
77
+ buffer[idx * 3 + 1] = temp_color.g
78
+ buffer[idx * 3 + 2] = temp_color.b
79
+ }
80
+
81
+ $effect(() => {
82
+ if (!mesh) return
83
+
84
+ const count = group.instances.length
85
+ const matrix = new Matrix4()
86
+ const temp_color = new Color()
87
+
69
88
  // Reallocate buffers if instance count changed
70
89
  if (colors_start.length !== count * 3) {
71
- colors_start = new Float32Array(count * 3);
72
- colors_end = new Float32Array(count * 3);
90
+ colors_start = new Float32Array(count * 3)
91
+ colors_end = new Float32Array(count * 3)
73
92
  }
93
+
74
94
  // Update instance matrices and colors
75
95
  for (let idx = 0; idx < count; idx++) {
76
- const instance = group.instances[idx];
77
- matrix.fromArray(instance.matrix);
78
- mesh.setMatrixAt(idx, matrix);
79
- set_color_buffer(colors_start, idx, instance.color_start, temp_color);
80
- set_color_buffer(colors_end, idx, instance.color_end, temp_color);
96
+ const instance = group.instances[idx]
97
+ matrix.fromArray(instance.matrix)
98
+ mesh.setMatrixAt(idx, matrix)
99
+ set_color_buffer(colors_start, idx, instance.color_start, temp_color)
100
+ set_color_buffer(colors_end, idx, instance.color_end, temp_color)
81
101
  }
82
- mesh.instanceMatrix.needsUpdate = true;
102
+
103
+ mesh.instanceMatrix.needsUpdate = true
104
+
83
105
  // Update geometry color attributes
84
- const { geometry } = mesh;
85
- for (const [name, buffer] of [
106
+ const { geometry } = mesh
107
+ for (
108
+ const [name, buffer] of [
86
109
  [`instanceColorStart`, colors_start],
87
110
  [`instanceColorEnd`, colors_end],
88
- ]) {
89
- const existing = geometry.getAttribute(name);
90
- if (existing?.array === buffer)
91
- existing.needsUpdate = true;
92
- else
93
- geometry.setAttribute(name, new InstancedBufferAttribute(buffer, 3));
111
+ ] as const
112
+ ) {
113
+ const existing = geometry.getAttribute(name)
114
+ if (existing?.array === buffer) existing.needsUpdate = true
115
+ else geometry.setAttribute(name, new InstancedBufferAttribute(buffer, 3))
94
116
  }
95
- mesh.count = count;
96
- });
97
- let shader_material = $derived(new ShaderMaterial({
98
- vertexShader: vertex_shader,
99
- fragmentShader: fragment_shader,
100
- uniforms: {
117
+
118
+ mesh.count = count
119
+ })
120
+
121
+ let shader_material = $derived(
122
+ new ShaderMaterial({
123
+ vertexShader: vertex_shader,
124
+ fragmentShader: fragment_shader,
125
+ uniforms: {
101
126
  ambientIntensity: { value: group.ambient_light ?? 0.7 },
102
127
  directionalIntensity: { value: group.directional_light ?? 0.3 },
103
128
  saturation: { value: saturation },
104
129
  brightness: { value: brightness },
105
- },
106
- }));
130
+ },
131
+ }),
132
+ )
107
133
  </script>
108
134
 
109
135
  <T.InstancedMesh
@@ -1,5 +1,13 @@
1
- <script lang="ts">import { HTML } from '@threlte/extras';
2
- let { position, children, ...rest } = $props();
1
+ <script lang="ts">
2
+ import type { Vec3 } from '../math'
3
+ import { HTML } from '@threlte/extras'
4
+ import type { Snippet } from 'svelte'
5
+ import type { HTMLAttributes } from 'svelte/elements'
6
+
7
+ let { position, children, ...rest }: HTMLAttributes<HTMLDivElement> & {
8
+ position: Vec3
9
+ children: Snippet<[{ position: Vec3 }]>
10
+ } = $props()
3
11
  </script>
4
12
 
5
13
  <HTML {position} pointerEvents="none">