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,94 +1,158 @@
1
- <script lang="ts">import { contrast_color, is_color, pick_contrast_color } from '../colors';
2
- import { format_num } from '../labels';
3
- import { colors, selected } from '../state.svelte';
4
- let { element, bg_color = undefined, show_symbol = true, show_number = undefined, // auto-determine based on multi-value splits
5
- show_name = true, value = undefined, symbol_style = ``, active = false, href = undefined, luminance_threshold = 0.7, text_color = $bindable(), float_fmt = undefined, node = $bindable(null), label = undefined, bg_colors = [], show_values = undefined, split_layout = undefined, // auto-determine based on value count if not specified
6
- onclick, ...rest } = $props();
7
- // background color defaults to category color (initialized in colors/index.ts, user editable in PeriodicTableControls.svelte)
8
- let fallback_bg_color = $derived(bg_color ?? colors.category[element.category] ?? `#cccccc`);
9
- // Compute contrast text color from background when in heatmap mode (single bg_color)
10
- let computed_text_color = $derived(text_color ??
11
- (bg_color && !Array.isArray(value)
1
+ <script lang="ts">
2
+ import { contrast_color, is_color, pick_contrast_color } from '../colors'
3
+ import type { ChemicalElement } from './'
4
+ import { format_num } from '../labels'
5
+ import { colors, selected } from '../state.svelte'
6
+ import type { HTMLAttributes } from 'svelte/elements'
7
+
8
+ type SplitLayout =
9
+ | `diagonal`
10
+ | `horizontal`
11
+ | `vertical`
12
+ | `triangular`
13
+ | `quadrant`
14
+ let {
15
+ element,
16
+ bg_color = undefined,
17
+ show_symbol = true,
18
+ show_number = undefined, // auto-determine based on multi-value splits
19
+ show_name = true,
20
+ value = undefined,
21
+ symbol_style = ``,
22
+ active = false,
23
+ href = undefined,
24
+ luminance_threshold = 0.7,
25
+ text_color = $bindable(),
26
+ float_fmt = undefined,
27
+ node = $bindable(null),
28
+ label = undefined,
29
+ bg_colors = [],
30
+ show_values = undefined,
31
+ split_layout = undefined, // auto-determine based on value count if not specified
32
+ onclick,
33
+ ...rest
34
+ }: Omit<HTMLAttributes<HTMLElement>, `onclick`> & {
35
+ element: ChemicalElement
36
+ bg_color?: string
37
+ show_symbol?: boolean
38
+ show_number?: boolean
39
+ show_name?: boolean
40
+ value?: number | number[] | string | string[] | false
41
+ symbol_style?: string
42
+ active?: boolean
43
+ href?: string
44
+ // at what background color lightness text color switches from black to white
45
+ luminance_threshold?: number
46
+ text_color?: string
47
+ float_fmt?: string
48
+ node?: HTMLElement | null
49
+ label?: string
50
+ // array of background colors for multi-segment tiles
51
+ bg_colors?: (string | null)[]
52
+ show_values?: boolean // explicitly control whether to show values when colors are passed
53
+ // control the layout of multi-value splits
54
+ split_layout?: SplitLayout
55
+ onclick?: (data: { element: ChemicalElement; event: MouseEvent }) => void
56
+ } = $props()
57
+
58
+ // background color defaults to category color (initialized in colors/index.ts, user editable in PeriodicTableControls.svelte)
59
+ let fallback_bg_color = $derived(
60
+ bg_color ?? colors.category[element.category] ?? `#cccccc`,
61
+ )
62
+
63
+ // Compute contrast text color from background when in heatmap mode (single bg_color)
64
+ let computed_text_color = $derived(
65
+ text_color ??
66
+ (bg_color && !Array.isArray(value)
12
67
  ? pick_contrast_color({ bg_color, luminance_threshold })
13
- : undefined));
14
- // Determine if we should show the atomic number
15
- const should_show_number = $derived.by(() => {
16
- if (show_number !== undefined)
17
- return show_number;
68
+ : undefined),
69
+ )
70
+
71
+ // Determine if we should show the atomic number
72
+ const should_show_number = $derived.by(() => {
73
+ if (show_number !== undefined) return show_number
18
74
  // Hide number for multi-value splits to prevent overlap with value labels
19
- if (Array.isArray(value) && value.length > 1)
20
- return false;
21
- return true;
22
- });
23
- // Helper function to format values appropriately
24
- const format_value = (val) => {
25
- if (is_color(val))
26
- return show_values === true ? val.toString() : ``;
75
+ if (Array.isArray(value) && value.length > 1) return false
76
+ return true
77
+ })
78
+
79
+ // Helper function to format values appropriately
80
+ const format_value = (val: string | number): string => {
81
+ if (is_color(val)) return show_values === true ? val.toString() : ``
82
+
27
83
  // Handle numeric values
28
- if (typeof val === `number`)
29
- return format_num(val, float_fmt);
84
+ if (typeof val === `number`) return format_num(val, float_fmt)
85
+
30
86
  // Handle string values - check if it's a numeric string
31
87
  if (typeof val === `string`) {
32
- const parsed_num = parseFloat(val);
33
- if (isFinite(parsed_num))
34
- return format_num(parsed_num, float_fmt);
35
- // If show_values is true, return the string as-is to preserve non-numeric strings
36
- return show_values === true ? val : ``;
88
+ const parsed_num = parseFloat(val)
89
+ if (isFinite(parsed_num)) return format_num(parsed_num, float_fmt)
90
+ // If show_values is true, return the string as-is to preserve non-numeric strings
91
+ return show_values === true ? val : ``
37
92
  }
38
- return ``;
39
- };
40
- // Determine if we should show values - default to false if any array element is a color
41
- const should_show_values = $derived.by(() => {
42
- if (show_values !== undefined)
43
- return show_values;
44
- if (Array.isArray(value))
45
- return !value.some(is_color);
46
- return !is_color(value);
47
- });
48
- // Get the appropriate CSS classes for segments and positions based on layout
49
- const layout_config = $derived.by(() => {
50
- if (!Array.isArray(value))
51
- return null;
52
- const count = value.length;
93
+
94
+ return ``
95
+ }
96
+
97
+ // Determine if we should show values - default to false if any array element is a color
98
+ const should_show_values = $derived.by(() => {
99
+ if (show_values !== undefined) return show_values
100
+ if (Array.isArray(value)) return !value.some(is_color)
101
+ return !is_color(value)
102
+ })
103
+
104
+ // Get the appropriate CSS classes for segments and positions based on layout
105
+ const layout_config = $derived.by(() => {
106
+ if (!Array.isArray(value)) return null
107
+
108
+ const count = value.length
53
109
  // Use explicit split_layout or auto-determine based on count
54
110
  const layout = split_layout ?? {
55
- 2: `diagonal`,
56
- 3: `horizontal`,
57
- 4: `quadrant`,
58
- }[count];
59
- if (!layout)
60
- return null;
111
+ 2: `diagonal`,
112
+ 3: `horizontal`,
113
+ 4: `quadrant`,
114
+ }[count] as SplitLayout | undefined
115
+
116
+ if (!layout) return null
117
+
61
118
  if (layout === `diagonal` && count === 2) {
62
- return {
63
- segments: [`diagonal-top`, `diagonal-bottom`],
64
- positions: [`top-left`, `bottom-right`],
65
- };
119
+ return {
120
+ segments: [`diagonal-top`, `diagonal-bottom`],
121
+ positions: [`top-left`, `bottom-right`],
122
+ }
66
123
  }
124
+
67
125
  if (layout === `horizontal` && count === 3) {
68
- return {
69
- segments: [`horizontal-top`, `horizontal-middle`, `horizontal-bottom`],
70
- positions: [`bar-top-left`, `bar-middle-right`, `bar-bottom-left`],
71
- };
126
+ return {
127
+ segments: [`horizontal-top`, `horizontal-middle`, `horizontal-bottom`],
128
+ positions: [`bar-top-left`, `bar-middle-right`, `bar-bottom-left`],
129
+ }
72
130
  }
131
+
73
132
  if (layout === `vertical` && count === 3) {
74
- return {
75
- segments: [`vertical-left`, `vertical-middle`, `vertical-right`],
76
- positions: [`bar-left-top`, `bar-middle-bottom`, `bar-right-top`],
77
- };
133
+ return {
134
+ segments: [`vertical-left`, `vertical-middle`, `vertical-right`],
135
+ positions: [`bar-left-top`, `bar-middle-bottom`, `bar-right-top`],
136
+ }
78
137
  }
138
+
79
139
  if (layout === `triangular` && count === 4) {
80
- return {
81
- segments: [`top`, `right`, `bottom`, `left`].map((pos) => `triangle-${pos}`),
82
- positions: [`top`, `right`, `bottom`, `left`].map((pos) => `triangle-${pos}-pos`),
83
- };
140
+ return {
141
+ segments: [`top`, `right`, `bottom`, `left`].map((pos) => `triangle-${pos}`),
142
+ positions: [`top`, `right`, `bottom`, `left`].map((pos) =>
143
+ `triangle-${pos}-pos`
144
+ ),
145
+ }
84
146
  }
147
+
85
148
  if (layout === `quadrant` && count === 4) {
86
- const segments = [`tl`, `tr`, `bl`, `br`].map((pos) => `quadrant-${pos}`);
87
- const positions = [`tl`, `tr`, `bl`, `br`].map((pos) => `value-quadrant-${pos}`);
88
- return { segments, positions };
149
+ const segments = [`tl`, `tr`, `bl`, `br`].map((pos) => `quadrant-${pos}`)
150
+ const positions = [`tl`, `tr`, `bl`, `br`].map((pos) => `value-quadrant-${pos}`)
151
+ return { segments, positions }
89
152
  }
90
- return null;
91
- });
153
+
154
+ return null
155
+ })
92
156
  </script>
93
157
 
94
158
  <svelte:element
@@ -1,17 +1,45 @@
1
- <script lang="ts">let { protons, neutrons, size = 100, radius = $bindable(size / 2), proton_color = `cornflowerblue`, neutron_color = `orange`, stroke = ``, proton_label = ` P`, neutron_label = ` N`, text_color = `white`, symbol = ``, ...rest } = $props();
2
- $effect(() => {
3
- radius = size / 2;
4
- });
5
- let proton_frac = $derived(protons / (protons + neutrons));
6
- let neutron_frac = $derived(1 - proton_frac);
7
- let proton_circ = $derived(Math.PI * radius * proton_frac);
8
- let dash_array = $derived(`0 ${Math.PI * radius - proton_circ} ${proton_circ}`);
9
- let text = $derived({
1
+ <script lang="ts">
2
+ import type { SVGAttributes } from 'svelte/elements'
3
+
4
+ let {
5
+ protons,
6
+ neutrons,
7
+ size = 100,
8
+ radius = $bindable(size / 2),
9
+ proton_color = `cornflowerblue`,
10
+ neutron_color = `orange`,
11
+ stroke = ``,
12
+ proton_label = ` P`,
13
+ neutron_label = ` N`,
14
+ text_color = `white`,
15
+ symbol = ``,
16
+ ...rest
17
+ }: SVGAttributes<SVGSVGElement> & {
18
+ protons: number
19
+ neutrons: number
20
+ radius?: number
21
+ size?: number
22
+ proton_color?: string
23
+ neutron_color?: string
24
+ stroke?: string
25
+ proton_label?: string
26
+ neutron_label?: string
27
+ text_color?: string
28
+ symbol?: string
29
+ } = $props()
30
+
31
+ $effect(() => {
32
+ radius = size / 2
33
+ })
34
+ let proton_frac = $derived(protons / (protons + neutrons))
35
+ let neutron_frac = $derived(1 - proton_frac)
36
+ let proton_circ = $derived(Math.PI * radius * proton_frac)
37
+ let dash_array = $derived(`0 ${Math.PI * radius - proton_circ} ${proton_circ}`)
38
+ let text = $derived({
10
39
  'dominant-baseline': `middle`,
11
40
  'text-anchor': `middle`,
12
41
  fill: text_color,
13
- });
14
- export {};
42
+ })
15
43
  </script>
16
44
 
17
45
  <svg width="100%" height="100%" viewBox="0 0 {size} {size}" {...rest}>
@@ -1,8 +1,19 @@
1
- <script lang="ts">import Icon from '../Icon.svelte';
2
- // Generic feedback component that shows a transient icon at a specific position.
3
- // Commonly used for copy-to-clipboard feedback, but can display icons for
4
- // various user interactions.
5
- let { visible = $bindable(false), position = { x: 0, y: 0 }, icon = `Check`, } = $props();
1
+ <script lang="ts">
2
+ import Icon from '../Icon.svelte'
3
+ import type { IconName } from '../icons'
4
+
5
+ // Generic feedback component that shows a transient icon at a specific position.
6
+ // Commonly used for copy-to-clipboard feedback, but can display icons for
7
+ // various user interactions.
8
+ let {
9
+ visible = $bindable(false),
10
+ position = { x: 0, y: 0 },
11
+ icon = `Check`,
12
+ }: {
13
+ visible?: boolean
14
+ position: { x: number; y: number }
15
+ icon?: IconName
16
+ } = $props()
6
17
  </script>
7
18
 
8
19
  {#if visible}
@@ -1,5 +1,13 @@
1
- <script lang="ts">import Icon from '../Icon.svelte';
2
- let { visible = false, message = `Drop JSON file to load phase diagram data`, } = $props();
1
+ <script lang="ts">
2
+ import Icon from '../Icon.svelte'
3
+
4
+ let {
5
+ visible = false,
6
+ message = `Drop JSON file to load phase diagram data`,
7
+ }: {
8
+ visible?: boolean
9
+ message?: string
10
+ } = $props()
3
11
  </script>
4
12
 
5
13
  {#if visible}
@@ -1,5 +1,7 @@
1
- <script lang="ts">let { text, ...rest } = $props();
2
- export {};
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements'
3
+
4
+ let { text, ...rest }: { text?: string } & HTMLAttributes<HTMLDivElement> = $props()
3
5
  </script>
4
6
 
5
7
  <div class="spinner" role="status" aria-live="polite" aria-busy="true" {...rest}>
@@ -1,5 +1,11 @@
1
- <script lang="ts">let { message = $bindable(), type = `info`, dismissible = false, ...rest } = $props();
2
- export {};
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements'
3
+
4
+ let { message = $bindable(), type = `info`, dismissible = false, ...rest }: {
5
+ message?: string
6
+ type?: `info` | `error` | `warning`
7
+ dismissible?: boolean
8
+ } & HTMLAttributes<HTMLDivElement> = $props()
3
9
  </script>
4
10
 
5
11
  {#if message}
@@ -1,103 +1,133 @@
1
- <script lang="ts">import { ScatterPlot } from '../plot';
2
- import { SvelteSet } from 'svelte/reactivity';
3
- import { compute_fermi_slice } from './compute';
4
- import { BAND_COLORS } from './constants';
5
- let { fermi_data, miller_indices = [0, 0, 1], distance = 0, line_width = 2, show_axes = true, axis_labels, band_colors = BAND_COLORS, show_legend = true, on_error, children, ...rest } = $props();
6
- let wrapper = $state(undefined);
7
- let hidden_bands = new SvelteSet();
8
- // Compute axis labels from Miller indices (subscript z doesn't exist in Unicode)
9
- let labels = $derived.by(() => {
10
- if (axis_labels)
11
- return axis_labels;
12
- const K = [`kₓ`, `kᵧ`, `kz`];
13
- const zeros = miller_indices.flatMap((val, idx) => (val === 0 ? [idx] : []));
14
- if (zeros.length === 2)
15
- return [K[zeros[0]], K[zeros[1]]];
16
- if (zeros.length === 1)
17
- return [`k⊥`, K[zeros[0]]];
18
- return [`k₁`, `k₂`];
19
- });
20
- // Compute slice with error handling
21
- let slice_data = $state(null);
22
- $effect(() => {
1
+ <script lang="ts">
2
+ import type { Vec3 } from '../math'
3
+ import type { DataSeries } from '../plot'
4
+ import { ScatterPlot } from '../plot'
5
+ import type { Snippet } from 'svelte'
6
+ import type { HTMLAttributes } from 'svelte/elements'
7
+ import { SvelteSet } from 'svelte/reactivity'
8
+ import { compute_fermi_slice } from './compute'
9
+ import { BAND_COLORS } from './constants'
10
+ import type { FermiSliceData, FermiSurfaceData } from './types'
11
+
12
+ let {
13
+ fermi_data,
14
+ miller_indices = [0, 0, 1],
15
+ distance = 0,
16
+ line_width = 2,
17
+ show_axes = true,
18
+ axis_labels,
19
+ band_colors = BAND_COLORS,
20
+ show_legend = true,
21
+ on_error,
22
+ children,
23
+ ...rest
24
+ }: {
25
+ fermi_data?: FermiSurfaceData
26
+ miller_indices?: Vec3
27
+ distance?: number
28
+ line_width?: number
29
+ show_axes?: boolean
30
+ axis_labels?: [string, string]
31
+ band_colors?: readonly string[]
32
+ show_legend?: boolean
33
+ on_error?: (error: Error) => void
34
+ children?: Snippet<
35
+ [{ slice_data: FermiSliceData | null; export_svg: () => string | null }]
36
+ >
37
+ } & HTMLAttributes<HTMLDivElement> = $props()
38
+
39
+ let wrapper = $state<HTMLDivElement | undefined>(undefined)
40
+ let hidden_bands = new SvelteSet<number>()
41
+
42
+ // Compute axis labels from Miller indices (subscript z doesn't exist in Unicode)
43
+ let labels = $derived.by((): [string, string] => {
44
+ if (axis_labels) return axis_labels
45
+ const K = [`kₓ`, `kᵧ`, `kz`] as const
46
+ const zeros = miller_indices.flatMap((val, idx) => (val === 0 ? [idx] : []))
47
+ if (zeros.length === 2) return [K[zeros[0]], K[zeros[1]]]
48
+ if (zeros.length === 1) return [`k⊥`, K[zeros[0]]]
49
+ return [`k₁`, `k₂`]
50
+ })
51
+
52
+ // Compute slice with error handling
53
+ let slice_data = $state<FermiSliceData | null>(null)
54
+ $effect(() => {
23
55
  if (!fermi_data) {
24
- slice_data = null;
25
- return;
56
+ slice_data = null
57
+ return
26
58
  }
27
59
  try {
28
- slice_data = compute_fermi_slice(fermi_data, { miller_indices, distance });
60
+ slice_data = compute_fermi_slice(fermi_data, { miller_indices, distance })
61
+ } catch (err) {
62
+ slice_data = null
63
+ on_error?.(err instanceof Error ? err : new Error(String(err)))
29
64
  }
30
- catch (err) {
31
- slice_data = null;
32
- on_error?.(err instanceof Error ? err : new Error(String(err)));
33
- }
34
- });
35
- // Transform isolines to ScatterPlot series
36
- let series = $derived(slice_data?.isolines.map((iso, idx) => ({
37
- id: `iso-${iso.band_index}-${idx}`,
38
- x: iso.points_2d.map((pt) => pt[0]),
39
- y: iso.points_2d.map((pt) => pt[1]),
40
- markers: `line`,
41
- visible: !hidden_bands.has(iso.band_index),
42
- label: `Band ${iso.band_index + 1}`,
43
- line_style: {
65
+ })
66
+
67
+ // Transform isolines to ScatterPlot series
68
+ let series: DataSeries[] = $derived(
69
+ slice_data?.isolines.map((iso, idx) => ({
70
+ id: `iso-${iso.band_index}-${idx}`,
71
+ x: iso.points_2d.map((pt) => pt[0]),
72
+ y: iso.points_2d.map((pt) => pt[1]),
73
+ markers: `line` as const,
74
+ visible: !hidden_bands.has(iso.band_index),
75
+ label: `Band ${iso.band_index + 1}`,
76
+ line_style: {
44
77
  stroke: band_colors[iso.band_index % band_colors.length],
45
78
  stroke_width: line_width,
46
- },
47
- })) ?? []);
48
- // Compute padded data bounds (single-pass to avoid stack overflow on large arrays)
49
- let bounds = $derived.by(() => {
50
- const isolines = slice_data?.isolines;
51
- if (!isolines?.length)
52
- return { min: [-1, -1], max: [1, 1] };
53
- let xmin = Infinity, xmax = -Infinity, ymin = Infinity, ymax = -Infinity;
79
+ },
80
+ })) ?? [],
81
+ )
82
+
83
+ // Compute padded data bounds (single-pass to avoid stack overflow on large arrays)
84
+ let bounds = $derived.by(() => {
85
+ const isolines = slice_data?.isolines
86
+ if (!isolines?.length) return { min: [-1, -1], max: [1, 1] }
87
+
88
+ let xmin = Infinity, xmax = -Infinity, ymin = Infinity, ymax = -Infinity
54
89
  for (const iso of isolines) {
55
- for (const pt of iso.points_2d) {
56
- if (pt[0] < xmin)
57
- xmin = pt[0];
58
- if (pt[0] > xmax)
59
- xmax = pt[0];
60
- if (pt[1] < ymin)
61
- ymin = pt[1];
62
- if (pt[1] > ymax)
63
- ymax = pt[1];
64
- }
90
+ for (const pt of iso.points_2d) {
91
+ if (pt[0] < xmin) xmin = pt[0]
92
+ if (pt[0] > xmax) xmax = pt[0]
93
+ if (pt[1] < ymin) ymin = pt[1]
94
+ if (pt[1] > ymax) ymax = pt[1]
95
+ }
65
96
  }
66
- if (!isFinite(xmin))
67
- return { min: [-1, -1], max: [1, 1] };
68
- const pad = 0.1, rx = xmax - xmin || 1, ry = ymax - ymin || 1;
97
+ if (!isFinite(xmin)) return { min: [-1, -1], max: [1, 1] }
98
+
99
+ const pad = 0.1, rx = xmax - xmin || 1, ry = ymax - ymin || 1
69
100
  return {
70
- min: [xmin - rx * pad, ymin - ry * pad],
71
- max: [xmax + rx * pad, ymax + ry * pad],
72
- };
73
- });
74
- function toggle_band(series_idx) {
75
- const band = slice_data?.isolines[series_idx]?.band_index;
76
- if (band === undefined)
77
- return;
78
- if (hidden_bands.has(band))
79
- hidden_bands.delete(band);
80
- else
81
- hidden_bands.add(band);
82
- }
83
- function isolate_band(series_idx) {
84
- const band = slice_data?.isolines[series_idx]?.band_index;
85
- if (band === undefined)
86
- return;
101
+ min: [xmin - rx * pad, ymin - ry * pad],
102
+ max: [xmax + rx * pad, ymax + ry * pad],
103
+ }
104
+ })
105
+
106
+ function toggle_band(series_idx: number) {
107
+ const band = slice_data?.isolines[series_idx]?.band_index
108
+ if (band === undefined) return
109
+ if (hidden_bands.has(band)) hidden_bands.delete(band)
110
+ else hidden_bands.add(band)
111
+ }
112
+
113
+ function isolate_band(series_idx: number) {
114
+ const band = slice_data?.isolines[series_idx]?.band_index
115
+ if (band === undefined) return
87
116
  const all_bands = [
88
- ...new Set(slice_data?.isolines.map((iso) => iso.band_index) ?? []),
89
- ];
90
- const is_solo = all_bands.every((b) => b === band || hidden_bands.has(b));
91
- hidden_bands.clear();
117
+ ...new Set(slice_data?.isolines.map((iso) => iso.band_index) ?? []),
118
+ ]
119
+ const is_solo = all_bands.every((bid) => bid === band || hidden_bands.has(bid))
120
+ hidden_bands.clear()
92
121
  if (!is_solo) {
93
- for (const b of all_bands) {
94
- if (b !== band)
95
- hidden_bands.add(b);
96
- }
122
+ for (const bid of all_bands) {
123
+ if (bid !== band) hidden_bands.add(bid)
124
+ }
97
125
  }
98
- }
99
- // Returns null if SVG not found, making export failures explicit
100
- const export_svg = () => wrapper?.querySelector(`svg`)?.outerHTML ?? null;
126
+ }
127
+
128
+ // Returns null if SVG not found, making export failures explicit
129
+ const export_svg = (): string | null =>
130
+ wrapper?.querySelector(`svg`)?.outerHTML ?? null
101
131
  </script>
102
132
 
103
133
  <ScatterPlot