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
@@ -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)}