matterviz 0.3.1 → 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 (358) hide show
  1. package/dist/EmptyState.svelte +10 -2
  2. package/dist/FilePicker.svelte +154 -96
  3. package/dist/Icon.svelte +20 -14
  4. package/dist/MillerIndexInput.svelte +27 -21
  5. package/dist/api/optimade.js +6 -6
  6. package/dist/app.css +216 -178
  7. package/dist/brillouin/BrillouinZone.svelte +299 -198
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +74 -55
  11. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte +277 -165
  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 +327 -0
  18. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
  19. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +847 -0
  20. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
  21. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +3194 -0
  22. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
  23. package/dist/chempot-diagram/ChemPotScene3D.svelte +11 -0
  24. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
  25. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  26. package/dist/chempot-diagram/async-compute.svelte.js +77 -0
  27. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  28. package/dist/chempot-diagram/chempot-worker.js +11 -0
  29. package/dist/chempot-diagram/color.d.ts +10 -0
  30. package/dist/chempot-diagram/color.js +32 -0
  31. package/dist/chempot-diagram/compute.d.ts +48 -0
  32. package/dist/chempot-diagram/compute.js +812 -0
  33. package/dist/chempot-diagram/index.d.ts +6 -0
  34. package/dist/chempot-diagram/index.js +6 -0
  35. package/dist/chempot-diagram/pointer.d.ts +16 -0
  36. package/dist/chempot-diagram/pointer.js +40 -0
  37. package/dist/chempot-diagram/temperature.d.ts +15 -0
  38. package/dist/chempot-diagram/temperature.js +36 -0
  39. package/dist/chempot-diagram/types.d.ts +86 -0
  40. package/dist/chempot-diagram/types.js +28 -0
  41. package/dist/colors/index.d.ts +3 -1
  42. package/dist/colors/index.js +9 -3
  43. package/dist/composition/BarChart.svelte +141 -77
  44. package/dist/composition/BubbleChart.svelte +107 -52
  45. package/dist/composition/Composition.svelte +100 -79
  46. package/dist/composition/Formula.svelte +108 -62
  47. package/dist/composition/FormulaFilter.svelte +973 -353
  48. package/dist/composition/FormulaFilter.svelte.d.ts +35 -1
  49. package/dist/composition/PieChart.svelte +199 -99
  50. package/dist/composition/PieChart.svelte.d.ts +1 -1
  51. package/dist/composition/format.d.ts +5 -0
  52. package/dist/composition/format.js +20 -3
  53. package/dist/composition/parse.js +14 -9
  54. package/dist/convex-hull/ConvexHull.svelte +93 -38
  55. package/dist/convex-hull/ConvexHull2D.svelte +551 -393
  56. package/dist/convex-hull/ConvexHull3D.svelte +1303 -825
  57. package/dist/convex-hull/ConvexHull4D.svelte +1012 -686
  58. package/dist/convex-hull/ConvexHullControls.svelte +115 -28
  59. package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
  60. package/dist/convex-hull/ConvexHullStats.svelte +821 -249
  61. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
  62. package/dist/convex-hull/ConvexHullTooltip.svelte +41 -16
  63. package/dist/convex-hull/GasPressureControls.svelte +104 -61
  64. package/dist/convex-hull/StructurePopup.svelte +25 -4
  65. package/dist/convex-hull/TemperatureSlider.svelte +45 -25
  66. package/dist/convex-hull/barycentric-coords.js +13 -7
  67. package/dist/convex-hull/demo-temperature.d.ts +6 -0
  68. package/dist/convex-hull/demo-temperature.js +40 -0
  69. package/dist/convex-hull/gas-thermodynamics.js +17 -12
  70. package/dist/convex-hull/helpers.d.ts +10 -1
  71. package/dist/convex-hull/helpers.js +79 -38
  72. package/dist/convex-hull/index.d.ts +1 -0
  73. package/dist/convex-hull/index.js +1 -0
  74. package/dist/convex-hull/thermodynamics.d.ts +8 -21
  75. package/dist/convex-hull/thermodynamics.js +163 -69
  76. package/dist/convex-hull/types.d.ts +12 -12
  77. package/dist/convex-hull/types.js +0 -12
  78. package/dist/coordination/CoordinationBarPlot.svelte +232 -176
  79. package/dist/element/BohrAtom.svelte +56 -13
  80. package/dist/element/ElementHeading.svelte +7 -2
  81. package/dist/element/ElementPhoto.svelte +15 -9
  82. package/dist/element/ElementStats.svelte +10 -4
  83. package/dist/element/ElementTile.svelte +137 -73
  84. package/dist/element/Nucleus.svelte +39 -11
  85. package/dist/element/data.js +2 -14
  86. package/dist/element/data.json.gz +0 -0
  87. package/dist/element/types.d.ts +1 -0
  88. package/dist/feedback/ClickFeedback.svelte +16 -5
  89. package/dist/feedback/DragOverlay.svelte +10 -2
  90. package/dist/feedback/Spinner.svelte +4 -2
  91. package/dist/feedback/StatusMessage.svelte +8 -2
  92. package/dist/fermi-surface/FermiSlice.svelte +118 -88
  93. package/dist/fermi-surface/FermiSurface.svelte +336 -239
  94. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  95. package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
  96. package/dist/fermi-surface/FermiSurfaceScene.svelte +536 -343
  97. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  98. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
  99. package/dist/fermi-surface/compute.js +16 -20
  100. package/dist/fermi-surface/parse.js +37 -33
  101. package/dist/fermi-surface/symmetry.js +2 -7
  102. package/dist/fermi-surface/types.d.ts +3 -5
  103. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1527 -0
  104. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
  105. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
  106. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +30 -0
  107. package/dist/heatmap-matrix/index.d.ts +53 -0
  108. package/dist/heatmap-matrix/index.js +100 -0
  109. package/dist/heatmap-matrix/shared.d.ts +2 -0
  110. package/dist/heatmap-matrix/shared.js +4 -0
  111. package/dist/icons.d.ts +111 -0
  112. package/dist/icons.js +158 -0
  113. package/dist/index.d.ts +5 -2
  114. package/dist/index.js +5 -2
  115. package/dist/io/decompress.js +1 -1
  116. package/dist/io/export.d.ts +3 -0
  117. package/dist/io/export.js +138 -140
  118. package/dist/io/file-drop.d.ts +7 -0
  119. package/dist/io/file-drop.js +43 -0
  120. package/dist/io/index.d.ts +2 -2
  121. package/dist/io/index.js +2 -112
  122. package/dist/io/is-binary.js +2 -3
  123. package/dist/io/types.d.ts +1 -0
  124. package/dist/io/url-drop.d.ts +2 -0
  125. package/dist/io/url-drop.js +117 -0
  126. package/dist/isosurface/Isosurface.svelte +220 -110
  127. package/dist/isosurface/IsosurfaceControls.svelte +65 -28
  128. package/dist/isosurface/parse.js +104 -56
  129. package/dist/isosurface/slice.d.ts +2 -1
  130. package/dist/isosurface/slice.js +8 -13
  131. package/dist/isosurface/types.d.ts +14 -1
  132. package/dist/isosurface/types.js +152 -5
  133. package/dist/labels.d.ts +2 -1
  134. package/dist/labels.js +12 -8
  135. package/dist/layout/FullscreenToggle.svelte +11 -2
  136. package/dist/layout/InfoCard.svelte +38 -6
  137. package/dist/layout/InfoTag.svelte +125 -94
  138. package/dist/layout/PropertyFilter.svelte +82 -37
  139. package/dist/layout/SettingsSection.svelte +85 -55
  140. package/dist/layout/SubpageGrid.svelte +82 -0
  141. package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
  142. package/dist/layout/index.d.ts +1 -0
  143. package/dist/layout/index.js +1 -0
  144. package/dist/layout/json-tree/JsonNode.svelte +266 -223
  145. package/dist/layout/json-tree/JsonTree.svelte +516 -429
  146. package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
  147. package/dist/layout/json-tree/JsonValue.svelte +281 -173
  148. package/dist/layout/json-tree/types.d.ts +10 -2
  149. package/dist/layout/json-tree/utils.d.ts +2 -0
  150. package/dist/layout/json-tree/utils.js +37 -2
  151. package/dist/marching-cubes.js +25 -2
  152. package/dist/math.d.ts +20 -17
  153. package/dist/math.js +474 -57
  154. package/dist/overlays/ContextMenu.svelte +66 -40
  155. package/dist/overlays/DraggablePane.svelte +331 -154
  156. package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
  157. package/dist/periodic-table/PeriodicTable.svelte +278 -145
  158. package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
  159. package/dist/periodic-table/PropertySelect.svelte +25 -7
  160. package/dist/periodic-table/TableInset.svelte +8 -3
  161. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +559 -267
  162. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
  163. package/dist/phase-diagram/PhaseDiagramControls.svelte +131 -51
  164. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
  165. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
  166. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
  167. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +160 -110
  168. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +8 -1
  169. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +217 -86
  170. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
  171. package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
  172. package/dist/phase-diagram/build-diagram.js +9 -9
  173. package/dist/phase-diagram/colors.js +1 -3
  174. package/dist/phase-diagram/index.d.ts +2 -0
  175. package/dist/phase-diagram/index.js +2 -0
  176. package/dist/phase-diagram/parse.js +10 -9
  177. package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
  178. package/dist/phase-diagram/svg-to-diagram.js +869 -0
  179. package/dist/phase-diagram/types.d.ts +10 -0
  180. package/dist/phase-diagram/utils.d.ts +8 -4
  181. package/dist/phase-diagram/utils.js +219 -74
  182. package/dist/plot/AxisLabel.svelte +51 -0
  183. package/dist/plot/AxisLabel.svelte.d.ts +16 -0
  184. package/dist/plot/BarPlot.svelte +1461 -768
  185. package/dist/plot/BarPlot.svelte.d.ts +3 -3
  186. package/dist/plot/BarPlotControls.svelte +33 -6
  187. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  188. package/dist/plot/ColorBar.svelte +533 -383
  189. package/dist/plot/ColorBar.svelte.d.ts +1 -1
  190. package/dist/plot/ColorScaleSelect.svelte +28 -7
  191. package/dist/plot/ElementScatter.svelte +38 -16
  192. package/dist/plot/FillArea.svelte +152 -92
  193. package/dist/plot/Histogram.svelte +1162 -709
  194. package/dist/plot/Histogram.svelte.d.ts +1 -1
  195. package/dist/plot/HistogramControls.svelte +81 -18
  196. package/dist/plot/HistogramControls.svelte.d.ts +6 -2
  197. package/dist/plot/InteractiveAxisLabel.svelte +34 -11
  198. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  199. package/dist/plot/Line.svelte +63 -28
  200. package/dist/plot/PlotControls.svelte +221 -96
  201. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  202. package/dist/plot/PlotLegend.svelte +174 -91
  203. package/dist/plot/PlotTooltip.svelte +45 -6
  204. package/dist/plot/PortalSelect.svelte +175 -146
  205. package/dist/plot/ReferenceLine.svelte +77 -22
  206. package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
  207. package/dist/plot/ReferenceLine3D.svelte +132 -107
  208. package/dist/plot/ReferencePlane.svelte +146 -123
  209. package/dist/plot/ScatterPlot.svelte +1880 -1156
  210. package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
  211. package/dist/plot/ScatterPlot3D.svelte +256 -131
  212. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  213. package/dist/plot/ScatterPlot3DControls.svelte +300 -297
  214. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
  215. package/dist/plot/ScatterPlot3DScene.svelte +608 -406
  216. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  217. package/dist/plot/ScatterPlotControls.svelte +150 -70
  218. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  219. package/dist/plot/ScatterPoint.svelte +98 -26
  220. package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
  221. package/dist/plot/SpacegroupBarPlot.svelte +142 -85
  222. package/dist/plot/Surface3D.svelte +159 -108
  223. package/dist/plot/ZeroLines.svelte +96 -0
  224. package/dist/plot/ZeroLines.svelte.d.ts +32 -0
  225. package/dist/plot/ZoomRect.svelte +23 -0
  226. package/dist/plot/ZoomRect.svelte.d.ts +8 -0
  227. package/dist/plot/axis-utils.d.ts +1 -1
  228. package/dist/plot/axis-utils.js +1 -3
  229. package/dist/plot/data-cleaning.js +12 -28
  230. package/dist/plot/data-transform.js +2 -1
  231. package/dist/plot/fill-utils.js +2 -0
  232. package/dist/plot/index.d.ts +6 -2
  233. package/dist/plot/index.js +6 -2
  234. package/dist/plot/interactions.d.ts +8 -10
  235. package/dist/plot/interactions.js +2 -3
  236. package/dist/plot/layout.d.ts +11 -2
  237. package/dist/plot/layout.js +44 -17
  238. package/dist/plot/reference-line.d.ts +5 -22
  239. package/dist/plot/reference-line.js +12 -84
  240. package/dist/plot/scales.js +24 -36
  241. package/dist/plot/types.d.ts +53 -40
  242. package/dist/plot/types.js +12 -7
  243. package/dist/plot/utils/label-placement.d.ts +32 -15
  244. package/dist/plot/utils/label-placement.js +227 -63
  245. package/dist/plot/utils/series-visibility.js +2 -3
  246. package/dist/plot/utils.d.ts +1 -0
  247. package/dist/plot/utils.js +14 -0
  248. package/dist/rdf/RdfPlot.svelte +173 -132
  249. package/dist/rdf/calc-rdf.js +4 -5
  250. package/dist/sanitize.d.ts +4 -0
  251. package/dist/sanitize.js +107 -0
  252. package/dist/settings.d.ts +21 -6
  253. package/dist/settings.js +63 -19
  254. package/dist/spectral/Bands.svelte +963 -412
  255. package/dist/spectral/Bands.svelte.d.ts +22 -2
  256. package/dist/spectral/BandsAndDos.svelte +90 -49
  257. package/dist/spectral/BrillouinBandsDos.svelte +151 -93
  258. package/dist/spectral/Dos.svelte +389 -258
  259. package/dist/spectral/helpers.d.ts +23 -1
  260. package/dist/spectral/helpers.js +119 -51
  261. package/dist/spectral/types.d.ts +2 -0
  262. package/dist/state.svelte.d.ts +1 -1
  263. package/dist/state.svelte.js +3 -2
  264. package/dist/structure/Arrow.svelte +59 -20
  265. package/dist/structure/AtomLegend.svelte +231 -129
  266. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  267. package/dist/structure/Bond.svelte +73 -47
  268. package/dist/structure/CanvasTooltip.svelte +10 -2
  269. package/dist/structure/CellSelect.svelte +148 -51
  270. package/dist/structure/Cylinder.svelte +33 -17
  271. package/dist/structure/Lattice.svelte +88 -33
  272. package/dist/structure/Structure.svelte +1077 -821
  273. package/dist/structure/Structure.svelte.d.ts +1 -1
  274. package/dist/structure/StructureControls.svelte +373 -139
  275. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  276. package/dist/structure/StructureExportPane.svelte +124 -89
  277. package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
  278. package/dist/structure/StructureInfoPane.svelte +304 -231
  279. package/dist/structure/StructureScene.svelte +919 -445
  280. package/dist/structure/StructureScene.svelte.d.ts +16 -7
  281. package/dist/structure/atom-properties.d.ts +6 -2
  282. package/dist/structure/atom-properties.js +42 -29
  283. package/dist/structure/bonding.js +6 -7
  284. package/dist/structure/export.js +22 -34
  285. package/dist/structure/ferrox-wasm-types.d.ts +3 -2
  286. package/dist/structure/ferrox-wasm-types.js +0 -3
  287. package/dist/structure/ferrox-wasm.d.ts +3 -2
  288. package/dist/structure/ferrox-wasm.js +2 -3
  289. package/dist/structure/index.d.ts +16 -0
  290. package/dist/structure/index.js +88 -6
  291. package/dist/structure/measure.d.ts +2 -2
  292. package/dist/structure/measure.js +4 -44
  293. package/dist/structure/parse.js +130 -155
  294. package/dist/structure/partial-occupancy.d.ts +25 -0
  295. package/dist/structure/partial-occupancy.js +99 -0
  296. package/dist/structure/pbc.d.ts +1 -0
  297. package/dist/structure/pbc.js +16 -6
  298. package/dist/structure/supercell.d.ts +2 -2
  299. package/dist/structure/supercell.js +12 -22
  300. package/dist/structure/validation.js +5 -3
  301. package/dist/symmetry/SymmetryStats.svelte +94 -37
  302. package/dist/symmetry/WyckoffTable.svelte +42 -14
  303. package/dist/symmetry/cell-transform.js +5 -3
  304. package/dist/symmetry/index.d.ts +7 -4
  305. package/dist/symmetry/index.js +87 -21
  306. package/dist/symmetry/spacegroups.js +148 -148
  307. package/dist/table/HeatmapTable.svelte +1112 -516
  308. package/dist/table/HeatmapTable.svelte.d.ts +12 -1
  309. package/dist/table/ToggleMenu.svelte +125 -90
  310. package/dist/table/index.d.ts +2 -0
  311. package/dist/table/index.js +2 -4
  312. package/dist/theme/ThemeControl.svelte +21 -12
  313. package/dist/time.js +4 -1
  314. package/dist/tooltip/TooltipContent.svelte +33 -8
  315. package/dist/trajectory/Trajectory.svelte +889 -687
  316. package/dist/trajectory/TrajectoryError.svelte +14 -3
  317. package/dist/trajectory/TrajectoryExportPane.svelte +148 -90
  318. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
  319. package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
  320. package/dist/trajectory/constants.d.ts +6 -0
  321. package/dist/trajectory/constants.js +7 -0
  322. package/dist/trajectory/extract.js +13 -31
  323. package/dist/trajectory/format-detect.d.ts +9 -0
  324. package/dist/trajectory/format-detect.js +76 -0
  325. package/dist/trajectory/frame-reader.d.ts +17 -0
  326. package/dist/trajectory/frame-reader.js +332 -0
  327. package/dist/trajectory/helpers.d.ts +14 -0
  328. package/dist/trajectory/helpers.js +172 -0
  329. package/dist/trajectory/index.d.ts +1 -0
  330. package/dist/trajectory/index.js +23 -14
  331. package/dist/trajectory/parse/ase.d.ts +2 -0
  332. package/dist/trajectory/parse/ase.js +77 -0
  333. package/dist/trajectory/parse/hdf5.d.ts +2 -0
  334. package/dist/trajectory/parse/hdf5.js +129 -0
  335. package/dist/trajectory/parse/index.d.ts +12 -0
  336. package/dist/trajectory/parse/index.js +299 -0
  337. package/dist/trajectory/parse/lammps.d.ts +5 -0
  338. package/dist/trajectory/parse/lammps.js +179 -0
  339. package/dist/trajectory/parse/vasp.d.ts +2 -0
  340. package/dist/trajectory/parse/vasp.js +68 -0
  341. package/dist/trajectory/parse/xyz.d.ts +2 -0
  342. package/dist/trajectory/parse/xyz.js +110 -0
  343. package/dist/trajectory/plotting.js +13 -8
  344. package/dist/trajectory/types.d.ts +11 -0
  345. package/dist/trajectory/types.js +1 -0
  346. package/dist/utils.d.ts +3 -0
  347. package/dist/utils.js +17 -0
  348. package/dist/xrd/XrdPlot.svelte +337 -245
  349. package/dist/xrd/broadening.js +14 -9
  350. package/dist/xrd/calc-xrd.js +12 -19
  351. package/dist/xrd/parse.d.ts +1 -1
  352. package/dist/xrd/parse.js +17 -17
  353. package/package.json +103 -101
  354. package/readme.md +4 -4
  355. package/dist/trajectory/parse.d.ts +0 -42
  356. package/dist/trajectory/parse.js +0 -1267
  357. /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
  358. /package/dist/theme/{themes.js → themes.mjs} +0 -0
@@ -1,61 +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
- // Helper for axis label updates
48
- const update_axis_label = (axis, setter) => (event) => {
49
- setter({ ...axis, label: get_input_value(event) });
50
- };
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[]>([
103
+ {
104
+ name: `X`,
105
+ axis: x_axis,
106
+ auto_range: auto_x_range,
107
+ set: (val) => (x_axis = val),
108
+ },
109
+ {
110
+ name: `Y`,
111
+ axis: y_axis,
112
+ auto_range: auto_y_range,
113
+ set: (val) => (y_axis = val),
114
+ },
115
+ {
116
+ name: `Z`,
117
+ axis: z_axis,
118
+ auto_range: auto_z_range,
119
+ set: (val) => (z_axis = val),
120
+ },
121
+ ])
51
122
  </script>
52
123
 
53
124
  <DraggablePane
125
+ bind:show
54
126
  {toggle_props}
55
127
  pane_props={{
56
128
  title: `3D Plot Settings`,
57
129
  ...pane_props,
58
- style: `max-height: 80cqh; overflow-y: auto; ${pane_props?.style ?? ``}`,
130
+ style: `--pane-max-height: 80cqh; ${pane_props?.style ?? ``}`,
59
131
  }}
60
132
  >
61
133
  <!-- Camera Controls -->
@@ -138,263 +210,160 @@ const update_axis_label = (axis, setter) => (event) => {
138
210
  </label>
139
211
  </SettingsSection>
140
212
 
141
- <!-- Projections -->
213
+ <!-- Projections: only when there's data to project -->
214
+ {#if series.length > 0}
215
+ <SettingsSection
216
+ title="Projections"
217
+ current_values={{
218
+ xy: display.projections?.xy,
219
+ xz: display.projections?.xz,
220
+ yz: display.projections?.yz,
221
+ opacity: display.projection_opacity,
222
+ scale: display.projection_scale,
223
+ }}
224
+ on_reset={() => {
225
+ display = {
226
+ ...display,
227
+ projections: { xy: false, xz: false, yz: false },
228
+ projection_opacity: 0.3,
229
+ projection_scale: 0.5,
230
+ }
231
+ }}
232
+ >
233
+ <div style="display: flex; flex-wrap: wrap; gap: 1ex">
234
+ <label>
235
+ <input
236
+ type="checkbox"
237
+ checked={display.projections?.xy}
238
+ onchange={toggle_projection(`xy`)}
239
+ /> XY
240
+ </label>
241
+ <label>
242
+ <input
243
+ type="checkbox"
244
+ checked={display.projections?.xz}
245
+ onchange={toggle_projection(`xz`)}
246
+ /> XZ
247
+ </label>
248
+ <label>
249
+ <input
250
+ type="checkbox"
251
+ checked={display.projections?.yz}
252
+ onchange={toggle_projection(`yz`)}
253
+ /> YZ
254
+ </label>
255
+ </div>
256
+ <div class="pane-row">
257
+ <label for="{uid}-proj-opacity">Opacity:</label>
258
+ <input
259
+ id="{uid}-proj-opacity"
260
+ type="range"
261
+ min="0"
262
+ max="1"
263
+ step="0.05"
264
+ value={display.projection_opacity ?? 0.3}
265
+ oninput={update_display(`projection_opacity`)}
266
+ />
267
+ <input
268
+ type="number"
269
+ min="0"
270
+ max="1"
271
+ step="0.05"
272
+ value={display.projection_opacity ?? 0.3}
273
+ oninput={update_display(`projection_opacity`)}
274
+ style="width: 3.5em"
275
+ />
276
+ </div>
277
+ <div class="pane-row">
278
+ <label for="{uid}-proj-scale">Size:</label>
279
+ <input
280
+ id="{uid}-proj-scale"
281
+ type="range"
282
+ min="0.1"
283
+ max="1"
284
+ step="0.05"
285
+ value={display.projection_scale ?? 0.5}
286
+ oninput={update_display(`projection_scale`)}
287
+ />
288
+ <input
289
+ type="number"
290
+ min="0.1"
291
+ max="1"
292
+ step="0.05"
293
+ value={display.projection_scale ?? 0.5}
294
+ oninput={update_display(`projection_scale`)}
295
+ style="width: 3.5em"
296
+ />
297
+ </div>
298
+ </SettingsSection>
299
+ {/if}
300
+
301
+ <!-- Axes (merged X/Y/Z) -->
142
302
  <SettingsSection
143
- title="Projections"
303
+ title="Axes"
144
304
  current_values={{
145
- xy: display.projections?.xy,
146
- xz: display.projections?.xz,
147
- yz: display.projections?.yz,
148
- opacity: display.projection_opacity,
149
- scale: display.projection_scale,
305
+ x_range: x_axis.range,
306
+ y_range: y_axis.range,
307
+ z_range: z_axis.range,
150
308
  }}
151
309
  on_reset={() => {
152
- display = {
153
- ...display,
154
- projections: { xy: false, xz: false, yz: false },
155
- projection_opacity: 0.3,
156
- projection_scale: 0.5,
157
- }
310
+ x_axis = { ...x_axis, range: [null, null] }
311
+ y_axis = { ...y_axis, range: [null, null] }
312
+ z_axis = { ...z_axis, range: [null, null] }
158
313
  }}
159
314
  >
160
- <div style="display: flex; flex-wrap: wrap; gap: 1ex">
161
- <label>
315
+ {#each axes as { name, axis, auto_range, set } (name)}
316
+ <div class="axis-row">
317
+ <span class="axis-name">{name}</span>
162
318
  <input
163
- type="checkbox"
164
- checked={display.projections?.xy}
165
- onchange={toggle_projection(`xy`)}
166
- /> XY
167
- </label>
168
- <label>
319
+ type="text"
320
+ value={axis.label}
321
+ oninput={update_axis_label(axis, set)}
322
+ placeholder="{name} label"
323
+ aria-label="{name} label"
324
+ class="axis-label-input"
325
+ />
169
326
  <input
170
- type="checkbox"
171
- checked={display.projections?.xz}
172
- onchange={toggle_projection(`xz`)}
173
- /> XZ
174
- </label>
175
- <label>
327
+ type="number"
328
+ step="any"
329
+ value={round4(axis.range?.[0] ?? auto_range[0])}
330
+ oninput={(event) => {
331
+ const val = parseFloat((event.target as HTMLInputElement).value)
332
+ if (Number.isNaN(val)) return
333
+ set({ ...axis, range: [val, axis.range?.[1] ?? auto_range[1]] })
334
+ }}
335
+ aria-label="{name} min"
336
+ class="axis-range-input"
337
+ />
338
+ <span class="axis-to">–</span>
176
339
  <input
177
- type="checkbox"
178
- checked={display.projections?.yz}
179
- onchange={toggle_projection(`yz`)}
180
- /> YZ
181
- </label>
182
- </div>
183
- <div class="pane-row">
184
- <label for="{uid}-proj-opacity">Opacity:</label>
185
- <input
186
- id="{uid}-proj-opacity"
187
- type="range"
188
- min="0"
189
- max="1"
190
- step="0.05"
191
- value={display.projection_opacity ?? 0.3}
192
- oninput={update_display(`projection_opacity`)}
193
- />
194
- <input
195
- type="number"
196
- min="0"
197
- max="1"
198
- step="0.05"
199
- value={display.projection_opacity ?? 0.3}
200
- oninput={update_display(`projection_opacity`)}
201
- style="width: 3.5em"
202
- />
203
- </div>
204
- <div class="pane-row">
205
- <label for="{uid}-proj-scale">Size:</label>
206
- <input
207
- id="{uid}-proj-scale"
208
- type="range"
209
- min="0.1"
210
- max="1"
211
- step="0.05"
212
- value={display.projection_scale ?? 0.5}
213
- oninput={update_display(`projection_scale`)}
214
- />
215
- <input
216
- type="number"
217
- min="0.1"
218
- max="1"
219
- step="0.05"
220
- value={display.projection_scale ?? 0.5}
221
- oninput={update_display(`projection_scale`)}
222
- style="width: 3.5em"
223
- />
224
- </div>
225
- </SettingsSection>
226
-
227
- <!-- X Axis Range -->
228
- <SettingsSection
229
- title="X Axis"
230
- current_values={{ range: x_axis.range }}
231
- on_reset={() => (x_axis = { ...x_axis, range: [null, null] })}
232
- >
233
- <div class="pane-row">
234
- <label for="{uid}-x-label">Label:</label>
235
- <input
236
- id="{uid}-x-label"
237
- type="text"
238
- value={x_axis.label}
239
- oninput={update_axis_label(x_axis, (val) => (x_axis = val))}
240
- placeholder="X"
241
- />
242
- </div>
243
- <div class="pane-row">
244
- <label for="{uid}-x-range-min">Range:</label>
245
- <input
246
- id="{uid}-x-range-min"
247
- type="number"
248
- step="any"
249
- value={x_axis.range?.[0] ?? auto_x_range[0]}
250
- oninput={(event) => {
251
- const val = parseFloat((event.target as HTMLInputElement).value)
252
- if (Number.isNaN(val)) return
253
- x_axis = {
254
- ...x_axis,
255
- range: [val, x_axis.range?.[1] ?? auto_x_range[1]],
256
- }
257
- }}
258
- />
259
- <span>to</span>
260
- <input
261
- id="{uid}-x-range-max"
262
- type="number"
263
- step="any"
264
- value={x_axis.range?.[1] ?? auto_x_range[1]}
265
- oninput={(event) => {
266
- const val = parseFloat((event.target as HTMLInputElement).value)
267
- if (Number.isNaN(val)) return
268
- x_axis = {
269
- ...x_axis,
270
- range: [x_axis.range?.[0] ?? auto_x_range[0], val],
271
- }
272
- }}
273
- />
274
- </div>
275
- </SettingsSection>
276
-
277
- <!-- Y Axis Range -->
278
- <SettingsSection
279
- title="Y Axis"
280
- current_values={{ range: y_axis.range }}
281
- on_reset={() => (y_axis = { ...y_axis, range: [null, null] })}
282
- >
283
- <div class="pane-row">
284
- <label for="{uid}-y-label">Label:</label>
285
- <input
286
- id="{uid}-y-label"
287
- type="text"
288
- value={y_axis.label}
289
- oninput={update_axis_label(y_axis, (val) => (y_axis = val))}
290
- placeholder="Y"
291
- />
292
- </div>
293
- <div class="pane-row">
294
- <label for="{uid}-y-range-min">Range:</label>
295
- <input
296
- id="{uid}-y-range-min"
297
- type="number"
298
- step="any"
299
- value={y_axis.range?.[0] ?? auto_y_range[0]}
300
- oninput={(event) => {
301
- const val = parseFloat((event.target as HTMLInputElement).value)
302
- if (Number.isNaN(val)) return
303
- y_axis = {
304
- ...y_axis,
305
- range: [val, y_axis.range?.[1] ?? auto_y_range[1]],
306
- }
307
- }}
308
- />
309
- <span>to</span>
310
- <input
311
- id="{uid}-y-range-max"
312
- type="number"
313
- step="any"
314
- value={y_axis.range?.[1] ?? auto_y_range[1]}
315
- oninput={(event) => {
316
- const val = parseFloat((event.target as HTMLInputElement).value)
317
- if (Number.isNaN(val)) return
318
- y_axis = {
319
- ...y_axis,
320
- range: [y_axis.range?.[0] ?? auto_y_range[0], val],
321
- }
322
- }}
323
- />
324
- </div>
340
+ type="number"
341
+ step="any"
342
+ value={round4(axis.range?.[1] ?? auto_range[1])}
343
+ oninput={(event) => {
344
+ const val = parseFloat((event.target as HTMLInputElement).value)
345
+ if (Number.isNaN(val)) return
346
+ set({ ...axis, range: [axis.range?.[0] ?? auto_range[0], val] })
347
+ }}
348
+ aria-label="{name} max"
349
+ class="axis-range-input"
350
+ />
351
+ </div>
352
+ {/each}
325
353
  </SettingsSection>
326
354
 
327
- <!-- Z Axis Range -->
328
- <SettingsSection
329
- title="Z Axis"
330
- current_values={{ range: z_axis.range }}
331
- on_reset={() => (z_axis = { ...z_axis, range: [null, null] })}
332
- >
333
- <div class="pane-row">
334
- <label for="{uid}-z-label">Label:</label>
335
- <input
336
- id="{uid}-z-label"
337
- type="text"
338
- value={z_axis.label}
339
- oninput={update_axis_label(z_axis, (val) => (z_axis = val))}
340
- placeholder="Z"
341
- />
342
- </div>
343
- <div class="pane-row">
344
- <label for="{uid}-z-range-min">Range:</label>
345
- <input
346
- id="{uid}-z-range-min"
347
- type="number"
348
- step="any"
349
- value={z_axis.range?.[0] ?? auto_z_range[0]}
350
- oninput={(event) => {
351
- const val = parseFloat((event.target as HTMLInputElement).value)
352
- if (Number.isNaN(val)) return
353
- z_axis = {
354
- ...z_axis,
355
- range: [val, z_axis.range?.[1] ?? auto_z_range[1]],
356
- }
357
- }}
358
- />
359
- <span>to</span>
360
- <input
361
- id="{uid}-z-range-max"
362
- type="number"
363
- step="any"
364
- value={z_axis.range?.[1] ?? auto_z_range[1]}
365
- oninput={(event) => {
366
- const val = parseFloat((event.target as HTMLInputElement).value)
367
- if (Number.isNaN(val)) return
368
- z_axis = {
369
- ...z_axis,
370
- range: [z_axis.range?.[0] ?? auto_z_range[0], val],
371
- }
372
- }}
373
- />
355
+ <!-- Data summary: only when there's data -->
356
+ {#if series.length > 0 || surfaces.length > 0}
357
+ <div class="data-summary">
358
+ {#if series.length > 0}
359
+ <span>{series.length} series · {
360
+ series.reduce((sum, srs) => sum + srs.x.length, 0).toLocaleString()
361
+ } points</span>
362
+ {/if}
363
+ {#if surfaces.length > 0}
364
+ <span>{surfaces.length} {surfaces.length === 1 ? `surface` : `surfaces`}</span>
365
+ {/if}
374
366
  </div>
375
- </SettingsSection>
376
-
377
- <!-- Series Info -->
378
- {#if series.length > 0}
379
- <SettingsSection title="Data" current_values={{ series_count: series.length }}>
380
- <div class="pane-row">
381
- <span>Series: {series.length}</span>
382
- </div>
383
- <div class="pane-row">
384
- <span>
385
- Points: {series.reduce((sum, srs) => sum + srs.x.length, 0).toLocaleString()}
386
- </span>
387
- </div>
388
- </SettingsSection>
389
- {/if}
390
-
391
- <!-- Surfaces Info -->
392
- {#if surfaces.length > 0}
393
- <SettingsSection title="Surfaces" current_values={{ surface_count: surfaces.length }}>
394
- <div class="pane-row">
395
- <span>Surfaces: {surfaces.length}</span>
396
- </div>
397
- </SettingsSection>
398
367
  {/if}
399
368
 
400
369
  <!-- User-provided children -->
@@ -416,10 +385,6 @@ const update_axis_label = (axis, setter) => (event) => {
416
385
  .pane-row input[type='number'] {
417
386
  width: 5em;
418
387
  }
419
- .pane-row input[type='text'] {
420
- flex: 1;
421
- min-width: 0;
422
- }
423
388
  .pane-row input[type='range'] {
424
389
  flex: 1;
425
390
  min-width: 4em;
@@ -428,7 +393,45 @@ const update_axis_label = (axis, setter) => (event) => {
428
393
  flex: 1;
429
394
  min-width: 0;
430
395
  }
431
- .pane-row span {
396
+ .axis-row {
397
+ display: flex;
398
+ align-items: center;
399
+ gap: 4px;
400
+ margin: 2px 0;
401
+ font-size: 0.9em;
402
+ }
403
+ .axis-row input {
404
+ box-sizing: border-box;
405
+ height: 1.4em;
406
+ padding: 0 3px;
407
+ font-size: inherit;
408
+ line-height: 1;
409
+ }
410
+ .axis-name {
411
+ font-weight: 600;
412
+ width: 1.2em;
432
413
  flex-shrink: 0;
433
414
  }
415
+ .axis-label-input {
416
+ width: 6em;
417
+ min-width: 0;
418
+ flex-shrink: 1;
419
+ }
420
+ .axis-range-input {
421
+ width: 7em;
422
+ flex: 1;
423
+ min-width: 5em;
424
+ }
425
+ .axis-to {
426
+ flex-shrink: 0;
427
+ opacity: 0.5;
428
+ }
429
+ .data-summary {
430
+ display: flex;
431
+ flex-wrap: wrap;
432
+ gap: 1ex;
433
+ font-size: 0.85em;
434
+ opacity: 0.7;
435
+ margin-top: 4px;
436
+ }
434
437
  </style>
@@ -2,6 +2,7 @@ import DraggablePane from '../overlays/DraggablePane.svelte';
2
2
  import type { AxisConfig3D, CameraProjection3D, DataSeries3D, DisplayConfig3D, Surface3DConfig } from './types';
3
3
  import type { ComponentProps, Snippet } from 'svelte';
4
4
  type $$ComponentProps = {
5
+ show?: boolean;
5
6
  x_axis?: AxisConfig3D;
6
7
  y_axis?: AxisConfig3D;
7
8
  z_axis?: AxisConfig3D;
@@ -14,6 +15,6 @@ type $$ComponentProps = {
14
15
  pane_props?: ComponentProps<typeof DraggablePane>[`pane_props`];
15
16
  children?: Snippet;
16
17
  };
17
- declare const ScatterPlot3DControls: import("svelte").Component<$$ComponentProps, {}, "display" | "x_axis" | "y_axis" | "camera_projection" | "auto_rotate" | "z_axis">;
18
+ declare const ScatterPlot3DControls: import("svelte").Component<$$ComponentProps, {}, "display" | "show" | "x_axis" | "y_axis" | "camera_projection" | "auto_rotate" | "z_axis">;
18
19
  type ScatterPlot3DControls = ReturnType<typeof ScatterPlot3DControls>;
19
20
  export default ScatterPlot3DControls;