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,180 +1,253 @@
1
- <script lang="ts">import { PLOT_COLORS } from '../colors';
2
- import { StatusMessage } from '../feedback';
3
- import { create_file_drop_handler } from '../io';
4
- import { format_value } from '../labels';
5
- import { BarPlot } from '../plot';
6
- import { parse_any_structure } from '../structure/parse';
7
- import { is_crystal } from '../structure/validation';
8
- import { SvelteMap, SvelteSet } from 'svelte/reactivity';
9
- import { calc_coordination_nums } from './calc-coordination';
10
- let { structures, strategy = `electroneg_ratio`, split_mode = `by_element`, mode = $bindable(`grouped`), orientation = `vertical`, x_axis = {}, y_axis = {}, allow_file_drop = true, on_file_drop, loading = $bindable(false), error_msg = $bindable(), ...rest } = $props();
11
- let dragover = $state(false);
12
- let dropped_entries = $state([]);
13
- let is_horizontal = $derived(orientation === `horizontal`);
14
- // Normalize input to consistent array of { label, structure, color }
15
- const structure_entries = $derived.by(() => {
16
- if (!structures)
17
- return [];
1
+ <script lang="ts">
2
+ import { PLOT_COLORS } from '../colors'
3
+ import { StatusMessage } from '../feedback'
4
+ import { create_file_drop_handler } from '../io'
5
+ import { format_value } from '../labels'
6
+ import { BarPlot } from '../plot'
7
+ import type {
8
+ AxisConfig,
9
+ BarHandlerProps,
10
+ BarSeries,
11
+ Orientation,
12
+ } from '../plot/types'
13
+ import type { AnyStructure } from '../structure'
14
+ import type { BondingStrategy } from '../structure/bonding'
15
+ import { parse_any_structure } from '../structure/parse'
16
+ import { is_crystal } from '../structure/validation'
17
+ import type { ComponentProps } from 'svelte'
18
+ import { SvelteMap, SvelteSet } from 'svelte/reactivity'
19
+ import { calc_coordination_nums, type CoordinationData } from './calc-coordination'
20
+ import type { SplitMode } from './index'
21
+
22
+ type CoordinationMetadata = {
23
+ element?: string
24
+ structure_label?: string
25
+ } & Record<string, unknown>
26
+
27
+ interface StructureEntry {
28
+ label: string
29
+ structure: AnyStructure
30
+ color?: string
31
+ data?: CoordinationData
32
+ }
33
+ let {
34
+ structures,
35
+ strategy = `electroneg_ratio`,
36
+ split_mode = `by_element`,
37
+ mode = $bindable(`grouped`),
38
+ orientation = `vertical` as Orientation,
39
+ x_axis = {},
40
+ y_axis = {},
41
+ allow_file_drop = true,
42
+ on_file_drop,
43
+ loading = $bindable(false),
44
+ error_msg = $bindable(),
45
+ ...rest
46
+ }: Omit<ComponentProps<typeof BarPlot>, `series`> & {
47
+ structures:
48
+ | AnyStructure
49
+ | Record<string, AnyStructure | { structure: AnyStructure; color?: string }>
50
+ | StructureEntry[]
51
+ strategy?: BondingStrategy
52
+ split_mode?: SplitMode
53
+ x_axis?: AxisConfig
54
+ y_axis?: AxisConfig
55
+ allow_file_drop?: boolean
56
+ on_file_drop?: (content: string | ArrayBuffer, filename: string) => void
57
+ loading?: boolean
58
+ error_msg?: string
59
+ } = $props()
60
+
61
+ let dragover = $state(false)
62
+ let dropped_entries = $state<StructureEntry[]>([])
63
+ let is_horizontal = $derived(orientation === `horizontal`)
64
+
65
+ // Normalize input to consistent array of { label, structure, color }
66
+ const structure_entries = $derived.by<StructureEntry[]>(() => {
67
+ if (!structures) return []
68
+
18
69
  const base_entries = Array.isArray(structures)
19
- ? structures
20
- : (is_crystal(structures)
21
- ? [{ label: `Structure`, structure: structures }]
22
- : Object.entries(structures).map(([label, value]) => `structure` in value
23
- ? { label, ...value }
24
- : { label, structure: value }));
70
+ ? (structures as StructureEntry[])
71
+ : (is_crystal(structures)
72
+ ? [{ label: `Structure`, structure: structures as AnyStructure }]
73
+ : Object.entries(
74
+ structures as Record<
75
+ string,
76
+ AnyStructure | { structure: AnyStructure; color?: string }
77
+ >,
78
+ ).map(([label, value]) =>
79
+ `structure` in value
80
+ ? { label, ...value }
81
+ : { label, structure: value as AnyStructure }
82
+ ))
83
+
25
84
  // Merge user-provided structures with dropped structures
26
- return [...base_entries, ...dropped_entries];
27
- });
28
- // Compute coordination data for each structure
29
- const entries_with_data = $derived(structure_entries.map((entry) => ({
85
+ return [...base_entries, ...dropped_entries]
86
+ })
87
+
88
+ // Compute coordination data for each structure
89
+ const entries_with_data = $derived(structure_entries.map((entry) => ({
30
90
  ...entry,
31
91
  data: calc_coordination_nums(entry.structure, strategy),
32
- })));
33
- // Compute appropriate ranges
34
- const ranges = $derived.by(() => {
92
+ })))
93
+
94
+ // Compute appropriate ranges
95
+ const ranges = $derived.by(() => {
35
96
  // CN axis should always start at 0 and show at least [0,4]
36
- let max_cn = 4; // minimum max value
97
+ let max_cn = 4 // minimum max value
37
98
  for (const entry of entries_with_data) {
38
- for (const [cn] of entry.data.cn_histogram)
39
- max_cn = Math.max(max_cn, cn);
99
+ for (const [cn] of entry.data.cn_histogram) max_cn = Math.max(max_cn, cn)
40
100
  }
41
- const cn_range = [-0.5, max_cn + 0.5];
42
- return { count: [0, null], cn: cn_range }; // Count axis should always start at 0
43
- });
44
- // Derive integer CN ticks for axis labels
45
- const cn_ticks = $derived.by(() => {
46
- const all_cns = new SvelteSet();
101
+ const cn_range: [number, number] = [-0.5, max_cn + 0.5]
102
+
103
+ return { count: [0, null] as [number, null], cn: cn_range } // Count axis should always start at 0
104
+ })
105
+
106
+ // Derive integer CN ticks for axis labels
107
+ const cn_ticks = $derived.by(() => {
108
+ const all_cns = new SvelteSet<number>()
47
109
  // Always include minimum CN values 0-4
48
- for (let idx = 0; idx <= 4; idx++)
49
- all_cns.add(idx);
110
+ for (let idx = 0; idx <= 4; idx++) all_cns.add(idx)
50
111
  // Add actual CN values from data
51
112
  for (const entry of entries_with_data) {
52
- for (const [cn] of entry.data.cn_histogram)
53
- all_cns.add(cn);
113
+ for (const [cn] of entry.data.cn_histogram) all_cns.add(cn)
54
114
  }
55
- return Array.from(all_cns).sort((cn1, cn2) => cn1 - cn2);
56
- });
57
- // Build BarPlot series based on split_mode
58
- const bar_series = $derived.by(() => {
115
+ return Array.from(all_cns).sort((cn1, cn2) => cn1 - cn2)
116
+ })
117
+
118
+ // Build BarPlot series based on split_mode
119
+ const bar_series = $derived.by<BarSeries<CoordinationMetadata>[]>(() => {
59
120
  if (split_mode === `by_element`) {
60
- // One series per element across all structures
61
- const element_series_map = new SvelteMap();
62
- // Collect all unique CNs across all elements
63
- const all_cns = new SvelteSet();
64
- for (const entry of entries_with_data) {
65
- for (const [element, cn_histogram] of entry.data.cn_histogram_by_element) {
66
- if (!element_series_map.has(element)) {
67
- element_series_map.set(element, new SvelteMap());
68
- }
69
- const element_map = element_series_map.get(element);
70
- for (const [cn, count] of cn_histogram) {
71
- all_cns.add(cn);
72
- element_map.set(cn, (element_map.get(cn) ?? 0) + count);
73
- }
74
- }
75
- }
76
- // Sort CNs for consistent x-axis
77
- const sorted_cns = Array.from(all_cns).sort((a, b) => a - b);
78
- // Convert map to array and ensure all series have same x-values
79
- return Array.from(element_series_map.entries())
80
- .sort((a, b) => a[0].localeCompare(b[0]))
81
- .map(([element, cn_map], idx) => {
82
- return {
83
- x: sorted_cns,
84
- y: sorted_cns.map((cn) => cn_map.get(cn) ?? 0),
85
- label: element,
86
- color: PLOT_COLORS[idx % PLOT_COLORS.length],
87
- bar_width: 0.8,
88
- visible: true,
89
- metadata: { element },
90
- };
91
- });
92
- }
93
- else if (split_mode === `by_structure`) {
94
- // One series per structure
95
- // First collect all unique CNs
96
- const all_cns = new SvelteSet();
97
- for (const entry of entries_with_data) {
98
- for (const [cn] of entry.data.cn_histogram) {
99
- all_cns.add(cn);
100
- }
121
+ // One series per element across all structures
122
+ const element_series_map = new SvelteMap<string, Map<number, number>>()
123
+
124
+ // Collect all unique CNs across all elements
125
+ const all_cns = new SvelteSet<number>()
126
+
127
+ for (const entry of entries_with_data) {
128
+ for (const [element, cn_histogram] of entry.data.cn_histogram_by_element) {
129
+ if (!element_series_map.has(element)) {
130
+ element_series_map.set(element, new SvelteMap())
131
+ }
132
+ const element_map = element_series_map.get(element)
133
+ if (!element_map) continue
134
+
135
+ for (const [cn, count] of cn_histogram) {
136
+ all_cns.add(cn)
137
+ element_map.set(cn, (element_map.get(cn) ?? 0) + count)
138
+ }
101
139
  }
102
- const sorted_cns = Array.from(all_cns).sort((a, b) => a - b);
103
- return entries_with_data.map((entry, idx) => {
104
- return {
105
- x: sorted_cns,
106
- y: sorted_cns.map((cn) => entry.data.cn_histogram.get(cn) ?? 0),
107
- label: entry.label,
108
- color: entry.color ?? PLOT_COLORS[idx % PLOT_COLORS.length],
109
- bar_width: 0.8,
110
- visible: true,
111
- metadata: { structure_label: entry.label },
112
- };
113
- });
114
- }
115
- else {
116
- // split_mode === 'none': combine all into single series
117
- const combined_histogram = new SvelteMap();
118
- for (const entry of entries_with_data) {
119
- for (const [cn, count] of entry.data.cn_histogram) {
120
- combined_histogram.set(cn, (combined_histogram.get(cn) ?? 0) + count);
121
- }
140
+ }
141
+
142
+ // Sort CNs for consistent x-axis
143
+ const sorted_cns = Array.from(all_cns).sort((a, b) => a - b)
144
+
145
+ // Convert map to array and ensure all series have same x-values
146
+ return Array.from(element_series_map.entries())
147
+ .sort((a, b) => a[0].localeCompare(b[0]))
148
+ .map(([element, cn_map], idx) => {
149
+ return {
150
+ x: sorted_cns,
151
+ y: sorted_cns.map((cn) => cn_map.get(cn) ?? 0),
152
+ label: element,
153
+ color: PLOT_COLORS[idx % PLOT_COLORS.length],
154
+ bar_width: 0.8,
155
+ visible: true,
156
+ metadata: { element },
157
+ }
158
+ })
159
+ } else if (split_mode === `by_structure`) {
160
+ // One series per structure
161
+ // First collect all unique CNs
162
+ const all_cns = new SvelteSet<number>()
163
+ for (const entry of entries_with_data) {
164
+ for (const [cn] of entry.data.cn_histogram) {
165
+ all_cns.add(cn)
122
166
  }
123
- const x_vals = Array.from(combined_histogram.keys()).sort((a, b) => a - b);
124
- const y_vals = x_vals.map((cn) => combined_histogram.get(cn));
125
- return [
126
- {
127
- x: x_vals,
128
- y: y_vals,
129
- label: `All Sites`,
130
- color: PLOT_COLORS[0],
131
- bar_width: 0.8,
132
- visible: true,
133
- metadata: {},
134
- },
135
- ];
136
- }
137
- });
138
- const compute_and_add = (content, filename) => {
139
- try {
140
- const text_content = content instanceof ArrayBuffer
141
- ? new TextDecoder().decode(content)
142
- : content;
143
- const parsed_structure = parse_any_structure(text_content, filename);
144
- if (is_crystal(parsed_structure)) {
145
- dropped_entries = [{
146
- label: filename || `Dropped structure`,
147
- structure: parsed_structure,
148
- }, ...dropped_entries];
167
+ }
168
+ const sorted_cns = Array.from(all_cns).sort((a, b) => a - b)
169
+
170
+ return entries_with_data.map((entry, idx) => {
171
+ return {
172
+ x: sorted_cns,
173
+ y: sorted_cns.map((cn) => entry.data.cn_histogram.get(cn) ?? 0),
174
+ label: entry.label,
175
+ color: entry.color ?? PLOT_COLORS[idx % PLOT_COLORS.length],
176
+ bar_width: 0.8,
177
+ visible: true,
178
+ metadata: { structure_label: entry.label },
149
179
  }
150
- else {
151
- error_msg = `Structure has no lattice or sites; cannot compute coordination`;
180
+ })
181
+ } else {
182
+ // split_mode === 'none': combine all into single series
183
+ const combined_histogram = new SvelteMap<number, number>()
184
+
185
+ for (const entry of entries_with_data) {
186
+ for (const [cn, count] of entry.data.cn_histogram) {
187
+ combined_histogram.set(cn, (combined_histogram.get(cn) ?? 0) + count)
152
188
  }
189
+ }
190
+
191
+ const x_vals = Array.from(combined_histogram.keys()).sort((a, b) => a - b)
192
+ const y_vals = x_vals.map((cn) => combined_histogram.get(cn) ?? 0)
193
+
194
+ return [
195
+ {
196
+ x: x_vals,
197
+ y: y_vals,
198
+ label: `All Sites`,
199
+ color: PLOT_COLORS[0],
200
+ bar_width: 0.8,
201
+ visible: true,
202
+ metadata: {},
203
+ },
204
+ ]
153
205
  }
154
- catch (exc) {
155
- error_msg = `Failed to process structure: ${exc instanceof Error ? exc.message : String(exc)}`;
206
+ })
207
+
208
+ const compute_and_add = (content: string | ArrayBuffer, filename: string) => {
209
+ try {
210
+ const text_content = content instanceof ArrayBuffer
211
+ ? new TextDecoder().decode(content)
212
+ : content
213
+ const parsed_structure = parse_any_structure(text_content, filename)
214
+ if (is_crystal(parsed_structure)) {
215
+ dropped_entries = [{
216
+ label: filename || `Dropped structure`,
217
+ structure: parsed_structure,
218
+ }, ...dropped_entries]
219
+ } else {
220
+ error_msg = `Structure has no lattice or sites; cannot compute coordination`
221
+ }
222
+ } catch (exc) {
223
+ error_msg = `Failed to process structure: ${
224
+ exc instanceof Error ? exc.message : String(exc)
225
+ }`
156
226
  }
157
- };
158
- const handle_file_drop = create_file_drop_handler({
227
+ }
228
+
229
+ const handle_file_drop = create_file_drop_handler({
159
230
  allow: () => allow_file_drop,
160
- on_drop: (content, filename) => (on_file_drop || compute_and_add)(content, filename),
231
+ on_drop: (content, filename) =>
232
+ (on_file_drop || compute_and_add)(content, filename),
161
233
  on_error: (msg) => {
162
- error_msg = msg;
234
+ error_msg = msg
163
235
  },
164
236
  set_loading: (val) => {
165
- loading = val;
166
- if (val)
167
- [error_msg, dragover] = [undefined, false];
237
+ loading = val
238
+ if (val) [error_msg, dragover] = [undefined, false]
168
239
  },
169
- });
170
- let display = $state({ x_zero_line: false, y_zero_line: false });
171
- // Update display when orientation changes
172
- $effect(() => {
173
- display.x_zero_line = is_horizontal;
174
- display.y_zero_line = !is_horizontal;
175
- });
176
- const cn_axis = { label: `Coordination Number`, format: `d` };
177
- const count_axis = { label: `Count`, format: `d` };
240
+ })
241
+
242
+ let display = $state({ x_zero_line: false, y_zero_line: false })
243
+ // Update display when orientation changes
244
+ $effect(() => {
245
+ display.x_zero_line = is_horizontal
246
+ display.y_zero_line = !is_horizontal
247
+ })
248
+
249
+ const cn_axis = { label: `Coordination Number`, format: `d` }
250
+ const count_axis = { label: `Count`, format: `d` }
178
251
  </script>
179
252
 
180
253
  <StatusMessage bind:message={error_msg} type="error" dismissible />
@@ -1,26 +1,69 @@
1
- <script lang="ts">let { symbol = ``, name = ``, shells, adapt_size = true, shell_width = 20, size = adapt_size ? (shells.length + 1) * 2 * shell_width + 30 : 270, base_fill = `var(--text-color)`, orbital_period = 3, nucleus_props = {}, shell_props = {}, electron_props = {}, highlight_shell = null, number_electrons = false, electron_label_props = {}, ...rest } = $props();
2
- // Bohr atom electron orbital period is given by
3
- // T = (n^3 h^3) / (4pi^2 m K e^4 Z^2) = 1.52 * 10^-16 * n^3 / Z^2 s
4
- // with n the shell number, Z the atomic number, m the mass of the electron
5
- let _nucleus_props = $derived({
1
+ <script lang="ts">
2
+ import type { SVGAttributes } from 'svelte/elements'
3
+
4
+ type Props = SVGAttributes<SVGSVGElement> & {
5
+ // https://svelte.dev/repl/17d71b590f554b5a9eba6e04023dd41c
6
+ symbol?: string // usually H, He, etc. but can be anything
7
+ name?: string // usually Hydrogen, Helium, etc. but can be anything
8
+ shells: number[]
9
+ adapt_size?: boolean
10
+ shell_width?: number
11
+ size?: number
12
+ base_fill?: string
13
+ orbital_period?: number // time for inner-most electron orbit in seconds, 0 for no motion
14
+ // set properties like size, fill, stroke, stroke-width, for nucleus and electrons here
15
+ nucleus_props?: Record<string, string | number>
16
+ shell_props?: Record<string, string | number>
17
+ electron_props?: Record<string, string | number>
18
+ highlight_shell?: number | null
19
+ // if function, it'll be called with electron index and should return a string
20
+ number_electrons?:
21
+ | boolean
22
+ | `hierarchical`
23
+ | `sequential`
24
+ | ((idx: number) => string)
25
+ electron_label_props?: Record<string, string | number>
26
+ }
27
+
28
+ let {
29
+ symbol = ``,
30
+ name = ``,
31
+ shells,
32
+ adapt_size = true,
33
+ shell_width = 20,
34
+ size = adapt_size ? (shells.length + 1) * 2 * shell_width + 30 : 270,
35
+ base_fill = `var(--text-color)`,
36
+ orbital_period = 3,
37
+ nucleus_props = {},
38
+ shell_props = {},
39
+ electron_props = {},
40
+ highlight_shell = null,
41
+ number_electrons = false,
42
+ electron_label_props = {},
43
+ ...rest
44
+ }: Props = $props()
45
+
46
+ // Bohr atom electron orbital period is given by
47
+ // T = (n^3 h^3) / (4pi^2 m K e^4 Z^2) = 1.52 * 10^-16 * n^3 / Z^2 s
48
+ // with n the shell number, Z the atomic number, m the mass of the electron
49
+ let _nucleus_props = $derived({
6
50
  r: 20,
7
51
  fill: base_fill,
8
52
  'fill-opacity': `0.3`,
9
53
  ...nucleus_props,
10
- });
11
- let _shell_props = $derived({
54
+ })
55
+ let _shell_props = $derived({
12
56
  stroke: base_fill,
13
57
  fill: `none`,
14
58
  ...shell_props,
15
- });
16
- let _electron_props = $derived({
59
+ })
60
+ let _electron_props = $derived({
17
61
  r: 3,
18
62
  stroke: base_fill,
19
63
  fill: `blue`,
20
64
  ...electron_props,
21
- });
22
- let viewBox = $derived(`-${size / 2}, -${size / 2}, ${size}, ${size}`);
23
- export {};
65
+ })
66
+ let viewBox = $derived(`-${size / 2}, -${size / 2}, ${size}, ${size}`)
24
67
  </script>
25
68
 
26
69
  <svg
@@ -1,5 +1,10 @@
1
- <script lang="ts">let { element, ...rest } = $props();
2
- export {};
1
+ <script lang="ts">
2
+ import type { ChemicalElement } from './'
3
+ import type { HTMLAttributes } from 'svelte/elements'
4
+
5
+ let { element, ...rest }: HTMLAttributes<HTMLHeadingElement> & {
6
+ element: ChemicalElement
7
+ } = $props()
3
8
  </script>
4
9
 
5
10
  <h2 {...rest}>
@@ -1,12 +1,18 @@
1
- <script lang="ts">import Icon from '../Icon.svelte';
2
- let { element, missing_msg = `No image for `, ...rest } = $props();
3
- let { name, number } = $derived(element ?? {});
4
- let file = $derived(`elements/${number}-${name?.toLowerCase()}.avif`);
5
- let hidden = $state(false);
6
- $effect.pre(() => {
7
- if (file)
8
- hidden = false;
9
- }); // reset hidden to false when file changes
1
+ <script lang="ts">
2
+ import type { ChemicalElement } from './'
3
+ import Icon from '../Icon.svelte'
4
+ import type { HTMLAttributes } from 'svelte/elements'
5
+
6
+ let { element, missing_msg = `No image for `, ...rest }:
7
+ & HTMLAttributes<HTMLImageElement | HTMLDivElement>
8
+ & { element: ChemicalElement; missing_msg?: string } = $props()
9
+
10
+ let { name, number } = $derived(element ?? {})
11
+ let file = $derived(`elements/${number}-${name?.toLowerCase()}.avif`)
12
+ let hidden = $state(false)
13
+ $effect.pre(() => {
14
+ if (file) hidden = false
15
+ }) // reset hidden to false when file changes
10
16
  </script>
11
17
 
12
18
  {#if name && number}
@@ -1,7 +1,13 @@
1
- <script lang="ts">import Icon from '../Icon.svelte';
2
- import { format_num } from '../labels';
3
- import ElementHeading from './ElementHeading.svelte';
4
- let { element, ...rest } = $props();
1
+ <script lang="ts">
2
+ import type { ChemicalElement } from './'
3
+ import Icon from '../Icon.svelte'
4
+ import { format_num } from '../labels'
5
+ import ElementHeading from './ElementHeading.svelte'
6
+ import type { HTMLAttributes } from 'svelte/elements'
7
+
8
+ let { element, ...rest }: HTMLAttributes<HTMLDivElement> & {
9
+ element: ChemicalElement | null
10
+ } = $props()
5
11
  </script>
6
12
 
7
13
  {#if element}