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
@@ -69,7 +69,7 @@ declare function $$render<Metadata extends Record<string, unknown> = Record<stri
69
69
  pan?: PanConfig;
70
70
  };
71
71
  exports: {};
72
- bindings: "display" | "series" | "x_axis" | "x2_axis" | "y_axis" | "y2_axis" | "fullscreen" | "hovered" | "ref_lines" | "wrapper" | "tooltip_point" | "fill_regions" | "selected_series_idx";
72
+ bindings: "display" | "fullscreen" | "series" | "hovered" | "ref_lines" | "x_axis" | "y_axis" | "x2_axis" | "y2_axis" | "wrapper" | "tooltip_point" | "fill_regions" | "selected_series_idx";
73
73
  slots: {};
74
74
  events: {};
75
75
  };
@@ -77,7 +77,7 @@ declare class __sveltets_Render<Metadata extends Record<string, unknown> = Recor
77
77
  props(): ReturnType<typeof $$render<Metadata>>['props'];
78
78
  events(): ReturnType<typeof $$render<Metadata>>['events'];
79
79
  slots(): ReturnType<typeof $$render<Metadata>>['slots'];
80
- bindings(): "display" | "series" | "x_axis" | "x2_axis" | "y_axis" | "y2_axis" | "fullscreen" | "hovered" | "ref_lines" | "wrapper" | "tooltip_point" | "fill_regions" | "selected_series_idx";
80
+ bindings(): "display" | "fullscreen" | "series" | "hovered" | "ref_lines" | "x_axis" | "y_axis" | "x2_axis" | "y2_axis" | "wrapper" | "tooltip_point" | "fill_regions" | "selected_series_idx";
81
81
  exports(): {};
82
82
  }
83
83
  interface $$IsomorphicComponent {
@@ -1,154 +1,279 @@
1
1
  <script
2
2
  lang="ts"
3
3
  generics="Metadata extends Record<string, unknown> = Record<string, unknown>"
4
- >import { FullscreenToggle } from '../layout';
5
- import { ColorBar, PlotLegend } from './';
6
- import { get_series_color } from './data-transform';
7
- import { Canvas } from '@threlte/core';
8
- import * as extras from '@threlte/extras';
9
- import { onMount } from 'svelte';
10
- import { create_color_scale } from './scales';
11
- import ScatterPlot3DControls from './ScatterPlot3DControls.svelte';
12
- import ScatterPlot3DScene from './ScatterPlot3DScene.svelte';
13
- let {
14
- // Data props
15
- series = [], surfaces = [], ref_lines = [], ref_planes = [],
16
- // Axis configuration (initial values)
17
- x_axis: x_axis_init = {}, y_axis: y_axis_init = {}, z_axis: z_axis_init = {},
18
- // Display settings (initial value)
19
- display: display_init = {
20
- show_axes: true,
21
- show_grid: true,
22
- show_axis_labels: true,
23
- }, styles = {},
24
- // Color and size scaling
25
- color_scale = {
26
- type: `linear`,
27
- scheme: `interpolateViridis`,
28
- value_range: undefined,
29
- }, color_bar = {}, size_scale = {
30
- type: `linear`,
31
- radius_range: [0.05, 0.2],
32
- value_range: undefined,
33
- },
34
- // Legend
35
- legend = {},
36
- // Camera settings
37
- camera_position = $bindable([8, 8, 8]), camera_projection: camera_projection_init = `perspective`, auto_rotate: auto_rotate_init = 0, rotation_damping = 0, fov = 50, min_zoom = 0.1, max_zoom = 100, rotate_speed = 1, zoom_speed = 2, pan_speed = 2,
38
- // Lighting
39
- ambient_light = 0.6, directional_light = 0.8,
40
- // Rendering quality
41
- sphere_segments = 16,
42
- // Gizmo
43
- gizmo = true,
44
- // Controls
45
- controls: controls_init = {},
46
- // State
47
- hovered = $bindable(false), tooltip_point = $bindable(null),
48
- // Callbacks
49
- on_point_click, on_point_hover, on_series_visibility_change,
50
- // Fullscreen
51
- fullscreen = $bindable(false), fullscreen_toggle = true,
52
- // Binding refs
53
- wrapper = $bindable(), scene = $bindable(), camera = $bindable(), orbit_controls = $bindable(),
54
- // Snippets
55
- tooltip, children, header_controls, controls_extra, ...rest } = $props();
56
- let [width, height] = $state([0, 0]);
57
- // Track mounted state to avoid SSR/hydration mismatch with Canvas
58
- let mounted = $state(false);
59
- onMount(() => mounted = true);
60
- // User overrides merged with series.visible defaults
61
- let visibility_overrides = $state({});
62
- let series_visibility = $derived(series.map((srs, idx) => visibility_overrides[idx] ?? srs?.visible ?? true));
63
- // Local state for controls (initialized from props, owned by this component)
64
- const axis_defaults = { format: `.3~g`, scale_type: `linear` };
65
- let x_axis = $derived({ label: `X`, ...axis_defaults, ...x_axis_init });
66
- let y_axis = $derived({ label: `Y`, ...axis_defaults, ...y_axis_init });
67
- let z_axis = $derived({ label: `Z`, ...axis_defaults, ...z_axis_init });
68
- let display = $derived({
4
+ >
5
+ import type { D3ColorSchemeName, D3InterpolateName } from '../colors'
6
+ import { FullscreenToggle } from '../layout'
7
+ import type { Vec2, Vec3 } from '../math'
8
+ import { ColorBar, PlotLegend } from './'
9
+ import { get_series_color } from './data-transform'
10
+ import type {
11
+ AxisConfig3D,
12
+ CameraProjection3D,
13
+ ControlsConfig3D,
14
+ DataSeries3D,
15
+ DisplayConfig3D,
16
+ InternalPoint3D,
17
+ LegendConfig,
18
+ RefLine3D,
19
+ RefPlane,
20
+ ScaleType,
21
+ Scatter3DHandlerEvent,
22
+ Sides,
23
+ StyleOverrides3D,
24
+ Surface3DConfig,
25
+ } from './types'
26
+ import { Canvas } from '@threlte/core'
27
+ import * as extras from '@threlte/extras'
28
+ import { type ComponentProps, onMount, type Snippet } from 'svelte'
29
+ import type { HTMLAttributes } from 'svelte/elements'
30
+ import type { Camera, Scene } from 'three'
31
+ import { create_color_scale } from './scales'
32
+ import ScatterPlot3DControls from './ScatterPlot3DControls.svelte'
33
+ import ScatterPlot3DScene from './ScatterPlot3DScene.svelte'
34
+
35
+ let {
36
+ // Data props
37
+ series = [],
38
+ surfaces = [],
39
+ ref_lines = [],
40
+ ref_planes = [],
41
+ // Axis configuration (initial values)
42
+ x_axis: x_axis_init = {},
43
+ y_axis: y_axis_init = {},
44
+ z_axis: z_axis_init = {},
45
+ // Display settings (initial value)
46
+ display: display_init = {
47
+ show_axes: true,
48
+ show_grid: true,
49
+ show_axis_labels: true,
50
+ },
51
+ styles = {},
52
+ // Color and size scaling
53
+ color_scale = {
54
+ type: `linear` as ScaleType,
55
+ scheme: `interpolateViridis` as D3InterpolateName,
56
+ value_range: undefined,
57
+ },
58
+ color_bar = {},
59
+ size_scale = {
60
+ type: `linear` as ScaleType,
61
+ radius_range: [0.05, 0.2],
62
+ value_range: undefined,
63
+ },
64
+ // Legend
65
+ legend = {},
66
+ // Camera settings
67
+ camera_position = $bindable([8, 8, 8]),
68
+ camera_projection: camera_projection_init = `perspective` as CameraProjection3D,
69
+ auto_rotate: auto_rotate_init = 0,
70
+ rotation_damping = 0,
71
+ fov = 50,
72
+ min_zoom = 0.1,
73
+ max_zoom = 100,
74
+ rotate_speed = 1,
75
+ zoom_speed = 2,
76
+ pan_speed = 2,
77
+ // Lighting
78
+ ambient_light = 0.6,
79
+ directional_light = 0.8,
80
+ // Rendering quality
81
+ sphere_segments = 16,
82
+ // Gizmo
83
+ gizmo = true,
84
+ // Controls
85
+ controls: controls_init = {},
86
+ // State
87
+ hovered = $bindable(false),
88
+ tooltip_point = $bindable(null),
89
+ // Callbacks
90
+ on_point_click,
91
+ on_point_hover,
92
+ on_series_visibility_change,
93
+ // Fullscreen
94
+ fullscreen = $bindable(false),
95
+ fullscreen_toggle = true,
96
+ // Binding refs
97
+ wrapper = $bindable(),
98
+ scene = $bindable(),
99
+ camera = $bindable(),
100
+ orbit_controls = $bindable(),
101
+ // Snippets
102
+ tooltip,
103
+ children,
104
+ header_controls,
105
+ controls_extra,
106
+ ...rest
107
+ }: HTMLAttributes<HTMLDivElement> & {
108
+ series?: DataSeries3D<Metadata>[]
109
+ surfaces?: Surface3DConfig[]
110
+ ref_lines?: RefLine3D[]
111
+ ref_planes?: RefPlane[]
112
+ x_axis?: AxisConfig3D
113
+ y_axis?: AxisConfig3D
114
+ z_axis?: AxisConfig3D
115
+ display?: DisplayConfig3D
116
+ styles?: StyleOverrides3D
117
+ color_scale?: {
118
+ type?: ScaleType
119
+ scheme?: D3ColorSchemeName | D3InterpolateName
120
+ value_range?: [number, number]
121
+ } | D3InterpolateName
122
+ color_bar?: ComponentProps<typeof ColorBar> & { margin?: number | Sides } | null
123
+ size_scale?: {
124
+ type?: ScaleType
125
+ radius_range?: [number, number]
126
+ value_range?: [number, number]
127
+ }
128
+ legend?: LegendConfig | null
129
+ camera_position?: Vec3
130
+ camera_projection?: CameraProjection3D
131
+ auto_rotate?: number
132
+ rotation_damping?: number
133
+ fov?: number
134
+ min_zoom?: number
135
+ max_zoom?: number
136
+ rotate_speed?: number
137
+ zoom_speed?: number
138
+ pan_speed?: number
139
+ ambient_light?: number
140
+ directional_light?: number
141
+ sphere_segments?: number
142
+ gizmo?: boolean | ComponentProps<typeof extras.Gizmo>
143
+ controls?: ControlsConfig3D
144
+ hovered?: boolean
145
+ tooltip_point?: InternalPoint3D<Metadata> | null
146
+ on_point_click?: (data: Scatter3DHandlerEvent<Metadata>) => void
147
+ on_point_hover?: (data: Scatter3DHandlerEvent<Metadata> | null) => void
148
+ on_series_visibility_change?: (series_idx: number, visible: boolean) => void
149
+ fullscreen?: boolean
150
+ fullscreen_toggle?: boolean
151
+ wrapper?: HTMLDivElement
152
+ scene?: Scene
153
+ camera?: Camera
154
+ orbit_controls?: ComponentProps<typeof extras.OrbitControls>[`ref`]
155
+ tooltip?: Snippet<[Scatter3DHandlerEvent<Metadata>]>
156
+ children?: Snippet<[{ height: number; width: number; fullscreen: boolean }]>
157
+ header_controls?: Snippet<
158
+ [{ height: number; width: number; fullscreen: boolean }]
159
+ >
160
+ controls_extra?: Snippet
161
+ } = $props()
162
+
163
+ let [width, height] = $state([0, 0])
164
+
165
+ // Track mounted state to avoid SSR/hydration mismatch with Canvas
166
+ let mounted = $state(false)
167
+ onMount(() => mounted = true)
168
+
169
+ // User overrides merged with series.visible defaults
170
+ let visibility_overrides: Record<number, boolean> = $state({})
171
+ let series_visibility = $derived(
172
+ series.map((srs, idx) => visibility_overrides[idx] ?? srs?.visible ?? true),
173
+ )
174
+
175
+ // Local state for controls (initialized from props, owned by this component)
176
+ const axis_defaults = { format: `.3~g`, scale_type: `linear` as const }
177
+ let x_axis = $derived({ label: `X`, ...axis_defaults, ...x_axis_init })
178
+ let y_axis = $derived({ label: `Y`, ...axis_defaults, ...y_axis_init })
179
+ let z_axis = $derived({ label: `Z`, ...axis_defaults, ...z_axis_init })
180
+ let display = $derived({
69
181
  show_axes: true,
70
182
  show_grid: true,
71
183
  show_axis_labels: true,
72
184
  ...display_init,
73
- });
74
- let camera_projection = $derived(camera_projection_init);
75
- let auto_rotate = $derived(auto_rotate_init);
76
- let controls = $derived({ show: true, open: false, ...controls_init });
77
- // Normalize color_scale to always be an object
78
- let normalized_color_scale = $derived(typeof color_scale === `string`
79
- ? { type: `linear`, scheme: color_scale }
80
- : color_scale);
81
- // Collect all color values for color bar
82
- let all_color_values = $derived(series.filter(Boolean).flatMap((srs) => srs.color_values?.filter((val) => val != null) ?? []));
83
- let auto_color_range = $derived.by(() => {
84
- if (all_color_values.length === 0)
85
- return [0, 1];
86
- let min = Infinity;
87
- let max = -Infinity;
185
+ })
186
+ let camera_projection = $derived(camera_projection_init)
187
+ let auto_rotate = $derived(auto_rotate_init)
188
+ let controls = $derived({ show: true, open: false, ...controls_init })
189
+
190
+ // Normalize color_scale to always be an object
191
+ let normalized_color_scale = $derived(
192
+ typeof color_scale === `string`
193
+ ? { type: `linear` as const, scheme: color_scale }
194
+ : color_scale,
195
+ )
196
+
197
+ // Collect all color values for color bar
198
+ let all_color_values = $derived(
199
+ series.filter(Boolean).flatMap((srs) =>
200
+ srs.color_values?.filter((val): val is number => val != null) ?? []
201
+ ),
202
+ )
203
+
204
+ let auto_color_range = $derived.by((): [number, number] => {
205
+ if (all_color_values.length === 0) return [0, 1]
206
+ let [min, max] = [Infinity, -Infinity]
88
207
  for (const val of all_color_values) {
89
- if (val < min)
90
- min = val;
91
- if (val > max)
92
- max = val;
208
+ if (val < min) min = val
209
+ if (val > max) max = val
93
210
  }
94
- return [min, max];
95
- });
96
- let color_scale_fn = $derived(create_color_scale(normalized_color_scale, auto_color_range));
97
- // Legend data
98
- let legend_data = $derived(series.map((srs, series_idx) => {
99
- const is_visible = series_visibility[series_idx] ?? true;
100
- const label = srs?.label ?? `Series ${series_idx + 1}`;
101
- const series_color = get_series_color(series_idx);
102
- return {
211
+ return [min, max]
212
+ })
213
+
214
+ let color_scale_fn = $derived(
215
+ create_color_scale(normalized_color_scale, auto_color_range),
216
+ )
217
+
218
+ // Legend data
219
+ let legend_data = $derived(
220
+ series.map((srs, series_idx) => {
221
+ const is_visible = series_visibility[series_idx] ?? true
222
+ const label = srs?.label ?? `Series ${series_idx + 1}`
223
+ const series_color = get_series_color(series_idx)
224
+
225
+ return {
103
226
  series_idx,
104
227
  label,
105
228
  visible: is_visible,
106
229
  display_style: {
107
- symbol_type: `Circle`,
108
- symbol_color: srs?.point_style
109
- ? (Array.isArray(srs.point_style)
110
- ? srs.point_style[0]?.fill
111
- : srs.point_style?.fill) ??
112
- series_color
113
- : series_color,
230
+ symbol_type: `Circle` as const,
231
+ symbol_color: srs?.point_style
232
+ ? (Array.isArray(srs.point_style)
233
+ ? srs.point_style[0]?.fill
234
+ : srs.point_style?.fill) ??
235
+ series_color
236
+ : series_color,
114
237
  },
115
238
  has_explicit_label: Boolean(srs?.label),
116
239
  legend_group: srs?.legend_group,
117
- };
118
- }));
119
- // Compute gizmo props - move up when color bar is shown
120
- let has_color_bar = $derived(color_bar && all_color_values.length > 0);
121
- let computed_gizmo = $derived.by(() => {
122
- if (gizmo === false)
123
- return false;
124
- const base_offset = { left: 5, bottom: has_color_bar ? 70 : 5 };
240
+ }
241
+ }),
242
+ )
243
+
244
+ // Compute gizmo props - move up when color bar is shown
245
+ let has_color_bar = $derived(color_bar && all_color_values.length > 0)
246
+ let computed_gizmo = $derived.by(() => {
247
+ if (gizmo === false) return false
248
+ const base_offset = { left: 5, bottom: has_color_bar ? 70 : 5 }
125
249
  // className enables CSS targeting for z-index and pointer-events
126
250
  const base = {
127
- background: { enabled: false },
128
- offset: base_offset,
129
- className: `scatter3d-gizmo`,
130
- };
131
- if (gizmo === true)
132
- return base;
251
+ background: { enabled: false },
252
+ offset: base_offset,
253
+ className: `scatter3d-gizmo`,
254
+ }
255
+ if (gizmo === true) return base
133
256
  // Merge user-provided gizmo config, preserving scatter3d-gizmo class
134
- const merged_class = `scatter3d-gizmo ${gizmo.className ?? ``}`.trim();
257
+ const merged_class = `scatter3d-gizmo ${gizmo.className ?? ``}`.trim()
135
258
  return {
136
- ...base,
137
- ...gizmo,
138
- offset: { ...base_offset, ...gizmo.offset },
139
- className: merged_class,
140
- };
141
- });
142
- function toggle_series_visibility(idx) {
143
- const visible = (visibility_overrides[idx] = !series_visibility[idx]);
144
- on_series_visibility_change?.(idx, visible);
145
- }
146
- // Handle point hover
147
- function handle_point_hover(data) {
148
- hovered = data !== null;
149
- tooltip_point = data?.point ?? null;
150
- on_point_hover?.(data);
151
- }
259
+ ...base,
260
+ ...gizmo,
261
+ offset: { ...base_offset, ...gizmo.offset },
262
+ className: merged_class,
263
+ }
264
+ })
265
+
266
+ function toggle_series_visibility(idx: number) {
267
+ const visible = (visibility_overrides[idx] = !series_visibility[idx])
268
+ on_series_visibility_change?.(idx, visible)
269
+ }
270
+
271
+ // Handle point hover
272
+ function handle_point_hover(data: Scatter3DHandlerEvent<Metadata> | null) {
273
+ hovered = data !== null
274
+ tooltip_point = data?.point ?? null
275
+ on_point_hover?.(data)
276
+ }
152
277
  </script>
153
278
 
154
279
  <svelte:window
@@ -71,7 +71,7 @@ declare function $$render<Metadata extends Record<string, unknown> = Record<stri
71
71
  controls_extra?: Snippet;
72
72
  };
73
73
  exports: {};
74
- bindings: "fullscreen" | "hovered" | "camera_position" | "wrapper" | "tooltip_point" | "scene" | "camera" | "orbit_controls";
74
+ bindings: "fullscreen" | "hovered" | "camera_position" | "wrapper" | "tooltip_point" | "camera" | "scene" | "orbit_controls";
75
75
  slots: {};
76
76
  events: {};
77
77
  };
@@ -79,7 +79,7 @@ declare class __sveltets_Render<Metadata extends Record<string, unknown> = Recor
79
79
  props(): ReturnType<typeof $$render<Metadata>>['props'];
80
80
  events(): ReturnType<typeof $$render<Metadata>>['events'];
81
81
  slots(): ReturnType<typeof $$render<Metadata>>['slots'];
82
- bindings(): "fullscreen" | "hovered" | "camera_position" | "wrapper" | "tooltip_point" | "scene" | "camera" | "orbit_controls";
82
+ bindings(): "fullscreen" | "hovered" | "camera_position" | "wrapper" | "tooltip_point" | "camera" | "scene" | "orbit_controls";
83
83
  exports(): {};
84
84
  }
85
85
  interface $$IsomorphicComponent {
@@ -1,83 +1,133 @@
1
- <script lang="ts">// NOTE: Axis config objects must be reassigned (not mutated) to trigger $bindable reactivity.
2
- // Pattern: `x_axis = { ...x_axis, prop: value }` instead of `x_axis.prop = value`
3
- import { SettingsSection } from '../layout';
4
- import DraggablePane from '../overlays/DraggablePane.svelte';
5
- // Unique ID prefix to avoid conflicts when multiple instances on same page
6
- const uid = crypto.randomUUID().slice(0, 8);
7
- let { x_axis = $bindable({}), y_axis = $bindable({}), z_axis = $bindable({}), display = $bindable({}), camera_projection = $bindable(`perspective`), auto_rotate = $bindable(0), series = [], surfaces = [], toggle_props, pane_props, children, } = $props();
8
- // Calculate auto ranges for reset
9
- function calc_auto_range(values) {
10
- if (values.length === 0)
11
- return [0, 1];
12
- let [min_val, max_val] = [values[0], values[0]];
1
+ <script lang="ts">
2
+ // NOTE: Axis config objects must be reassigned (not mutated) to trigger $bindable reactivity.
3
+ // Pattern: `x_axis = { ...x_axis, prop: value }` instead of `x_axis.prop = value`
4
+ import { SettingsSection } from '../layout'
5
+ import DraggablePane from '../overlays/DraggablePane.svelte'
6
+ import type {
7
+ AxisConfig3D,
8
+ CameraProjection3D,
9
+ DataSeries3D,
10
+ DisplayConfig3D,
11
+ Surface3DConfig,
12
+ } from './types'
13
+ import type { ComponentProps, Snippet } from 'svelte'
14
+
15
+ // Unique ID prefix to avoid conflicts when multiple instances on same page
16
+ const uid = crypto.randomUUID().slice(0, 8)
17
+
18
+ let {
19
+ show = $bindable(false),
20
+ x_axis = $bindable({}),
21
+ y_axis = $bindable({}),
22
+ z_axis = $bindable({}),
23
+ display = $bindable({}),
24
+ camera_projection = $bindable(`perspective`),
25
+ auto_rotate = $bindable(0),
26
+ series = [],
27
+ surfaces = [],
28
+ toggle_props,
29
+ pane_props,
30
+ children,
31
+ }: {
32
+ show?: boolean
33
+ x_axis?: AxisConfig3D
34
+ y_axis?: AxisConfig3D
35
+ z_axis?: AxisConfig3D
36
+ display?: DisplayConfig3D
37
+ camera_projection?: CameraProjection3D
38
+ auto_rotate?: number
39
+ series?: DataSeries3D[]
40
+ surfaces?: Surface3DConfig[]
41
+ toggle_props?: ComponentProps<typeof DraggablePane>[`toggle_props`]
42
+ pane_props?: ComponentProps<typeof DraggablePane>[`pane_props`]
43
+ children?: Snippet
44
+ } = $props()
45
+
46
+ // Calculate auto ranges for reset
47
+ function calc_auto_range(values: number[]): [number, number] {
48
+ if (values.length === 0) return [0, 1]
49
+ let [min_val, max_val] = [values[0], values[0]]
13
50
  for (const v of values) {
14
- if (v < min_val)
15
- min_val = v;
16
- else if (v > max_val)
17
- max_val = v;
51
+ if (v < min_val) min_val = v
52
+ else if (v > max_val) max_val = v
18
53
  }
19
- const padding = (max_val - min_val) * 0.05 || 0.5;
20
- return [min_val - padding, max_val + padding];
21
- }
22
- // flatMap already creates new array, no need to spread
23
- let all_x_values = $derived(series.flatMap((srs) => srs.x));
24
- let all_y_values = $derived(series.flatMap((srs) => srs.y));
25
- let all_z_values = $derived(series.flatMap((srs) => srs.z));
26
- let auto_x_range = $derived(calc_auto_range(all_x_values));
27
- let auto_y_range = $derived(calc_auto_range(all_y_values));
28
- let auto_z_range = $derived(calc_auto_range(all_z_values));
29
- // Helper to extract input value from event - DRYs up event handler casts
30
- const get_input_value = (event) => event.target.value;
31
- // Helpers to update display properties - avoids verbose inline handlers
32
- const update_display = (key) => (event) => {
33
- const parsed = parseFloat(get_input_value(event));
54
+ const padding = (max_val - min_val) * 0.05 || 0.5
55
+ return [min_val - padding, max_val + padding]
56
+ }
57
+
58
+ // flatMap already creates new array, no need to spread
59
+ let all_x_values = $derived(series.flatMap((srs) => srs.x))
60
+ let all_y_values = $derived(series.flatMap((srs) => srs.y))
61
+ let all_z_values = $derived(series.flatMap((srs) => srs.z))
62
+
63
+ let auto_x_range = $derived(calc_auto_range(all_x_values))
64
+ let auto_y_range = $derived(calc_auto_range(all_y_values))
65
+ let auto_z_range = $derived(calc_auto_range(all_z_values))
66
+
67
+ // Helper to extract input value from event - DRYs up event handler casts
68
+ const get_input_value = (event: Event) => (event.target as HTMLInputElement).value
69
+
70
+ // Helpers to update display properties - avoids verbose inline handlers
71
+ const update_display = (key: keyof DisplayConfig3D) => (event: Event) => {
72
+ const parsed = parseFloat(get_input_value(event))
34
73
  // Guard against NaN when input is cleared - preserve existing value
35
- if (!Number.isNaN(parsed))
36
- display = { ...display, [key]: parsed };
37
- };
38
- const toggle_display = (key) => () => {
39
- display = { ...display, [key]: !display[key] };
40
- };
41
- const toggle_projection = (plane) => () => {
74
+ if (!Number.isNaN(parsed)) display = { ...display, [key]: parsed }
75
+ }
76
+ const toggle_display = (key: keyof DisplayConfig3D) => () => {
77
+ display = { ...display, [key]: !display[key] }
78
+ }
79
+ const toggle_projection = (plane: `xy` | `xz` | `yz`) => () => {
42
80
  display = {
43
- ...display,
44
- projections: { ...display.projections, [plane]: !display.projections?.[plane] },
45
- };
46
- };
47
- // Round to 4 decimal places for display
48
- const round4 = (val) => Math.round(val * 1e4) / 1e4;
49
- // Helper for axis label updates
50
- const update_axis_label = (axis, setter) => (event) => {
51
- setter({ ...axis, label: get_input_value(event) });
52
- };
53
- const axes = $derived([
81
+ ...display,
82
+ projections: { ...display.projections, [plane]: !display.projections?.[plane] },
83
+ }
84
+ }
85
+
86
+ // Round to 4 decimal places for display
87
+ const round4 = (val: number) => Math.round(val * 1e4) / 1e4
88
+
89
+ // Helper for axis label updates
90
+ const update_axis_label =
91
+ <T extends { label?: string }>(axis: T, setter: (val: T) => void) =>
92
+ (event: Event) => {
93
+ setter({ ...axis, label: get_input_value(event) })
94
+ }
95
+
96
+ type AxisEntry = {
97
+ name: string
98
+ axis: AxisConfig3D
99
+ auto_range: [number, number]
100
+ set: (val: AxisConfig3D) => void
101
+ }
102
+ const axes = $derived<AxisEntry[]>([
54
103
  {
55
- name: `X`,
56
- axis: x_axis,
57
- auto_range: auto_x_range,
58
- set: (val) => (x_axis = val),
104
+ name: `X`,
105
+ axis: x_axis,
106
+ auto_range: auto_x_range,
107
+ set: (val) => (x_axis = val),
59
108
  },
60
109
  {
61
- name: `Y`,
62
- axis: y_axis,
63
- auto_range: auto_y_range,
64
- set: (val) => (y_axis = val),
110
+ name: `Y`,
111
+ axis: y_axis,
112
+ auto_range: auto_y_range,
113
+ set: (val) => (y_axis = val),
65
114
  },
66
115
  {
67
- name: `Z`,
68
- axis: z_axis,
69
- auto_range: auto_z_range,
70
- set: (val) => (z_axis = val),
116
+ name: `Z`,
117
+ axis: z_axis,
118
+ auto_range: auto_z_range,
119
+ set: (val) => (z_axis = val),
71
120
  },
72
- ]);
121
+ ])
73
122
  </script>
74
123
 
75
124
  <DraggablePane
125
+ bind:show
76
126
  {toggle_props}
77
127
  pane_props={{
78
128
  title: `3D Plot Settings`,
79
129
  ...pane_props,
80
- style: `max-height: 80cqh; overflow-y: auto; ${pane_props?.style ?? ``}`,
130
+ style: `--pane-max-height: 80cqh; ${pane_props?.style ?? ``}`,
81
131
  }}
82
132
  >
83
133
  <!-- Camera Controls -->