matterviz 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/dist/EmptyState.svelte +10 -2
  2. package/dist/FilePicker.svelte +123 -82
  3. package/dist/Icon.svelte +18 -12
  4. package/dist/MillerIndexInput.svelte +27 -21
  5. package/dist/api/optimade.js +6 -6
  6. package/dist/app.css +216 -207
  7. package/dist/brillouin/BrillouinZone.svelte +292 -149
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +69 -42
  11. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte +275 -163
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  15. package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
  16. package/dist/brillouin/compute.js +11 -6
  17. package/dist/chempot-diagram/ChemPotDiagram.svelte +162 -27
  18. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +451 -281
  19. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2148 -1642
  20. package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -5
  21. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  22. package/dist/chempot-diagram/async-compute.svelte.js +77 -0
  23. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  24. package/dist/chempot-diagram/chempot-worker.js +11 -0
  25. package/dist/chempot-diagram/color.js +1 -2
  26. package/dist/chempot-diagram/compute.d.ts +10 -0
  27. package/dist/chempot-diagram/compute.js +250 -88
  28. package/dist/chempot-diagram/index.d.ts +2 -1
  29. package/dist/chempot-diagram/index.js +2 -1
  30. package/dist/chempot-diagram/temperature.js +8 -9
  31. package/dist/chempot-diagram/types.d.ts +3 -0
  32. package/dist/chempot-diagram/types.js +1 -0
  33. package/dist/colors/index.d.ts +1 -1
  34. package/dist/colors/index.js +5 -3
  35. package/dist/composition/BarChart.svelte +128 -55
  36. package/dist/composition/BubbleChart.svelte +102 -49
  37. package/dist/composition/Composition.svelte +100 -79
  38. package/dist/composition/Formula.svelte +108 -62
  39. package/dist/composition/FormulaFilter.svelte +665 -537
  40. package/dist/composition/PieChart.svelte +183 -108
  41. package/dist/composition/format.d.ts +5 -0
  42. package/dist/composition/format.js +20 -3
  43. package/dist/composition/parse.js +14 -9
  44. package/dist/convex-hull/ConvexHull.svelte +93 -40
  45. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  46. package/dist/convex-hull/ConvexHull2D.svelte +549 -360
  47. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  48. package/dist/convex-hull/ConvexHull3D.svelte +1296 -827
  49. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  50. package/dist/convex-hull/ConvexHull4D.svelte +1004 -688
  51. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  52. package/dist/convex-hull/ConvexHullControls.svelte +115 -28
  53. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +1 -1
  54. package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
  55. package/dist/convex-hull/ConvexHullStats.svelte +425 -328
  56. package/dist/convex-hull/ConvexHullTooltip.svelte +40 -16
  57. package/dist/convex-hull/GasPressureControls.svelte +104 -61
  58. package/dist/convex-hull/StructurePopup.svelte +25 -4
  59. package/dist/convex-hull/TemperatureSlider.svelte +45 -25
  60. package/dist/convex-hull/barycentric-coords.js +13 -7
  61. package/dist/convex-hull/demo-temperature.js +8 -4
  62. package/dist/convex-hull/gas-thermodynamics.js +17 -12
  63. package/dist/convex-hull/helpers.d.ts +9 -0
  64. package/dist/convex-hull/helpers.js +77 -34
  65. package/dist/convex-hull/thermodynamics.js +61 -56
  66. package/dist/convex-hull/types.d.ts +9 -14
  67. package/dist/convex-hull/types.js +0 -17
  68. package/dist/coordination/CoordinationBarPlot.svelte +227 -154
  69. package/dist/element/BohrAtom.svelte +55 -12
  70. package/dist/element/ElementHeading.svelte +7 -2
  71. package/dist/element/ElementPhoto.svelte +15 -9
  72. package/dist/element/ElementStats.svelte +10 -4
  73. package/dist/element/ElementTile.svelte +137 -73
  74. package/dist/element/Nucleus.svelte +39 -11
  75. package/dist/element/data.js +1 -1
  76. package/dist/feedback/ClickFeedback.svelte +16 -5
  77. package/dist/feedback/DragOverlay.svelte +10 -2
  78. package/dist/feedback/Spinner.svelte +4 -2
  79. package/dist/feedback/StatusMessage.svelte +8 -2
  80. package/dist/fermi-surface/FermiSlice.svelte +118 -88
  81. package/dist/fermi-surface/FermiSurface.svelte +328 -187
  82. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  83. package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
  84. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  85. package/dist/fermi-surface/FermiSurfaceScene.svelte +535 -342
  86. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  87. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
  88. package/dist/fermi-surface/compute.js +16 -20
  89. package/dist/fermi-surface/parse.js +24 -14
  90. package/dist/fermi-surface/symmetry.js +2 -7
  91. package/dist/fermi-surface/types.d.ts +3 -5
  92. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1019 -765
  93. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +1 -1
  94. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +76 -22
  95. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +2 -3
  96. package/dist/icons.js +47 -0
  97. package/dist/index.d.ts +2 -1
  98. package/dist/index.js +2 -1
  99. package/dist/io/decompress.js +1 -1
  100. package/dist/io/export.d.ts +3 -0
  101. package/dist/io/export.js +129 -143
  102. package/dist/io/is-binary.js +2 -3
  103. package/dist/io/url-drop.js +1 -2
  104. package/dist/isosurface/Isosurface.svelte +202 -148
  105. package/dist/isosurface/IsosurfaceControls.svelte +46 -28
  106. package/dist/isosurface/parse.js +34 -29
  107. package/dist/isosurface/slice.js +5 -10
  108. package/dist/isosurface/types.d.ts +2 -1
  109. package/dist/isosurface/types.js +61 -12
  110. package/dist/labels.js +11 -8
  111. package/dist/layout/FullscreenToggle.svelte +11 -2
  112. package/dist/layout/InfoCard.svelte +38 -6
  113. package/dist/layout/InfoTag.svelte +63 -32
  114. package/dist/layout/PropertyFilter.svelte +82 -37
  115. package/dist/layout/SettingsSection.svelte +85 -55
  116. package/dist/layout/SubpageGrid.svelte +10 -2
  117. package/dist/layout/json-tree/JsonNode.svelte +183 -138
  118. package/dist/layout/json-tree/JsonTree.svelte +499 -413
  119. package/dist/layout/json-tree/JsonValue.svelte +127 -99
  120. package/dist/layout/json-tree/utils.js +4 -2
  121. package/dist/marching-cubes.js +25 -2
  122. package/dist/math.d.ts +13 -17
  123. package/dist/math.js +133 -67
  124. package/dist/overlays/ContextMenu.svelte +65 -40
  125. package/dist/overlays/DraggablePane.svelte +211 -139
  126. package/dist/periodic-table/PeriodicTable.svelte +278 -145
  127. package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
  128. package/dist/periodic-table/PropertySelect.svelte +25 -7
  129. package/dist/periodic-table/TableInset.svelte +8 -3
  130. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +446 -309
  131. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  132. package/dist/phase-diagram/PhaseDiagramControls.svelte +102 -43
  133. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  134. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +63 -40
  135. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +71 -28
  136. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +1 -1
  137. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +158 -101
  138. package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
  139. package/dist/phase-diagram/build-diagram.js +9 -9
  140. package/dist/phase-diagram/colors.js +1 -3
  141. package/dist/phase-diagram/parse.js +10 -9
  142. package/dist/phase-diagram/svg-to-diagram.js +53 -49
  143. package/dist/phase-diagram/utils.d.ts +1 -0
  144. package/dist/phase-diagram/utils.js +80 -25
  145. package/dist/plot/AxisLabel.svelte +28 -3
  146. package/dist/plot/BarPlot.svelte +1182 -734
  147. package/dist/plot/BarPlot.svelte.d.ts +2 -2
  148. package/dist/plot/BarPlotControls.svelte +31 -5
  149. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  150. package/dist/plot/ColorBar.svelte +479 -329
  151. package/dist/plot/ColorScaleSelect.svelte +27 -6
  152. package/dist/plot/ElementScatter.svelte +36 -15
  153. package/dist/plot/FillArea.svelte +152 -95
  154. package/dist/plot/Histogram.svelte +934 -571
  155. package/dist/plot/Histogram.svelte.d.ts +1 -1
  156. package/dist/plot/HistogramControls.svelte +53 -9
  157. package/dist/plot/HistogramControls.svelte.d.ts +1 -1
  158. package/dist/plot/InteractiveAxisLabel.svelte +34 -11
  159. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  160. package/dist/plot/Line.svelte +63 -28
  161. package/dist/plot/PlotControls.svelte +157 -114
  162. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  163. package/dist/plot/PlotLegend.svelte +174 -91
  164. package/dist/plot/PlotTooltip.svelte +45 -6
  165. package/dist/plot/PortalSelect.svelte +175 -147
  166. package/dist/plot/ReferenceLine.svelte +76 -22
  167. package/dist/plot/ReferenceLine3D.svelte +132 -107
  168. package/dist/plot/ReferencePlane.svelte +146 -121
  169. package/dist/plot/ScatterPlot.svelte +1681 -1091
  170. package/dist/plot/ScatterPlot.svelte.d.ts +2 -2
  171. package/dist/plot/ScatterPlot3D.svelte +256 -131
  172. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  173. package/dist/plot/ScatterPlot3DControls.svelte +113 -63
  174. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
  175. package/dist/plot/ScatterPlot3DScene.svelte +608 -403
  176. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  177. package/dist/plot/ScatterPlotControls.svelte +65 -25
  178. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  179. package/dist/plot/ScatterPoint.svelte +98 -26
  180. package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
  181. package/dist/plot/SpacegroupBarPlot.svelte +142 -85
  182. package/dist/plot/Surface3D.svelte +159 -108
  183. package/dist/plot/ZeroLines.svelte +55 -3
  184. package/dist/plot/ZoomRect.svelte +4 -2
  185. package/dist/plot/axis-utils.js +1 -3
  186. package/dist/plot/data-cleaning.js +12 -28
  187. package/dist/plot/data-transform.js +2 -1
  188. package/dist/plot/fill-utils.js +2 -0
  189. package/dist/plot/layout.d.ts +4 -1
  190. package/dist/plot/layout.js +33 -14
  191. package/dist/plot/reference-line.d.ts +2 -2
  192. package/dist/plot/reference-line.js +7 -5
  193. package/dist/plot/scales.js +24 -36
  194. package/dist/plot/types.d.ts +11 -23
  195. package/dist/plot/types.js +6 -11
  196. package/dist/plot/utils/label-placement.d.ts +32 -15
  197. package/dist/plot/utils/label-placement.js +227 -66
  198. package/dist/plot/utils/series-visibility.js +2 -3
  199. package/dist/rdf/RdfPlot.svelte +143 -91
  200. package/dist/rdf/calc-rdf.js +4 -5
  201. package/dist/sanitize.d.ts +4 -0
  202. package/dist/sanitize.js +107 -0
  203. package/dist/settings.d.ts +18 -6
  204. package/dist/settings.js +46 -16
  205. package/dist/spectral/Bands.svelte +632 -453
  206. package/dist/spectral/BandsAndDos.svelte +90 -49
  207. package/dist/spectral/BrillouinBandsDos.svelte +151 -93
  208. package/dist/spectral/Dos.svelte +389 -258
  209. package/dist/spectral/helpers.js +55 -43
  210. package/dist/state.svelte.d.ts +1 -1
  211. package/dist/state.svelte.js +3 -2
  212. package/dist/structure/Arrow.svelte +59 -20
  213. package/dist/structure/AtomLegend.svelte +215 -134
  214. package/dist/structure/Bond.svelte +73 -47
  215. package/dist/structure/CanvasTooltip.svelte +10 -2
  216. package/dist/structure/CellSelect.svelte +72 -45
  217. package/dist/structure/Cylinder.svelte +33 -17
  218. package/dist/structure/Lattice.svelte +88 -33
  219. package/dist/structure/Structure.svelte +1063 -797
  220. package/dist/structure/Structure.svelte.d.ts +1 -1
  221. package/dist/structure/StructureControls.svelte +349 -118
  222. package/dist/structure/StructureExportPane.svelte +124 -89
  223. package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
  224. package/dist/structure/StructureInfoPane.svelte +304 -237
  225. package/dist/structure/StructureScene.svelte +879 -443
  226. package/dist/structure/StructureScene.svelte.d.ts +15 -7
  227. package/dist/structure/atom-properties.js +8 -8
  228. package/dist/structure/bonding.js +6 -7
  229. package/dist/structure/export.js +14 -29
  230. package/dist/structure/ferrox-wasm.js +1 -1
  231. package/dist/structure/index.d.ts +13 -3
  232. package/dist/structure/index.js +83 -23
  233. package/dist/structure/measure.d.ts +2 -2
  234. package/dist/structure/measure.js +4 -44
  235. package/dist/structure/parse.js +113 -141
  236. package/dist/structure/partial-occupancy.js +7 -10
  237. package/dist/structure/pbc.d.ts +1 -0
  238. package/dist/structure/pbc.js +16 -6
  239. package/dist/structure/supercell.d.ts +2 -2
  240. package/dist/structure/supercell.js +12 -22
  241. package/dist/structure/validation.js +1 -2
  242. package/dist/symmetry/SymmetryStats.svelte +84 -41
  243. package/dist/symmetry/WyckoffTable.svelte +26 -6
  244. package/dist/symmetry/cell-transform.js +5 -3
  245. package/dist/symmetry/index.js +8 -7
  246. package/dist/symmetry/spacegroups.js +148 -148
  247. package/dist/table/HeatmapTable.svelte +790 -554
  248. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  249. package/dist/table/ToggleMenu.svelte +125 -92
  250. package/dist/table/index.js +2 -4
  251. package/dist/theme/ThemeControl.svelte +21 -12
  252. package/dist/time.js +4 -1
  253. package/dist/tooltip/TooltipContent.svelte +33 -8
  254. package/dist/trajectory/Trajectory.svelte +758 -558
  255. package/dist/trajectory/TrajectoryError.svelte +14 -3
  256. package/dist/trajectory/TrajectoryExportPane.svelte +137 -83
  257. package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
  258. package/dist/trajectory/extract.js +10 -26
  259. package/dist/trajectory/format-detect.js +5 -5
  260. package/dist/trajectory/frame-reader.d.ts +1 -1
  261. package/dist/trajectory/frame-reader.js +5 -12
  262. package/dist/trajectory/helpers.d.ts +0 -1
  263. package/dist/trajectory/helpers.js +2 -17
  264. package/dist/trajectory/index.js +14 -12
  265. package/dist/trajectory/parse/ase.js +5 -4
  266. package/dist/trajectory/parse/hdf5.js +26 -18
  267. package/dist/trajectory/parse/index.js +13 -18
  268. package/dist/trajectory/parse/lammps.js +17 -7
  269. package/dist/trajectory/parse/vasp.js +5 -2
  270. package/dist/trajectory/parse/xyz.js +8 -7
  271. package/dist/trajectory/plotting.js +13 -8
  272. package/dist/utils.d.ts +1 -0
  273. package/dist/utils.js +13 -0
  274. package/dist/xrd/XrdPlot.svelte +337 -247
  275. package/dist/xrd/broadening.js +14 -9
  276. package/dist/xrd/calc-xrd.js +12 -18
  277. package/dist/xrd/parse.d.ts +1 -1
  278. package/dist/xrd/parse.js +17 -17
  279. package/package.json +99 -103
  280. package/readme.md +1 -1
  281. /package/dist/theme/{themes.js → themes.mjs} +0 -0
@@ -51,7 +51,7 @@ declare function $$render<Metadata extends Record<string, unknown> = Record<stri
51
51
  height?: number;
52
52
  };
53
53
  exports: {};
54
- bindings: "hovered_point" | "scene" | "camera" | "orbit_controls";
54
+ bindings: "camera" | "hovered_point" | "scene" | "orbit_controls";
55
55
  slots: {};
56
56
  events: {};
57
57
  };
@@ -59,7 +59,7 @@ declare class __sveltets_Render<Metadata extends Record<string, unknown> = Recor
59
59
  props(): ReturnType<typeof $$render<Metadata>>['props'];
60
60
  events(): ReturnType<typeof $$render<Metadata>>['events'];
61
61
  slots(): ReturnType<typeof $$render<Metadata>>['slots'];
62
- bindings(): "hovered_point" | "scene" | "camera" | "orbit_controls";
62
+ bindings(): "camera" | "hovered_point" | "scene" | "orbit_controls";
63
63
  exports(): {};
64
64
  }
65
65
  interface $$IsomorphicComponent {
@@ -1,28 +1,68 @@
1
- <script lang="ts">import { SettingsSection } from '../layout';
2
- import { PlotControls } from './';
3
- import { DEFAULTS } from '../settings';
4
- import { tooltip } from 'svelte-multiselect/attachments';
5
- // Unique ID prefix to avoid conflicts when multiple instances on same page
6
- const uid = crypto.randomUUID().slice(0, 8);
7
- let { series = [], x_axis = $bindable({}), x2_axis = $bindable({}), y_axis = $bindable({}), y2_axis = $bindable({}), display = $bindable({}), styles = $bindable({}), selected_series_idx = $bindable(0), on_touch, children, ...rest } = $props();
8
- let non_null_series = $derived(series.filter((srs) => srs != null));
9
- let visible_series = $derived(non_null_series.filter((srs) => (srs.visible ?? true)));
10
- let has_multiple_series = $derived(non_null_series.length > 1);
11
- // Derive what marker types are present, and whether color/size are data-driven
12
- const markers_include = (mode) => visible_series.some((srs) => (srs?.markers ?? `line+points`).includes(mode));
13
- let has_any_lines = $derived(markers_include(`line`));
14
- let has_any_points = $derived(markers_include(`points`));
15
- let has_color_data = $derived(visible_series.some((srs) => srs?.color_values?.some((val) => val != null)));
16
- let has_size_data = $derived(visible_series.some((srs) => srs?.size_values?.some((val) => val != null)));
17
- $effect(() => {
18
- styles.show_points ??= DEFAULTS.scatter.show_points;
19
- styles.show_lines ??= DEFAULTS.scatter.show_lines;
20
- });
21
- const touch = ({ target }) => {
22
- const key = target?.closest(`[data-key]`)?.getAttribute(`data-key`);
23
- if (key)
24
- on_touch?.(key);
25
- };
1
+ <script lang="ts">
2
+ import { SettingsSection } from '../layout'
3
+ import { PlotControls } from './'
4
+ import type {
5
+ DataSeries,
6
+ PlotConfig,
7
+ PlotControlsProps,
8
+ StyleOverrides,
9
+ } from './types'
10
+ import { DEFAULTS } from '../settings'
11
+ import type { Snippet } from 'svelte'
12
+ import { tooltip } from 'svelte-multiselect/attachments'
13
+
14
+ // Unique ID prefix to avoid conflicts when multiple instances on same page
15
+ const uid = crypto.randomUUID().slice(0, 8)
16
+
17
+ let {
18
+ series = [],
19
+ x_axis = $bindable({}),
20
+ x2_axis = $bindable({}),
21
+ y_axis = $bindable({}),
22
+ y2_axis = $bindable({}),
23
+ display = $bindable({}),
24
+ styles = $bindable({}),
25
+ selected_series_idx = $bindable(0),
26
+ on_touch,
27
+ children,
28
+ ...rest
29
+ }: Omit<PlotControlsProps, `children` | `post_children`> & {
30
+ series?: readonly DataSeries[]
31
+ styles?: StyleOverrides
32
+ selected_series_idx?: number
33
+ on_touch?: (key: string) => void
34
+ children?: Snippet<
35
+ [{ styles: StyleOverrides; selected_series_idx: number } & Required<PlotConfig>]
36
+ >
37
+ } = $props()
38
+
39
+ let non_null_series = $derived(series.filter((srs) => srs != null))
40
+ let visible_series = $derived(
41
+ non_null_series.filter((srs) => (srs.visible ?? true)),
42
+ )
43
+ let has_multiple_series = $derived(non_null_series.length > 1)
44
+
45
+ // Derive what marker types are present, and whether color/size are data-driven
46
+ const markers_include = (mode: string) =>
47
+ visible_series.some((srs) => (srs?.markers ?? `line+points`).includes(mode))
48
+ let has_any_lines = $derived(markers_include(`line`))
49
+ let has_any_points = $derived(markers_include(`points`))
50
+ let has_color_data = $derived(
51
+ visible_series.some((srs) => srs?.color_values?.some((val) => val != null)),
52
+ )
53
+ let has_size_data = $derived(
54
+ visible_series.some((srs) => srs?.size_values?.some((val) => val != null)),
55
+ )
56
+
57
+ $effect(() => { // Initialize show_points/show_lines from defaults
58
+ styles.show_points ??= DEFAULTS.scatter.show_points
59
+ styles.show_lines ??= DEFAULTS.scatter.show_lines
60
+ })
61
+
62
+ const touch = ({ target }: Event) => {
63
+ const key = (target as Element)?.closest(`[data-key]`)?.getAttribute(`data-key`)
64
+ if (key) on_touch?.(key)
65
+ }
26
66
  </script>
27
67
 
28
68
  <PlotControls
@@ -12,6 +12,6 @@ type $$ComponentProps = Omit<PlotControlsProps, `children` | `post_children`> &
12
12
  } & Required<PlotConfig>
13
13
  ]>;
14
14
  };
15
- declare const ScatterPlotControls: import("svelte").Component<$$ComponentProps, {}, "display" | "x_axis" | "x2_axis" | "y_axis" | "y2_axis" | "selected_series_idx" | "styles">;
15
+ declare const ScatterPlotControls: import("svelte").Component<$$ComponentProps, {}, "display" | "x_axis" | "y_axis" | "x2_axis" | "y2_axis" | "selected_series_idx" | "styles">;
16
16
  type ScatterPlotControls = ReturnType<typeof ScatterPlotControls>;
17
17
  export default ScatterPlotControls;
@@ -1,27 +1,61 @@
1
- <script lang="ts">import { symbol_map } from '../labels';
2
- import { DEFAULTS } from '../settings';
3
- import * as d3_symbols from 'd3-shape';
4
- import { symbol } from 'd3-shape';
5
- import { cubicOut } from 'svelte/easing';
6
- import { Tween } from 'svelte/motion';
7
- let { x, y, style = {}, hover = {}, label = {}, offset = { x: 0, y: 0 }, point_tween = $bindable({}), origin = $bindable({ x: 0, y: 0 }), is_hovered = false, is_selected = false, ...rest } = $props();
8
- // get the SVG path data as 'd' attribute
9
- function get_symbol_path() {
10
- const symbol_key = style.symbol_type ?? DEFAULTS.scatter.symbol_type;
11
- const symbol_type = symbol_map[symbol_key] ?? d3_symbols.symbolCircle;
12
- const size = style.symbol_size ?? Math.PI * Math.pow(style.radius ?? 2, 2);
13
- return symbol().type(symbol_type).size(size)() || ``;
14
- }
15
- let marker_path = $derived.by(get_symbol_path);
16
- const default_tween_props = {
1
+ <script lang="ts">
2
+ import { type D3SymbolName, symbol_map } from '../labels'
3
+ import type { HoverStyle, LabelStyle, Point } from './'
4
+ import type { PointStyle, TweenedOptions, XyObj } from './types'
5
+ import { DEFAULTS } from '../settings'
6
+ import * as d3_symbols from 'd3-shape'
7
+ import { symbol } from 'd3-shape'
8
+ import { cubicOut } from 'svelte/easing'
9
+ import type { SVGAttributes } from 'svelte/elements'
10
+ import { Tween } from 'svelte/motion'
11
+
12
+ let {
13
+ x,
14
+ y,
15
+ style = {},
16
+ hover = {},
17
+ label = {},
18
+ offset = { x: 0, y: 0 },
19
+ point_tween = $bindable({}),
20
+ origin = $bindable({ x: 0, y: 0 }),
21
+ is_hovered = false,
22
+ is_selected = false,
23
+ leader_line_threshold = 15,
24
+ ...rest
25
+ }: Omit<SVGAttributes<SVGGElement>, `style` | `offset` | `origin` | `transform`> & {
26
+ x: number
27
+ y: number
28
+ style?: PointStyle
29
+ hover?: HoverStyle
30
+ label?: LabelStyle
31
+ offset?: Point[`offset`]
32
+ point_tween?: TweenedOptions<XyObj>
33
+ origin?: XyObj
34
+ is_hovered?: boolean
35
+ is_selected?: boolean
36
+ leader_line_threshold?: number
37
+ } = $props()
38
+
39
+ // get the SVG path data as 'd' attribute
40
+ function get_symbol_path(): string {
41
+ const symbol_key: D3SymbolName = style.symbol_type ?? DEFAULTS.scatter.symbol_type
42
+ const symbol_type = symbol_map[symbol_key] ?? d3_symbols.symbolCircle
43
+ const size = style.symbol_size ?? Math.PI * Math.pow(style.radius ?? 2, 2)
44
+ return symbol().type(symbol_type).size(size)() || ``
45
+ }
46
+
47
+ let marker_path = $derived.by(get_symbol_path)
48
+
49
+ const default_tween_props: TweenedOptions<XyObj> = {
17
50
  duration: 600,
18
51
  easing: cubicOut,
19
- };
20
- // Single tween for {x, y} coordinates
21
- const tweened_coords = new Tween(origin, { ...default_tween_props, ...point_tween });
22
- $effect.pre(() => {
23
- tweened_coords.target = { x: x + offset.x, y: y + offset.y };
24
- });
52
+ }
53
+ // Single tween for {x, y} coordinates
54
+ const tweened_coords = new Tween(origin, { ...default_tween_props, ...point_tween })
55
+
56
+ $effect.pre(() => {
57
+ tweened_coords.target = { x: x + offset.x, y: y + offset.y }
58
+ })
25
59
  </script>
26
60
 
27
61
  <g
@@ -61,11 +95,46 @@ $effect.pre(() => {
61
95
  style:cursor={style.cursor}
62
96
  />
63
97
  {#if label.text}
98
+ {@const offset_x = label.offset?.x ?? 10}
99
+ {@const offset_y = label.offset?.y ?? 0}
100
+ {@const displacement = Math.hypot(offset_x, offset_y)}
101
+ {#if displacement > leader_line_threshold}
102
+ {@const marker_radius = style.radius ?? 3}
103
+ {@const angle = Math.atan2(offset_y, offset_x)}
104
+ {@const cos_a = Math.cos(angle)}
105
+ {@const sin_a = Math.sin(angle)}
106
+ {@const start_x = cos_a * (marker_radius + 2)}
107
+ {@const start_y = sin_a * (marker_radius + 2)}
108
+ {@const font_px = parseFloat(label.font_size ?? `10`) || 10}
109
+ {@const half_w = (label.text?.length ?? 1) * font_px * 0.2}
110
+ {@const half_h = font_px * 0.5}
111
+ {@const edge_dist = Math.min(
112
+ Math.abs(cos_a) > 0.01 ? half_w / Math.abs(cos_a) : Infinity,
113
+ Math.abs(sin_a) > 0.01 ? half_h / Math.abs(sin_a) : Infinity,
114
+ )}
115
+ {@const end_x = offset_x - cos_a * (edge_dist + 1)}
116
+ {@const end_y = offset_y - sin_a * (edge_dist + 1)}
117
+ {@const line_len = Math.hypot(end_x - start_x, end_y - start_y)}
118
+ {#if line_len > 6}
119
+ <line
120
+ x1={start_x}
121
+ y1={start_y}
122
+ x2={end_x}
123
+ y2={end_y}
124
+ class="leader-line"
125
+ stroke="var(--scatter-leader-line-color, #888)"
126
+ stroke-width="var(--scatter-leader-line-width, 0.8)"
127
+ stroke-dasharray="var(--scatter-leader-line-dash, 2 2)"
128
+ stroke-opacity="var(--scatter-leader-line-opacity, 0.6)"
129
+ />
130
+ {/if}
131
+ {/if}
64
132
  <text
65
- x={label?.offset?.x ?? 10}
66
- y={label?.offset?.y ?? 0}
67
- style:font-size={label?.font_size ?? `10px`}
68
- style:font-family={label?.font_family ?? `sans-serif`}
133
+ x={offset_x}
134
+ y={offset_y}
135
+ text-anchor={label.auto_placement ? `middle` : undefined}
136
+ style:font-size={label.font_size ?? `10px`}
137
+ style:font-family={label.font_family ?? `sans-serif`}
69
138
  fill="var(--scatter-point-label-fill, currentColor)"
70
139
  dominant-baseline="middle"
71
140
  class="label-text"
@@ -110,4 +179,7 @@ $effect.pre(() => {
110
179
  .label-text {
111
180
  pointer-events: var(--scatter-point-label-pointer-events, none);
112
181
  }
182
+ .leader-line {
183
+ pointer-events: none;
184
+ }
113
185
  </style>
@@ -12,6 +12,7 @@ type $$ComponentProps = Omit<SVGAttributes<SVGGElement>, `style` | `offset` | `o
12
12
  origin?: XyObj;
13
13
  is_hovered?: boolean;
14
14
  is_selected?: boolean;
15
+ leader_line_threshold?: number;
15
16
  };
16
17
  declare const ScatterPoint: import("svelte").Component<$$ComponentProps, {}, "origin" | "point_tween">;
17
18
  type ScatterPoint = ReturnType<typeof ScatterPoint>;
@@ -1,112 +1,169 @@
1
- <script lang="ts">import { format_num, format_value } from '../labels';
2
- import { BarPlot } from './';
3
- import * as symmetry from '../symmetry';
4
- import * as spg from '../symmetry/spacegroups';
5
- import { SvelteMap } from 'svelte/reactivity';
6
- // Merge tick config with default rotation, preserving user overrides
7
- const with_rotation = (tick, default_rot) => ({
1
+ <script lang="ts">
2
+ import { format_num, format_value } from '../labels'
3
+ import type { BarHandlerProps, BarSeries, TickConfig } from './'
4
+ import { BarPlot } from './'
5
+ import type { CrystalSystem } from '../symmetry'
6
+ import * as symmetry from '../symmetry'
7
+ import * as spg from '../symmetry/spacegroups'
8
+ import type { ComponentProps } from 'svelte'
9
+ import { SvelteMap } from 'svelte/reactivity'
10
+
11
+ // Merge tick config with default rotation, preserving user overrides
12
+ const with_rotation = (
13
+ tick: TickConfig | undefined,
14
+ default_rot: number,
15
+ ): TickConfig => ({
8
16
  ...tick,
9
17
  label: { ...tick?.label, rotation: tick?.label?.rotation ?? default_rot },
10
- });
11
- const MAX_SPACEGROUP = 230;
12
- let { data, show_counts = true, orientation = `vertical`, x_axis = {}, y_axis = {}, ...rest } = $props();
13
- // Normalize input data to space group numbers
14
- const normalized_data = $derived(data.map(spg.normalize_spacegroup).filter((sg) => sg !== null));
15
- // Compute histogram of space group numbers
16
- const histogram = $derived.by(() => {
17
- const hist = new SvelteMap();
18
+ })
19
+
20
+ const MAX_SPACEGROUP = 230
21
+ let {
22
+ data,
23
+ show_counts = true,
24
+ orientation = `vertical`,
25
+ x_axis = {},
26
+ y_axis = {},
27
+ ...rest
28
+ }: ComponentProps<typeof BarPlot> & {
29
+ data: (number | string)[]
30
+ show_counts?: boolean
31
+ } = $props()
32
+
33
+ // Normalize input data to space group numbers
34
+ const normalized_data = $derived(
35
+ data.map(spg.normalize_spacegroup).filter((sg): sg is number => sg !== null),
36
+ )
37
+
38
+ // Compute histogram of space group numbers
39
+ const histogram = $derived.by(() => {
40
+ const hist = new SvelteMap<number, number>()
41
+
18
42
  // Count occurrences
19
43
  for (const sg of normalized_data) {
20
- hist.set(sg, (hist.get(sg) ?? 0) + 1);
44
+ hist.set(sg, (hist.get(sg) ?? 0) + 1)
21
45
  }
22
- return hist;
23
- });
24
- // Group counts by crystal system
25
- const crystal_system_stats = $derived.by(() => {
26
- const stats = new SvelteMap();
46
+
47
+ return hist
48
+ })
49
+
50
+ // Group counts by crystal system
51
+ const crystal_system_stats = $derived.by(() => {
52
+ const stats = new SvelteMap<
53
+ CrystalSystem,
54
+ { count: number; spacegroups: number[] }
55
+ >()
56
+
27
57
  for (const system of symmetry.CRYSTAL_SYSTEMS) {
28
- stats.set(system, { count: 0, spacegroups: [] });
58
+ stats.set(system, { count: 0, spacegroups: [] })
29
59
  }
60
+
30
61
  for (const [sg, count] of histogram) {
31
- const system = spg.spacegroup_to_crystal_sys(sg);
32
- if (system) {
33
- const stat = stats.get(system);
34
- stat.count += count;
35
- stat.spacegroups.push(sg);
36
- }
62
+ const system = spg.spacegroup_to_crystal_sys(sg)
63
+ if (!system) continue
64
+ const stat = stats.get(system)
65
+ if (!stat) continue
66
+ stat.count += count
67
+ stat.spacegroups.push(sg)
37
68
  }
38
- return stats;
39
- });
40
- // Create sorted list of space groups for x-axis
41
- const sorted_spacegroups = $derived(Array.from(histogram.keys()).sort((a, b) => a - b));
42
- // Smart tick selection: thin out ticks for dense data
43
- const x_axis_ticks = $derived.by(() => {
44
- const non_zero_count = sorted_spacegroups.filter((sg) => (histogram.get(sg) ?? 0) > 0).length;
69
+
70
+ return stats
71
+ })
72
+
73
+ // Create sorted list of space groups for x-axis
74
+ const sorted_spacegroups = $derived(
75
+ Array.from(histogram.keys()).sort((a, b) => a - b),
76
+ )
77
+
78
+ // Smart tick selection: thin out ticks for dense data
79
+ const x_axis_ticks = $derived.by(() => {
80
+ const non_zero_count = sorted_spacegroups.filter(
81
+ (sg) => (histogram.get(sg) ?? 0) > 0,
82
+ ).length
83
+
45
84
  // If data is dense (>40 space groups with data), show only multiples of 5
46
85
  return non_zero_count > 40
47
- ? sorted_spacegroups.filter((sg) => sg % 5 === 0)
48
- : sorted_spacegroups;
49
- });
50
- // Build BarSeries - one series per crystal system for proper coloring
51
- const bar_series = $derived.by(() => {
52
- const series_by_system = new SvelteMap();
86
+ ? sorted_spacegroups.filter((sg) => sg % 5 === 0)
87
+ : sorted_spacegroups
88
+ })
89
+
90
+ // Build BarSeries - one series per crystal system for proper coloring
91
+ const bar_series = $derived.by<BarSeries[]>(() => {
92
+ const series_by_system = new SvelteMap<
93
+ CrystalSystem,
94
+ { x: number[]; y: number[] }
95
+ >()
96
+
53
97
  // Group data by crystal system
54
98
  for (const sg of sorted_spacegroups) {
55
- const system = spg.spacegroup_to_crystal_sys(sg);
56
- if (system) {
57
- let series = series_by_system.get(system);
58
- if (!series) {
59
- series = { x: [], y: [] };
60
- series_by_system.set(system, series);
61
- }
62
- series.x.push(sg);
63
- series.y.push(histogram.get(sg) ?? 0);
99
+ const system = spg.spacegroup_to_crystal_sys(sg)
100
+ if (system) {
101
+ let series = series_by_system.get(system)
102
+ if (!series) {
103
+ series = { x: [], y: [] }
104
+ series_by_system.set(system, series)
64
105
  }
106
+ series.x.push(sg)
107
+ series.y.push(histogram.get(sg) ?? 0)
108
+ }
65
109
  }
110
+
66
111
  // Convert to BarSeries array, maintaining order of crystal systems
67
- const result = [];
112
+ const result: BarSeries[] = []
68
113
  for (const system of symmetry.CRYSTAL_SYSTEMS) {
69
- const data = series_by_system.get(system);
70
- if (data) {
71
- const { x, y } = data;
72
- const color = symmetry.CRYSTAL_SYSTEM_COLORS[system];
73
- result.push({ x, y, color, label: system, bar_width: 0.9, visible: true });
74
- }
114
+ const data = series_by_system.get(system)
115
+ if (data) {
116
+ const { x, y } = data
117
+ const color = symmetry.CRYSTAL_SYSTEM_COLORS[system]
118
+ result.push({ x, y, color, label: system, bar_width: 0.9, visible: true })
119
+ }
75
120
  }
76
- return result;
77
- });
78
- // Always show full space group range (1-230)
79
- const x_range = [0.5, MAX_SPACEGROUP + 0.5];
80
- // Calculate crystal system region boundaries using full theoretical ranges
81
- const crystal_system_regions = $derived.by(() => {
82
- const [range_min, range_max] = x_range;
121
+ return result
122
+ })
123
+
124
+ // Always show full space group range (1-230)
125
+ const x_range: [number, number] = [0.5, MAX_SPACEGROUP + 0.5]
126
+
127
+ // Calculate crystal system region boundaries using full theoretical ranges
128
+ const crystal_system_regions = $derived.by(() => {
129
+ const [range_min, range_max] = x_range
130
+
83
131
  return symmetry.CRYSTAL_SYSTEMS.map((system) => {
84
- const [sg_start, sg_end] = symmetry.CRYSTAL_SYSTEM_RANGES[system];
85
- const stats = crystal_system_stats.get(system);
86
- const count = stats?.count ?? 0;
87
- const color = symmetry.CRYSTAL_SYSTEM_COLORS[system];
88
- return { system, sg_start, sg_end, count, color };
89
- }).filter((region) => region.sg_end >= range_min && region.sg_start <= range_max);
90
- });
91
- const total_count = $derived(normalized_data.length);
92
- // Build axis configurations based on orientation
93
- const x_axis_config = $derived(orientation === `horizontal` ? { ...x_axis, label: x_axis.label ?? `Counts` } : {
94
- ...x_axis,
95
- label: x_axis.label ?? `International Spacegroup Number`,
96
- range: x_range,
97
- ticks: x_axis_ticks,
98
- tick: with_rotation(x_axis.tick, 90), // Rotate ticks 90° to avoid overlap
99
- label_shift: { x: 0, y: 20, ...x_axis.label_shift }, // Move label down for rotated ticks
100
- });
101
- const y_axis_config = $derived(orientation === `horizontal`
102
- ? {
132
+ const [sg_start, sg_end] = symmetry.CRYSTAL_SYSTEM_RANGES[system]
133
+ const stats = crystal_system_stats.get(system)
134
+ const count = stats?.count ?? 0
135
+ const color = symmetry.CRYSTAL_SYSTEM_COLORS[system]
136
+ return { system, sg_start, sg_end, count, color }
137
+ }).filter(
138
+ (region) => region.sg_end >= range_min && region.sg_start <= range_max, // Only visible systems
139
+ )
140
+ })
141
+
142
+ const total_count = $derived(normalized_data.length)
143
+
144
+ // Build axis configurations based on orientation
145
+ const x_axis_config = $derived(
146
+ orientation === `horizontal` ? { ...x_axis, label: x_axis.label ?? `Counts` } : {
147
+ ...x_axis,
148
+ label: x_axis.label ?? `International Spacegroup Number`,
149
+ range: x_range,
150
+ ticks: x_axis_ticks,
151
+ tick: with_rotation(x_axis.tick, 90), // Rotate ticks 90° to avoid overlap
152
+ label_shift: { x: 0, y: 20, ...x_axis.label_shift }, // Move label down for rotated ticks
153
+ },
154
+ )
155
+
156
+ const y_axis_config = $derived(
157
+ orientation === `horizontal`
158
+ ? {
103
159
  ...y_axis,
104
160
  label: y_axis.label ?? `International Spacegroup Number`,
105
161
  range: x_range,
106
162
  ticks: x_axis_ticks,
107
163
  tick: with_rotation(y_axis.tick, 0),
108
- }
109
- : { ...y_axis, label: y_axis.label ?? `Counts` });
164
+ }
165
+ : { ...y_axis, label: y_axis.label ?? `Counts` },
166
+ )
110
167
  </script>
111
168
 
112
169
  {#snippet tooltip(info: BarHandlerProps)}