matterviz 0.4.0 → 0.4.2

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 (527) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +12 -14
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/app.css +53 -0
  6. package/dist/brillouin/BrillouinZone.svelte +132 -219
  7. package/dist/brillouin/BrillouinZone.svelte.d.ts +9 -20
  8. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  9. package/dist/brillouin/BrillouinZoneExportPane.svelte +47 -96
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  11. package/dist/brillouin/BrillouinZoneInfoPane.svelte +15 -42
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
  13. package/dist/brillouin/BrillouinZoneScene.svelte +63 -230
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +3 -23
  15. package/dist/brillouin/ReciprocalVectors.svelte +39 -0
  16. package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
  17. package/dist/brillouin/compute.d.ts +2 -0
  18. package/dist/brillouin/compute.js +80 -77
  19. package/dist/brillouin/geometry.d.ts +8 -0
  20. package/dist/brillouin/geometry.js +57 -0
  21. package/dist/brillouin/index.d.ts +2 -0
  22. package/dist/brillouin/index.js +2 -0
  23. package/dist/brillouin/types.d.ts +2 -2
  24. package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
  25. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
  26. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +143 -246
  27. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
  28. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +652 -976
  29. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
  30. package/dist/chempot-diagram/async-compute.svelte.js +1 -1
  31. package/dist/chempot-diagram/color.d.ts +3 -6
  32. package/dist/chempot-diagram/color.js +5 -5
  33. package/dist/chempot-diagram/compute.d.ts +3 -3
  34. package/dist/chempot-diagram/compute.js +3 -1
  35. package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
  36. package/dist/chempot-diagram/controls-state.svelte.js +42 -0
  37. package/dist/chempot-diagram/export.d.ts +47 -0
  38. package/dist/chempot-diagram/export.js +133 -0
  39. package/dist/chempot-diagram/index.d.ts +1 -0
  40. package/dist/chempot-diagram/index.js +1 -0
  41. package/dist/chempot-diagram/pointer.d.ts +0 -10
  42. package/dist/chempot-diagram/pointer.js +4 -4
  43. package/dist/chempot-diagram/types.d.ts +3 -3
  44. package/dist/colors/index.d.ts +0 -4
  45. package/dist/colors/index.js +21 -22
  46. package/dist/composition/BarChart.svelte +37 -31
  47. package/dist/composition/BubbleChart.svelte +17 -17
  48. package/dist/composition/Composition.svelte +7 -11
  49. package/dist/composition/Formula.svelte +18 -25
  50. package/dist/composition/FormulaFilter.svelte +96 -98
  51. package/dist/composition/PieChart.svelte +60 -46
  52. package/dist/composition/chem-sys.js +3 -2
  53. package/dist/composition/format.js +4 -3
  54. package/dist/composition/index.d.ts +2 -0
  55. package/dist/composition/index.js +14 -0
  56. package/dist/composition/parse.d.ts +2 -3
  57. package/dist/composition/parse.js +27 -28
  58. package/dist/constants.js +11 -9
  59. package/dist/controls.d.ts +1 -0
  60. package/dist/controls.js +0 -1
  61. package/dist/convex-hull/ConvexHull.svelte +20 -25
  62. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
  63. package/dist/convex-hull/ConvexHull2D.svelte +176 -256
  64. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  65. package/dist/convex-hull/ConvexHull3D.svelte +269 -804
  66. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  67. package/dist/convex-hull/ConvexHull4D.svelte +236 -755
  68. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  69. package/dist/convex-hull/ConvexHullChrome.svelte +264 -0
  70. package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
  71. package/dist/convex-hull/ConvexHullControls.svelte +128 -49
  72. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
  73. package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
  74. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
  75. package/dist/convex-hull/ConvexHullStats.svelte +210 -351
  76. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
  77. package/dist/convex-hull/ConvexHullTooltip.svelte +16 -14
  78. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
  79. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  80. package/dist/convex-hull/StructurePopup.svelte +17 -21
  81. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  82. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  83. package/dist/convex-hull/barycentric-coords.d.ts +2 -4
  84. package/dist/convex-hull/barycentric-coords.js +6 -33
  85. package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
  86. package/dist/convex-hull/canvas-interactions.svelte.js +279 -0
  87. package/dist/convex-hull/helpers.d.ts +47 -17
  88. package/dist/convex-hull/helpers.js +186 -101
  89. package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
  90. package/dist/convex-hull/hull-state.svelte.js +124 -0
  91. package/dist/convex-hull/index.d.ts +9 -7
  92. package/dist/convex-hull/index.js +7 -2
  93. package/dist/convex-hull/thermodynamics.js +109 -937
  94. package/dist/convex-hull/types.d.ts +12 -4
  95. package/dist/convex-hull/types.js +12 -0
  96. package/dist/coordination/CoordinationBarPlot.svelte +41 -43
  97. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  98. package/dist/coordination/calc-coordination.d.ts +1 -1
  99. package/dist/coordination/calc-coordination.js +28 -25
  100. package/dist/element/BohrAtom.svelte +6 -8
  101. package/dist/element/ElementHeading.svelte +4 -1
  102. package/dist/element/ElementPhoto.svelte +11 -9
  103. package/dist/element/ElementStats.svelte +12 -10
  104. package/dist/element/ElementTile.svelte +24 -29
  105. package/dist/element/ElementTile.svelte.d.ts +1 -1
  106. package/dist/element/Nucleus.svelte +4 -2
  107. package/dist/element/data.d.ts +1 -2
  108. package/dist/element/helpers.d.ts +4 -0
  109. package/dist/element/helpers.js +18 -0
  110. package/dist/element/index.d.ts +1 -0
  111. package/dist/element/index.js +3 -0
  112. package/dist/feedback/DragOverlay.svelte +5 -3
  113. package/dist/feedback/DragOverlay.svelte.d.ts +2 -1
  114. package/dist/feedback/StatusMessage.svelte +20 -7
  115. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  116. package/dist/fermi-surface/FermiSurface.svelte +78 -165
  117. package/dist/fermi-surface/FermiSurface.svelte.d.ts +9 -20
  118. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  119. package/dist/fermi-surface/FermiSurfaceScene.svelte +93 -272
  120. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
  121. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  122. package/dist/fermi-surface/compute.js +14 -13
  123. package/dist/fermi-surface/export.js +4 -15
  124. package/dist/fermi-surface/index.d.ts +0 -1
  125. package/dist/fermi-surface/index.js +0 -1
  126. package/dist/fermi-surface/parse.d.ts +1 -1
  127. package/dist/fermi-surface/parse.js +84 -97
  128. package/dist/fermi-surface/types.d.ts +2 -2
  129. package/dist/heatmap-matrix/HeatmapMatrix.svelte +161 -185
  130. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +6 -5
  131. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +12 -9
  132. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
  133. package/dist/heatmap-matrix/index.d.ts +8 -2
  134. package/dist/icons.d.ts +4 -0
  135. package/dist/icons.js +4 -0
  136. package/dist/index.d.ts +1 -0
  137. package/dist/index.js +1 -0
  138. package/dist/io/ExportPane.svelte +170 -0
  139. package/dist/io/ExportPane.svelte.d.ts +17 -0
  140. package/dist/io/decompress.d.ts +2 -1
  141. package/dist/io/decompress.js +22 -36
  142. package/dist/io/export.d.ts +9 -1
  143. package/dist/io/export.js +37 -29
  144. package/dist/io/fetch.d.ts +2 -4
  145. package/dist/io/fetch.js +0 -11
  146. package/dist/io/file-drop.d.ts +7 -0
  147. package/dist/io/file-drop.js +13 -0
  148. package/dist/io/index.d.ts +1 -0
  149. package/dist/io/index.js +3 -0
  150. package/dist/io/is-binary.d.ts +9 -0
  151. package/dist/io/is-binary.js +45 -1
  152. package/dist/io/types.d.ts +13 -0
  153. package/dist/io/url-drop.js +13 -25
  154. package/dist/isosurface/Isosurface.svelte +17 -23
  155. package/dist/isosurface/IsosurfaceControls.svelte +37 -42
  156. package/dist/isosurface/parse-vaspwave.d.ts +3 -0
  157. package/dist/isosurface/parse-vaspwave.js +138 -0
  158. package/dist/isosurface/parse.js +50 -48
  159. package/dist/labels.d.ts +6 -2
  160. package/dist/labels.js +44 -14
  161. package/dist/layout/FullscreenButton.svelte +34 -0
  162. package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
  163. package/dist/layout/FullscreenToggle.svelte +12 -12
  164. package/dist/layout/InfoCard.svelte +7 -18
  165. package/dist/layout/InfoTag.svelte +1 -3
  166. package/dist/layout/NumberRangeInput.svelte +46 -0
  167. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  168. package/dist/layout/PropertyFilter.svelte +2 -6
  169. package/dist/layout/SettingsSection.svelte +21 -17
  170. package/dist/layout/SubpageGrid.svelte +3 -1
  171. package/dist/layout/ViewerChrome.svelte +115 -0
  172. package/dist/layout/ViewerChrome.svelte.d.ts +18 -0
  173. package/dist/layout/fullscreen.d.ts +4 -0
  174. package/dist/layout/fullscreen.js +3 -5
  175. package/dist/layout/fullscreen.svelte.d.ts +8 -0
  176. package/dist/layout/fullscreen.svelte.js +36 -0
  177. package/dist/layout/index.d.ts +4 -0
  178. package/dist/layout/index.js +4 -0
  179. package/dist/layout/json-tree/JsonNode.svelte +8 -11
  180. package/dist/layout/json-tree/JsonTree.svelte +53 -77
  181. package/dist/layout/json-tree/JsonValue.svelte +7 -15
  182. package/dist/layout/json-tree/utils.js +14 -23
  183. package/dist/math.d.ts +9 -3
  184. package/dist/math.js +37 -21
  185. package/dist/overlays/ContextMenu.svelte +4 -2
  186. package/dist/overlays/CopyButton.svelte +11 -5
  187. package/dist/overlays/DragControlTab.svelte +6 -1
  188. package/dist/overlays/DraggablePane.svelte +81 -26
  189. package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
  190. package/dist/overlays/GlassChip.svelte +30 -0
  191. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  192. package/dist/overlays/InfoPaneCards.svelte +11 -23
  193. package/dist/overlays/index.d.ts +11 -0
  194. package/dist/overlays/index.js +26 -0
  195. package/dist/overlays/portal.d.ts +2 -0
  196. package/dist/overlays/portal.js +14 -0
  197. package/dist/periodic-table/PeriodicTable.svelte +115 -146
  198. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  199. package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
  200. package/dist/periodic-table/TableInset.svelte +9 -4
  201. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
  202. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  203. package/dist/phase-diagram/PhaseDiagramControls.svelte +73 -96
  204. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
  205. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
  206. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
  207. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +49 -134
  208. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
  209. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  210. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  211. package/dist/phase-diagram/build-diagram.js +3 -3
  212. package/dist/phase-diagram/colors.js +1 -1
  213. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  214. package/dist/phase-diagram/parse.d.ts +2 -1
  215. package/dist/phase-diagram/parse.js +15 -15
  216. package/dist/phase-diagram/svg-to-diagram.js +21 -15
  217. package/dist/phase-diagram/utils.js +2 -3
  218. package/dist/plot/bar/BarPlot.svelte +494 -692
  219. package/dist/plot/bar/BarPlot.svelte.d.ts +9 -15
  220. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  221. package/dist/plot/bar/BarPlotControls.svelte.d.ts +5 -7
  222. package/dist/plot/bar/SpacegroupBarPlot.svelte +31 -37
  223. package/dist/plot/bar/data.d.ts +5 -4
  224. package/dist/plot/bar/data.js +2 -1
  225. package/dist/plot/box/BoxPlot.svelte +361 -439
  226. package/dist/plot/box/BoxPlot.svelte.d.ts +6 -3
  227. package/dist/plot/box/BoxPlotControls.svelte.d.ts +1 -1
  228. package/dist/plot/box/Violin.svelte.d.ts +2 -1
  229. package/dist/plot/box/box-plot.d.ts +3 -2
  230. package/dist/plot/box/box-plot.js +6 -3
  231. package/dist/plot/box/kde.d.ts +2 -1
  232. package/dist/plot/box/kde.js +4 -4
  233. package/dist/plot/core/auto-place.d.ts +1 -1
  234. package/dist/plot/core/auto-place.js +5 -2
  235. package/dist/plot/core/axis-utils.d.ts +12 -7
  236. package/dist/plot/core/axis-utils.js +48 -48
  237. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  238. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  239. package/dist/plot/core/components/ColorBar.svelte +106 -111
  240. package/dist/plot/core/components/ColorBar.svelte.d.ts +5 -4
  241. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  242. package/dist/plot/core/components/FillArea.svelte +10 -17
  243. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  244. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  245. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  246. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  247. package/dist/plot/core/components/Line.svelte +21 -11
  248. package/dist/plot/core/components/Line.svelte.d.ts +5 -2
  249. package/dist/plot/core/components/PlotAxis.svelte +42 -18
  250. package/dist/plot/core/components/PlotAxis.svelte.d.ts +2 -1
  251. package/dist/plot/core/components/PlotControls.svelte +65 -41
  252. package/dist/plot/core/components/PlotControls.svelte.d.ts +1 -1
  253. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  254. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  255. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  256. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  257. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  258. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  259. package/dist/plot/core/components/ReferenceLine3D.svelte +56 -59
  260. package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +4 -4
  261. package/dist/plot/core/components/ReferencePlane.svelte +9 -10
  262. package/dist/plot/core/components/ReferencePlane.svelte.d.ts +4 -4
  263. package/dist/plot/core/components/ZeroLines.svelte +4 -8
  264. package/dist/plot/core/components/ZoomRect.svelte +1 -2
  265. package/dist/plot/core/components/index.d.ts +1 -0
  266. package/dist/plot/core/components/index.js +1 -0
  267. package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
  268. package/dist/plot/core/data-cleaning-signal.js +467 -0
  269. package/dist/plot/core/data-cleaning.d.ts +2 -42
  270. package/dist/plot/core/data-cleaning.js +29 -476
  271. package/dist/plot/core/data-transform.js +9 -5
  272. package/dist/plot/core/fill-utils.d.ts +7 -4
  273. package/dist/plot/core/fill-utils.js +34 -9
  274. package/dist/plot/core/index.d.ts +1 -0
  275. package/dist/plot/core/index.js +1 -0
  276. package/dist/plot/core/interactions.d.ts +5 -1
  277. package/dist/plot/core/interactions.js +14 -2
  278. package/dist/plot/core/layout.d.ts +3 -1
  279. package/dist/plot/core/layout.js +22 -13
  280. package/dist/plot/core/marginals.d.ts +170 -0
  281. package/dist/plot/core/marginals.js +436 -0
  282. package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
  283. package/dist/plot/core/pan-zoom.svelte.js +221 -0
  284. package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
  285. package/dist/plot/core/placed-tween.svelte.js +68 -0
  286. package/dist/plot/core/reference-line.d.ts +10 -10
  287. package/dist/plot/core/reference-line.js +7 -7
  288. package/dist/plot/core/scales.d.ts +40 -25
  289. package/dist/plot/core/scales.js +49 -21
  290. package/dist/plot/core/svg.d.ts +2 -1
  291. package/dist/plot/core/types/fills.d.ts +101 -0
  292. package/dist/plot/core/types/fills.js +15 -0
  293. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  294. package/dist/plot/core/types/plot-3d.js +4 -0
  295. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  296. package/dist/plot/core/types/reference-lines.js +9 -0
  297. package/dist/plot/core/types.d.ts +47 -331
  298. package/dist/plot/core/types.js +23 -20
  299. package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
  300. package/dist/plot/core/utils/hierarchy-chart.js +179 -0
  301. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  302. package/dist/plot/core/utils/hierarchy-labels.js +99 -0
  303. package/dist/plot/core/utils/label-placement.d.ts +1 -1
  304. package/dist/plot/core/utils/label-placement.js +5 -5
  305. package/dist/plot/core/utils.d.ts +2 -1
  306. package/dist/plot/histogram/Histogram.svelte +373 -631
  307. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  308. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  309. package/dist/plot/histogram/HistogramControls.svelte.d.ts +1 -1
  310. package/dist/plot/histogram/histogram.d.ts +31 -0
  311. package/dist/plot/histogram/histogram.js +70 -0
  312. package/dist/plot/histogram/index.d.ts +1 -0
  313. package/dist/plot/histogram/index.js +1 -0
  314. package/dist/plot/index.d.ts +1 -0
  315. package/dist/plot/index.js +1 -0
  316. package/dist/plot/sankey/Sankey.svelte +79 -73
  317. package/dist/plot/sankey/Sankey.svelte.d.ts +3 -3
  318. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  319. package/dist/plot/sankey/sankey.js +3 -1
  320. package/dist/plot/scatter/BinnedScatterPlot.svelte +264 -112
  321. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +11 -4
  322. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  323. package/dist/plot/scatter/ScatterPlot.svelte +623 -821
  324. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +9 -15
  325. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  326. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  327. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  328. package/dist/plot/scatter/binned-scatter-types.d.ts +6 -12
  329. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  330. package/dist/plot/scatter/index.d.ts +1 -1
  331. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  332. package/dist/plot/scatter/scatter-data.js +8 -7
  333. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +40 -60
  334. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +6 -14
  335. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +17 -15
  336. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +5 -5
  337. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +232 -234
  338. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +5 -14
  339. package/dist/plot/scatter-3d/Surface3D.svelte +9 -17
  340. package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +4 -3
  341. package/dist/plot/sunburst/Sunburst.svelte +256 -338
  342. package/dist/plot/sunburst/Sunburst.svelte.d.ts +4 -3
  343. package/dist/plot/sunburst/index.d.ts +1 -1
  344. package/dist/plot/sunburst/index.js +2 -1
  345. package/dist/plot/sunburst/render.d.ts +2 -2
  346. package/dist/plot/sunburst/render.js +47 -22
  347. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  348. package/dist/plot/sunburst/sunburst.js +14 -4
  349. package/dist/plot/treemap/Treemap.svelte +907 -0
  350. package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
  351. package/dist/plot/treemap/index.d.ts +3 -0
  352. package/dist/plot/treemap/index.js +4 -0
  353. package/dist/plot/treemap/treemap.d.ts +26 -0
  354. package/dist/plot/treemap/treemap.js +99 -0
  355. package/dist/rdf/RdfPlot.svelte +22 -26
  356. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  357. package/dist/rdf/calc-rdf.js +4 -8
  358. package/dist/sanitize.js +14 -3
  359. package/dist/scene/SceneCamera.svelte +62 -0
  360. package/dist/scene/SceneCamera.svelte.d.ts +19 -0
  361. package/dist/scene/bind-renderer.svelte.d.ts +2 -0
  362. package/dist/scene/bind-renderer.svelte.js +22 -0
  363. package/dist/scene/index.d.ts +4 -0
  364. package/dist/scene/index.js +5 -0
  365. package/dist/scene/props.js +52 -0
  366. package/dist/scene/types.d.ts +26 -0
  367. package/dist/scene/types.js +1 -0
  368. package/dist/settings.d.ts +33 -11
  369. package/dist/settings.js +136 -51
  370. package/dist/spectral/Bands.svelte +231 -237
  371. package/dist/spectral/Bands.svelte.d.ts +3 -2
  372. package/dist/spectral/BandsAndDos.svelte +29 -29
  373. package/dist/spectral/BrillouinBandsDos.svelte +21 -29
  374. package/dist/spectral/Dos.svelte +75 -77
  375. package/dist/spectral/Dos.svelte.d.ts +2 -1
  376. package/dist/spectral/helpers.d.ts +9 -9
  377. package/dist/spectral/helpers.js +66 -70
  378. package/dist/state.svelte.d.ts +0 -7
  379. package/dist/state.svelte.js +5 -24
  380. package/dist/structure/Arrow.svelte +6 -21
  381. package/dist/structure/ArrowInstances.svelte +160 -0
  382. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  383. package/dist/structure/AtomLegend.svelte +115 -75
  384. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  385. package/dist/structure/Bond.svelte +31 -23
  386. package/dist/structure/CanvasTooltip.svelte +16 -3
  387. package/dist/structure/CellSelect.svelte +22 -29
  388. package/dist/structure/CellSelect.svelte.d.ts +2 -1
  389. package/dist/structure/Cylinder.svelte +24 -40
  390. package/dist/structure/InstancedAtoms.svelte +114 -0
  391. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  392. package/dist/structure/Lattice.svelte +85 -149
  393. package/dist/structure/SiteLabels.svelte +122 -0
  394. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  395. package/dist/structure/Structure.svelte +725 -735
  396. package/dist/structure/Structure.svelte.d.ts +8 -16
  397. package/dist/structure/StructureCarousel.svelte +630 -0
  398. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  399. package/dist/structure/StructureControls.svelte +298 -325
  400. package/dist/structure/StructureControls.svelte.d.ts +5 -3
  401. package/dist/structure/StructureExportPane.svelte +62 -168
  402. package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
  403. package/dist/structure/StructureInfoPane.svelte +77 -69
  404. package/dist/structure/StructureInfoPane.svelte.d.ts +6 -6
  405. package/dist/structure/StructureScene.svelte +758 -600
  406. package/dist/structure/StructureScene.svelte.d.ts +24 -20
  407. package/dist/structure/StructureViewport.svelte +386 -0
  408. package/dist/structure/StructureViewport.svelte.d.ts +63 -0
  409. package/dist/structure/atom-label-placement.d.ts +18 -0
  410. package/dist/structure/atom-label-placement.js +115 -0
  411. package/dist/structure/atom-properties.d.ts +3 -1
  412. package/dist/structure/atom-properties.js +115 -54
  413. package/dist/structure/bond-order-perception.js +2 -4
  414. package/dist/structure/bonding.d.ts +12 -2
  415. package/dist/structure/bonding.js +172 -73
  416. package/dist/structure/edit-history.d.ts +6 -0
  417. package/dist/structure/edit-history.js +27 -0
  418. package/dist/structure/export.d.ts +25 -4
  419. package/dist/structure/export.js +103 -153
  420. package/dist/structure/format-detect.d.ts +1 -0
  421. package/dist/structure/format-detect.js +22 -0
  422. package/dist/structure/geometry.d.ts +9 -0
  423. package/dist/structure/geometry.js +27 -0
  424. package/dist/structure/index.d.ts +18 -1
  425. package/dist/structure/index.js +15 -2
  426. package/dist/structure/measure.d.ts +1 -1
  427. package/dist/structure/measure.js +6 -12
  428. package/dist/structure/parse.d.ts +5 -3
  429. package/dist/structure/parse.js +551 -567
  430. package/dist/structure/partial-occupancy.d.ts +0 -1
  431. package/dist/structure/partial-occupancy.js +5 -3
  432. package/dist/structure/pbc.d.ts +1 -1
  433. package/dist/structure/pbc.js +204 -51
  434. package/dist/structure/polyhedra.d.ts +40 -0
  435. package/dist/structure/polyhedra.js +587 -0
  436. package/dist/structure/site.d.ts +4 -0
  437. package/dist/structure/site.js +1 -0
  438. package/dist/structure/supercell.d.ts +1 -2
  439. package/dist/structure/supercell.js +10 -15
  440. package/dist/structure/validation.js +5 -6
  441. package/dist/symmetry/SymmetryElementControls.svelte +69 -0
  442. package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
  443. package/dist/symmetry/SymmetryElements.svelte +350 -0
  444. package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
  445. package/dist/symmetry/SymmetryStats.svelte +142 -49
  446. package/dist/symmetry/WyckoffTable.svelte +58 -16
  447. package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
  448. package/dist/symmetry/cell-transform.js +8 -14
  449. package/dist/symmetry/index.d.ts +15 -4
  450. package/dist/symmetry/index.js +308 -81
  451. package/dist/symmetry/spacegroups.d.ts +5 -1
  452. package/dist/symmetry/spacegroups.js +18 -3
  453. package/dist/symmetry/symmetry-elements.d.ts +33 -0
  454. package/dist/symmetry/symmetry-elements.js +521 -0
  455. package/dist/symmetry/wyckoff-db.d.ts +9 -0
  456. package/dist/symmetry/wyckoff-db.js +87 -0
  457. package/dist/table/HeatmapTable.svelte +1104 -378
  458. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  459. package/dist/table/ToggleMenu.svelte +5 -12
  460. package/dist/table/index.d.ts +21 -6
  461. package/dist/table/index.js +34 -21
  462. package/dist/theme/ThemeControl.svelte +16 -8
  463. package/dist/theme/index.d.ts +1 -5
  464. package/dist/theme/index.js +4 -10
  465. package/dist/theme/themes.mjs +14 -7
  466. package/dist/tooltip/KCoords.svelte +4 -1
  467. package/dist/tooltip/TooltipContent.svelte +2 -5
  468. package/dist/trajectory/Trajectory.svelte +556 -352
  469. package/dist/trajectory/Trajectory.svelte.d.ts +10 -22
  470. package/dist/trajectory/TrajectoryError.svelte +11 -8
  471. package/dist/trajectory/TrajectoryExportPane.svelte +28 -54
  472. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
  473. package/dist/trajectory/TrajectoryInfoPane.svelte +88 -99
  474. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
  475. package/dist/trajectory/constants.js +6 -2
  476. package/dist/trajectory/extract.js +73 -71
  477. package/dist/trajectory/format-detect.d.ts +0 -1
  478. package/dist/trajectory/format-detect.js +13 -17
  479. package/dist/trajectory/frame-reader.d.ts +2 -1
  480. package/dist/trajectory/frame-reader.js +74 -136
  481. package/dist/trajectory/helpers.d.ts +12 -2
  482. package/dist/trajectory/helpers.js +68 -37
  483. package/dist/trajectory/index.d.ts +1 -0
  484. package/dist/trajectory/index.js +3 -0
  485. package/dist/trajectory/parse/ase.d.ts +9 -1
  486. package/dist/trajectory/parse/ase.js +47 -32
  487. package/dist/trajectory/parse/diagnostics.d.ts +3 -0
  488. package/dist/trajectory/parse/diagnostics.js +14 -0
  489. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  490. package/dist/trajectory/parse/h5-utils.js +109 -0
  491. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  492. package/dist/trajectory/parse/hdf5.js +116 -106
  493. package/dist/trajectory/parse/index.d.ts +3 -4
  494. package/dist/trajectory/parse/index.js +68 -119
  495. package/dist/trajectory/parse/lammps.d.ts +0 -2
  496. package/dist/trajectory/parse/lammps.js +14 -16
  497. package/dist/trajectory/parse/pymatgen.d.ts +2 -0
  498. package/dist/trajectory/parse/pymatgen.js +74 -0
  499. package/dist/trajectory/parse/vasp.js +13 -9
  500. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  501. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  502. package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
  503. package/dist/trajectory/parse/vaspout-h5.js +284 -0
  504. package/dist/trajectory/parse/xyz.d.ts +9 -21
  505. package/dist/trajectory/parse/xyz.js +38 -39
  506. package/dist/trajectory/plotting.d.ts +8 -10
  507. package/dist/trajectory/plotting.js +102 -127
  508. package/dist/utils.d.ts +4 -0
  509. package/dist/utils.js +8 -1
  510. package/dist/xrd/XrdPlot.svelte +56 -85
  511. package/dist/xrd/broadening.d.ts +2 -1
  512. package/dist/xrd/broadening.js +2 -1
  513. package/dist/xrd/calc-xrd.js +8 -15
  514. package/dist/xrd/index.d.ts +2 -2
  515. package/dist/xrd/parse.d.ts +0 -1
  516. package/dist/xrd/parse.js +56 -73
  517. package/package.json +77 -36
  518. package/dist/api/mp.d.ts +0 -6
  519. package/dist/api/mp.js +0 -22
  520. package/dist/element/data.json +0 -11864
  521. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  522. package/dist/fermi-surface/marching-cubes.js +0 -2
  523. package/dist/plot/core/hover-lock.svelte.d.ts +0 -14
  524. package/dist/plot/core/hover-lock.svelte.js +0 -45
  525. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
  526. package/dist/structure/label-placement.d.ts +0 -14
  527. package/dist/structure/label-placement.js +0 -72
@@ -2,7 +2,6 @@
2
2
  lang="ts"
3
3
  generics="Metadata extends Record<string, unknown> = Record<string, unknown>"
4
4
  >
5
- import type { D3ColorSchemeName, D3InterpolateName } from '../../colors'
6
5
  import { format_num } from '../../labels'
7
6
  import type { Vec2, Vec3 } from '../../math'
8
7
  import type {
@@ -13,12 +12,14 @@
13
12
  InternalPoint3D,
14
13
  RefLine3D,
15
14
  RefPlane,
16
- ScaleType,
17
15
  Scatter3DHandlerEvent,
16
+ SizeScaleConfig,
18
17
  StyleOverrides3D,
19
18
  Surface3DConfig,
20
19
  } from '../core/types'
21
- import { T, useTask, useThrelte } from '@threlte/core'
20
+ import { SCALE_DEFAULTS } from '../core/types'
21
+ import { bind_renderer } from '../../scene'
22
+ import { T, useTask } from '@threlte/core'
22
23
  import * as extras from '@threlte/extras'
23
24
  import { scaleLinear } from 'd3-scale'
24
25
  import { type ComponentProps, onDestroy, type Snippet, untrack } from 'svelte'
@@ -31,7 +32,7 @@
31
32
  import { normalize_to_scene } from '../core/reference-line'
32
33
  import ReferenceLine3D from '../core/components/ReferenceLine3D.svelte'
33
34
  import ReferencePlane from '../core/components/ReferencePlane.svelte'
34
- import { create_color_scale, create_size_scale } from '../core/scales'
35
+ import { create_size_scale } from '../core/scales'
35
36
  import Surface3D from './Surface3D.svelte'
36
37
 
37
38
  let {
@@ -45,8 +46,8 @@
45
46
  surfaces = [],
46
47
  ref_lines = [],
47
48
  ref_planes = [],
48
- color_scale = { type: `linear`, scheme: `interpolateViridis` },
49
- size_scale = { type: `linear`, radius_range: [0.05, 0.2] },
49
+ color_scale_fn = () => get_series_color(0),
50
+ size_scale = SCALE_DEFAULTS.size_3d,
50
51
  camera_position = [10, 10, 10] as Vec3,
51
52
  camera_projection = `perspective` as CameraProjection3D,
52
53
  auto_rotate = 0,
@@ -81,16 +82,9 @@
81
82
  surfaces?: Surface3DConfig[]
82
83
  ref_lines?: RefLine3D[]
83
84
  ref_planes?: RefPlane[]
84
- color_scale?: {
85
- type?: ScaleType
86
- scheme?: D3ColorSchemeName | D3InterpolateName
87
- value_range?: [number, number]
88
- }
89
- size_scale?: {
90
- type?: ScaleType
91
- radius_range?: [number, number]
92
- value_range?: [number, number]
93
- }
85
+ // Color scale function for color_values (computed once by the ScatterPlot3D wrapper)
86
+ color_scale_fn?: (value: number) => string
87
+ size_scale?: SizeScaleConfig
94
88
  camera_position?: Vec3
95
89
  camera_projection?: CameraProjection3D
96
90
  auto_rotate?: number
@@ -116,10 +110,10 @@
116
110
  height?: number
117
111
  } = $props()
118
112
 
119
- const threlte = useThrelte()
120
- $effect(() => {
121
- scene = threlte.scene
122
- camera = threlte.camera.current
113
+ // Mirrors scene/camera into bindable props and tags the canvas so export_canvas_as_png can re-render at export DPI
114
+ bind_renderer((threlte_scene, threlte_camera) => {
115
+ scene = threlte_scene
116
+ camera = threlte_camera
123
117
  })
124
118
 
125
119
  extras.interactivity()
@@ -157,49 +151,47 @@
157
151
 
158
152
  // Flatten all points from series
159
153
  let all_points = $derived(
160
- series
161
- .filter(Boolean)
162
- .flatMap((srs, series_idx) =>
163
- srs.x.map((x_val, point_idx) => ({
164
- x: x_val,
165
- y: srs.y[point_idx],
166
- z: srs.z[point_idx],
167
- series_idx,
168
- point_idx,
169
- color_value: srs.color_values?.[point_idx] ?? null,
170
- size_value: srs.size_values?.[point_idx] ?? null,
171
- metadata: Array.isArray(srs.metadata)
172
- ? srs.metadata[point_idx]
173
- : srs.metadata,
174
- point_style: Array.isArray(srs.point_style)
175
- ? srs.point_style[point_idx]
176
- : srs.point_style,
177
- }))
178
- ),
154
+ series.filter(Boolean).flatMap((srs, series_idx) =>
155
+ srs.x.map((x_val, point_idx) => ({
156
+ x: x_val,
157
+ y: srs.y[point_idx],
158
+ z: srs.z[point_idx],
159
+ series_idx,
160
+ point_idx,
161
+ color_value: srs.color_values?.[point_idx] ?? null,
162
+ size_value: srs.size_values?.[point_idx] ?? null,
163
+ metadata: Array.isArray(srs.metadata) ? srs.metadata[point_idx] : srs.metadata,
164
+ point_style: Array.isArray(srs.point_style)
165
+ ? srs.point_style[point_idx]
166
+ : srs.point_style,
167
+ })),
168
+ ),
179
169
  )
180
170
 
181
171
  // Sample surface points for range calculation (10x10 grid)
182
- function sample_surface(
183
- surface: Surface3DConfig,
184
- ): { x: number; y: number; z: number }[] {
185
- const n = 10
172
+ function sample_surface(surface: Surface3DConfig): { x: number; y: number; z: number }[] {
173
+ const grid_steps = 10
186
174
  const pts: { x: number; y: number; z: number }[] = []
187
175
  if (surface.type === `grid` && surface.z_fn) {
188
176
  const [x0, x1] = surface.x_range ?? [-1, 1]
189
177
  const [y0, y1] = surface.y_range ?? [-1, 1]
190
- for (let i = 0; i <= n; i++) {
191
- for (let j = 0; j <= n; j++) {
192
- const x = x0 + (i / n) * (x1 - x0), y = y0 + (j / n) * (y1 - y0)
178
+ for (let idx_x = 0; idx_x <= grid_steps; idx_x++) {
179
+ for (let idx_y = 0; idx_y <= grid_steps; idx_y++) {
180
+ const x = x0 + (idx_x / grid_steps) * (x1 - x0),
181
+ y = y0 + (idx_y / grid_steps) * (y1 - y0)
193
182
  pts.push({ x, y, z: surface.z_fn(x, y) })
194
183
  }
195
184
  }
196
185
  } else if (surface.type === `parametric` && surface.parametric_fn) {
197
186
  const [u0, u1] = surface.u_range ?? [0, 1]
198
187
  const [v0, v1] = surface.v_range ?? [0, 1]
199
- for (let i = 0; i <= n; i++) {
200
- for (let j = 0; j <= n; j++) {
188
+ for (let idx_u = 0; idx_u <= grid_steps; idx_u++) {
189
+ for (let idx_v = 0; idx_v <= grid_steps; idx_v++) {
201
190
  pts.push(
202
- surface.parametric_fn(u0 + (i / n) * (u1 - u0), v0 + (j / n) * (v1 - v0)),
191
+ surface.parametric_fn(
192
+ u0 + (idx_u / grid_steps) * (u1 - u0),
193
+ v0 + (idx_v / grid_steps) * (v1 - v0),
194
+ ),
203
195
  )
204
196
  }
205
197
  }
@@ -209,78 +201,69 @@
209
201
  return pts.filter((pt) => isFinite(pt.x) && isFinite(pt.y) && isFinite(pt.z))
210
202
  }
211
203
 
212
- // Compute axis range with D3's nice() for clean boundaries
204
+ // Compute axis range with D3's nice(); data_min/data_max are the finite extent (Infinity/-Infinity when empty)
213
205
  function compute_range(
214
- values: number[],
206
+ [data_min, data_max]: Vec2,
215
207
  range?: [number | null, number | null],
216
208
  ): Vec2 {
217
209
  if (range?.[0] != null && range?.[1] != null) return range as Vec2
218
- const valid = values.filter(isFinite)
219
- if (valid.length === 0) return [0, 1]
220
- let [min, max] = [Math.min(...valid), Math.max(...valid)]
221
- const pad = min === max
222
- ? (min === 0 ? 1 : Math.abs(min * 0.1))
223
- : (max - min) * 0.05
210
+ if (data_min > data_max) return [0, 1] // no finite values
211
+ let [min, max] = [data_min, data_max]
212
+ const pad = min === max ? (min === 0 ? 1 : Math.abs(min * 0.1)) : (max - min) * 0.05
224
213
  if (range?.[0] == null) min -= pad
225
214
  if (range?.[1] == null) max += pad
226
- return scaleLinear().domain([range?.[0] ?? min, range?.[1] ?? max]).nice()
215
+ return scaleLinear()
216
+ .domain([range?.[0] ?? min, range?.[1] ?? max])
217
+ .nice()
227
218
  .domain() as Vec2
228
219
  }
229
220
 
230
- // Collect xyz values from points and surfaces
221
+ // Collect xyz extents from points and surfaces in one pass (no intermediate arrays)
231
222
  let surface_samples = $derived(surfaces.flatMap(sample_surface))
232
- let x_range = $derived(
233
- compute_range([
234
- ...all_points.map((point) => point.x),
235
- ...surface_samples.map((point) => point.x),
236
- ], x_axis.range),
237
- )
238
- let y_range = $derived(
239
- compute_range([
240
- ...all_points.map((point) => point.y),
241
- ...surface_samples.map((point) => point.y),
242
- ], y_axis.range),
243
- )
244
- let z_range = $derived(
245
- compute_range([
246
- ...all_points.map((point) => point.z),
247
- ...surface_samples.map((point) => point.z),
248
- ], z_axis.range),
249
- )
223
+ let data_extents = $derived.by(() => {
224
+ const extents = {
225
+ x: [Infinity, -Infinity] as Vec2,
226
+ y: [Infinity, -Infinity] as Vec2,
227
+ z: [Infinity, -Infinity] as Vec2,
228
+ }
229
+ for (const points of [all_points, surface_samples]) {
230
+ for (const pt of points) {
231
+ for (const axis of [`x`, `y`, `z`] as const) {
232
+ const val = pt[axis]
233
+ if (!isFinite(val)) continue
234
+ const extent = extents[axis]
235
+ if (val < extent[0]) extent[0] = val
236
+ if (val > extent[1]) extent[1] = val
237
+ }
238
+ }
239
+ }
240
+ return extents
241
+ })
242
+ let x_range = $derived(compute_range(data_extents.x, x_axis.range))
243
+ let y_range = $derived(compute_range(data_extents.y, y_axis.range))
244
+ let z_range = $derived(compute_range(data_extents.z, z_axis.range))
250
245
 
251
246
  const normalize_x = (value: number) => normalize_to_scene(value, x_range, scene_x)
252
247
  const normalize_y = (value: number) => normalize_to_scene(value, y_range, scene_y)
253
248
  const normalize_z = (value: number) => normalize_to_scene(value, z_range, scene_z)
254
249
 
255
- // Color/size scales
256
- let all_color_values = $derived(
257
- all_points.map((pt) => pt.color_value).filter((val): val is number => val != null),
258
- )
259
- let auto_color_range: [number, number] = $derived.by(() => {
260
- if (all_color_values.length === 0) return [0, 1]
261
- let min = all_color_values[0]
262
- let max = all_color_values[0]
263
- for (const val of all_color_values) {
264
- if (val < min) min = val
265
- else if (val > max) max = val
266
- }
267
- return [min, max]
268
- })
250
+ // Size scale (the color scale is computed by the wrapper and passed as a prop)
269
251
  let all_size_values = $derived(
270
252
  all_points.map((pt) => pt.size_value).filter((val): val is number => val != null),
271
253
  )
272
- let color_scale_fn = $derived(create_color_scale(color_scale, auto_color_range))
273
254
  let size_scale_fn = $derived(create_size_scale(size_scale, all_size_values))
274
255
 
275
256
  // Process points with normalized positions
276
257
  // Swap Y/Z for Three.js: user Z → Three.js Y (vertical), user Y → Three.js Z (depth)
277
258
  let processed_points = $derived(
278
- all_points.map((pt): InternalPoint3D<Metadata> => ({
279
- ...pt,
280
- x: normalize_x(pt.x), // user X → Three.js X
281
- y: normalize_z(pt.z), // user Z → Three.js Y (vertical)
282
- z: normalize_y(pt.y), // user Y → Three.js Z (depth)
283
- })),
259
+ all_points.map(
260
+ (pt): InternalPoint3D<Metadata> => ({
261
+ ...pt,
262
+ x: normalize_x(pt.x), // user X → Three.js X
263
+ y: normalize_z(pt.z), // user Z → Three.js Y (vertical)
264
+ z: normalize_y(pt.y), // user Y → Three.js Z (depth)
265
+ }),
266
+ ),
284
267
  )
285
268
 
286
269
  // Group points by radius, with per-instance colors
@@ -295,12 +278,14 @@
295
278
  for (const pt of processed_points) {
296
279
  const srs = series[pt.series_idx]
297
280
  if (!(series_visibility[pt.series_idx] ?? srs?.visible ?? true)) continue
298
- const color = pt.color_value != null
299
- ? color_scale_fn(pt.color_value)
300
- : pt.point_style?.fill ?? get_series_color(pt.series_idx)
301
- const radius = pt.size_value != null
302
- ? size_scale_fn(pt.size_value)
303
- : (pt.point_style?.radius ?? styles.point?.size ?? 2) * 0.05
281
+ const color =
282
+ pt.color_value != null
283
+ ? color_scale_fn(pt.color_value)
284
+ : (pt.point_style?.fill ?? get_series_color(pt.series_idx))
285
+ const radius =
286
+ pt.size_value != null
287
+ ? size_scale_fn(pt.size_value)
288
+ : (pt.point_style?.radius ?? styles.point?.size ?? 2) * 0.05
304
289
  const key = radius.toFixed(4)
305
290
  ;(groups[key] ??= { radius, points: [], colors: [] }).points.push(pt)
306
291
  groups[key].colors.push(color)
@@ -320,94 +305,113 @@
320
305
  let projection_configs = $derived(
321
306
  ([`xy`, `xz`, `yz`] as const)
322
307
  .filter((key) => display.projections?.[key])
323
- .map((key): ProjectionConfig => ({
324
- key,
325
- get_pos: key === `xy`
326
- ? (pt) => [pt.x, pos.y, pt.z]
327
- : key === `xz`
328
- ? (pt) => [pt.x, pt.y, pos.z]
329
- : (pt) => [pos.x, pt.y, pt.z],
330
- })),
308
+ .map(
309
+ (key): ProjectionConfig => ({
310
+ key,
311
+ get_pos:
312
+ key === `xy`
313
+ ? (pt) => [pt.x, pos.y, pt.z]
314
+ : key === `xz`
315
+ ? (pt) => [pt.x, pt.y, pos.z]
316
+ : (pt) => [pos.x, pt.y, pt.z],
317
+ }),
318
+ ),
331
319
  )
332
320
 
333
321
  // Series line data for connecting points
334
- type SeriesLineData = {
322
+ type SeriesLineInput = {
335
323
  series_idx: number
324
+ positions: number[]
336
325
  color: string
337
326
  width: number
338
327
  dashed: boolean
328
+ }
329
+ type SeriesLineData = SeriesLineInput & {
339
330
  line2: Line2
340
331
  geometry: LineGeometry
341
332
  material: LineMaterial
342
333
  }
343
334
 
344
- // Track previous lines for cleanup
345
- let series_lines: SeriesLineData[] = $state([])
346
-
347
- $effect(() => {
348
- // Dispose old lines before creating new ones
349
- for (const line_data of untrack(() => series_lines)) {
350
- line_data.geometry.dispose()
351
- line_data.material.dispose()
352
- }
353
-
354
- const lines: SeriesLineData[] = []
335
+ // Per-series fat-line inputs (ordered positions + resolved stroke style) as a derived so
336
+ // the effect below can diff against previous lines and only rebuild what changed
337
+ let line_inputs = $derived.by((): SeriesLineInput[] => {
338
+ const eligible: SeriesLineInput[] = []
339
+ const positions_by_series = new Map<number, number[]>()
355
340
  for (let series_idx = 0; series_idx < series.length; series_idx++) {
356
341
  const srs = series[series_idx]
357
- if (!srs?.line_style) continue
342
+ const line_style = srs?.line_style
343
+ if (!line_style) continue
358
344
  if (!(series_visibility[series_idx] ?? srs.visible ?? true)) continue
359
-
360
- // Get points for this series in order
361
- const series_points = processed_points
362
- .filter((pt) => pt.series_idx === series_idx)
363
- .sort((a, b) => a.point_idx - b.point_idx)
364
-
365
- if (series_points.length < 2) continue
366
-
367
- // Create fat line geometry (LineGeometry for Line2)
368
345
  const positions: number[] = []
369
- for (const pt of series_points) {
370
- positions.push(pt.x, pt.y, pt.z)
371
- }
372
- const geometry = new LineGeometry()
373
- geometry.setPositions(positions)
374
-
375
- // Determine line style
376
- const line_style = srs.line_style
377
- const color = line_style.stroke ??
378
- (Array.isArray(srs.point_style)
379
- ? srs.point_style[0]?.fill
380
- : srs.point_style?.fill) ??
346
+ positions_by_series.set(series_idx, positions)
347
+ const color =
348
+ line_style.stroke ??
349
+ (Array.isArray(srs.point_style) ? srs.point_style[0]?.fill : srs.point_style?.fill) ??
381
350
  get_series_color(series_idx)
382
- const line_width = line_style.stroke_width ?? 2
383
- const dashed = Boolean(line_style.line_dash)
384
-
385
- // Create LineMaterial for fat lines (linewidth is in pixels when resolution is set)
386
- // Use placeholder resolution; the separate resolution effect updates it
387
- const material = new LineMaterial({
388
- color: new THREE.Color(color).getHex(),
389
- linewidth: line_width, // Width in pixels
390
- dashed,
391
- dashScale: dashed ? 2 : 1,
392
- dashSize: 0.1,
393
- gapSize: 0.05,
394
- resolution: new THREE.Vector2(1, 1),
395
- })
396
-
397
- const line2 = new Line2(geometry, material)
398
- line2.computeLineDistances()
399
-
400
- lines.push({
351
+ eligible.push({
401
352
  series_idx,
353
+ positions,
402
354
  color,
403
- width: line_width,
404
- dashed,
405
- line2,
406
- geometry,
407
- material,
355
+ width: line_style.stroke_width ?? 2,
356
+ dashed: Boolean(line_style.line_dash),
408
357
  })
409
358
  }
410
- series_lines = lines
359
+ // processed_points are emitted in (series_idx, point_idx) order, so one ordered pass replaces the old per-series filter + sort
360
+ for (const pt of processed_points) {
361
+ positions_by_series.get(pt.series_idx)?.push(pt.x, pt.y, pt.z)
362
+ }
363
+ return eligible.filter((input) => input.positions.length >= 6) // >= 2 points
364
+ })
365
+
366
+ const same_line_input = (prev: SeriesLineData, next: SeriesLineInput): boolean =>
367
+ prev.color === next.color &&
368
+ prev.width === next.width &&
369
+ prev.dashed === next.dashed &&
370
+ prev.positions.length === next.positions.length &&
371
+ prev.positions.every((coord, idx) => coord === next.positions[idx])
372
+
373
+ // Track previous lines for reuse/cleanup
374
+ let series_lines: SeriesLineData[] = $state([])
375
+
376
+ $effect(() => {
377
+ const inputs = line_inputs
378
+ untrack(() => {
379
+ const prev_by_idx = new Map(series_lines.map((line) => [line.series_idx, line]))
380
+ const next_lines = inputs.map((input): SeriesLineData => {
381
+ const prev = prev_by_idx.get(input.series_idx)
382
+ if (prev && same_line_input(prev, input)) {
383
+ prev_by_idx.delete(input.series_idx) // reused - don't dispose below
384
+ return prev
385
+ }
386
+ // Create fat line geometry (LineGeometry for Line2)
387
+ const geometry = new LineGeometry()
388
+ geometry.setPositions(input.positions)
389
+ // Create LineMaterial for fat lines (linewidth is in pixels when resolution
390
+ // is set). Use placeholder resolution; the separate resolution effect updates it
391
+ const material = new LineMaterial({
392
+ color: new THREE.Color(input.color).getHex(),
393
+ linewidth: input.width, // Width in pixels
394
+ dashed: input.dashed,
395
+ dashScale: input.dashed ? 2 : 1,
396
+ dashSize: 0.1,
397
+ gapSize: 0.05,
398
+ resolution: new THREE.Vector2(1, 1),
399
+ })
400
+ const line2 = new Line2(geometry, material)
401
+ line2.computeLineDistances()
402
+ return { ...input, line2, geometry, material }
403
+ })
404
+ // Dispose lines that were replaced or removed
405
+ for (const stale of prev_by_idx.values()) {
406
+ stale.geometry.dispose()
407
+ stale.material.dispose()
408
+ }
409
+ // Skip reassignment when every line was reused to avoid invalidating consumers
410
+ const unchanged =
411
+ next_lines.length === series_lines.length &&
412
+ next_lines.every((line, idx) => line === series_lines[idx])
413
+ if (!unchanged) series_lines = next_lines
414
+ })
411
415
  })
412
416
 
413
417
  // Update LineMaterial resolution when canvas size changes
@@ -433,10 +437,7 @@
433
437
  })
434
438
 
435
439
  // Generate axis ticks using D3's smart tick generation
436
- function gen_ticks(
437
- range: [number, number],
438
- ticks?: AxisConfig3D[`ticks`],
439
- ): number[] {
440
+ function gen_ticks(range: Vec2, ticks?: AxisConfig3D[`ticks`]): number[] {
440
441
  if (Array.isArray(ticks)) return ticks
441
442
  const [min, max] = range
442
443
  if (!isFinite(min) || !isFinite(max) || min === max) return [min]
@@ -501,8 +502,8 @@
501
502
  gizmo === false
502
503
  ? null
503
504
  : gizmo === true
504
- ? { background: { enabled: false }, offset: { left: 5, bottom: 5 } }
505
- : gizmo,
505
+ ? { background: { enabled: false }, offset: { left: 5, bottom: 5 } }
506
+ : gizmo,
506
507
  )
507
508
 
508
509
  // Orbit controls - snappy with minimal inertia
@@ -557,19 +558,25 @@
557
558
  ticks: x_ticks,
558
559
  range: x_range,
559
560
  get_tick_pos: (val: number): Vec3 => [normalize_x(val), pos.y, pos.z],
560
- get_tick_end: (
561
- val: number,
562
- ): Vec3 => [normalize_x(val), pos.y + sign_y * tick_length, pos.z],
561
+ get_tick_end: (val: number): Vec3 => [
562
+ normalize_x(val),
563
+ pos.y + sign_y * tick_length,
564
+ pos.z,
565
+ ],
563
566
  get_grid_lines: (val: number): [Vec3, Vec3][] => {
564
567
  const px = normalize_x(val)
565
568
  return [
566
- [[px, -half_z, pos.z], [px, half_z, pos.z]],
567
- [[px, pos.y, -half_y], [px, pos.y, half_y]],
569
+ [
570
+ [px, -half_z, pos.z],
571
+ [px, half_z, pos.z],
572
+ ],
573
+ [
574
+ [px, pos.y, -half_y],
575
+ [px, pos.y, half_y],
576
+ ],
568
577
  ]
569
578
  },
570
- tick_label_pos: (
571
- val: number,
572
- ): Vec3 => [normalize_x(val), pos.y + sign_y * 0.4, pos.z],
579
+ tick_label_pos: (val: number): Vec3 => [normalize_x(val), pos.y + sign_y * 0.4, pos.z],
573
580
  axis_label_pos: [0, pos.y + sign_y * 0.9, pos.z] as Vec3,
574
581
  },
575
582
  {
@@ -579,19 +586,29 @@
579
586
  ticks: y_ticks,
580
587
  range: y_range,
581
588
  get_tick_pos: (val: number): Vec3 => [pos.x, pos.y, normalize_y(val)],
582
- get_tick_end: (
583
- val: number,
584
- ): Vec3 => [pos.x, pos.y + sign_y * tick_length, normalize_y(val)],
589
+ get_tick_end: (val: number): Vec3 => [
590
+ pos.x,
591
+ pos.y + sign_y * tick_length,
592
+ normalize_y(val),
593
+ ],
585
594
  get_grid_lines: (val: number): [Vec3, Vec3][] => {
586
595
  const py = normalize_y(val)
587
596
  return [
588
- [[-half_x, pos.y, py], [half_x, pos.y, py]],
589
- [[pos.x, -half_z, py], [pos.x, half_z, py]],
597
+ [
598
+ [-half_x, pos.y, py],
599
+ [half_x, pos.y, py],
600
+ ],
601
+ [
602
+ [pos.x, -half_z, py],
603
+ [pos.x, half_z, py],
604
+ ],
590
605
  ]
591
606
  },
592
- tick_label_pos: (
593
- val: number,
594
- ): Vec3 => [pos.x + sign_x * 0.5, pos.y + sign_y * 0.4, normalize_y(val)],
607
+ tick_label_pos: (val: number): Vec3 => [
608
+ pos.x + sign_x * 0.5,
609
+ pos.y + sign_y * 0.4,
610
+ normalize_y(val),
611
+ ],
595
612
  axis_label_pos: [
596
613
  pos.x,
597
614
  pos.y + sign_y * 0.9,
@@ -605,19 +622,25 @@
605
622
  ticks: z_ticks,
606
623
  range: z_range,
607
624
  get_tick_pos: (val: number): Vec3 => [pos.x, normalize_z(val), pos.z],
608
- get_tick_end: (
609
- val: number,
610
- ): Vec3 => [pos.x + sign_x * tick_length, normalize_z(val), pos.z],
625
+ get_tick_end: (val: number): Vec3 => [
626
+ pos.x + sign_x * tick_length,
627
+ normalize_z(val),
628
+ pos.z,
629
+ ],
611
630
  get_grid_lines: (val: number): [Vec3, Vec3][] => {
612
631
  const pz = normalize_z(val)
613
632
  return [
614
- [[-half_x, pz, pos.z], [half_x, pz, pos.z]],
615
- [[pos.x, pz, -half_y], [pos.x, pz, half_y]],
633
+ [
634
+ [-half_x, pz, pos.z],
635
+ [half_x, pz, pos.z],
636
+ ],
637
+ [
638
+ [pos.x, pz, -half_y],
639
+ [pos.x, pz, half_y],
640
+ ],
616
641
  ]
617
642
  },
618
- tick_label_pos: (
619
- val: number,
620
- ): Vec3 => [pos.x + sign_x * 0.5, normalize_z(val), pos.z],
643
+ tick_label_pos: (val: number): Vec3 => [pos.x + sign_x * 0.5, normalize_z(val), pos.z],
621
644
  axis_label_pos: [pos.x + sign_x, 0, pos.z] as Vec3,
622
645
  },
623
646
  ])
@@ -647,10 +670,10 @@
647
670
  for (const { key, ticks, get_tick_pos, get_tick_end, get_grid_lines } of config) {
648
671
  axis_geom_data[key] = {
649
672
  tick_geoms: ticks.map((val) =>
650
- create_line_geometry(get_tick_pos(val), get_tick_end(val))
673
+ create_line_geometry(get_tick_pos(val), get_tick_end(val)),
651
674
  ),
652
675
  grid_geoms: ticks.map((val) =>
653
- get_grid_lines(val).map(([start, end]) => create_line_geometry(start, end))
676
+ get_grid_lines(val).map(([start, end]) => create_line_geometry(start, end)),
654
677
  ),
655
678
  }
656
679
  }
@@ -722,11 +745,7 @@
722
745
  </T.Line>
723
746
  {/if}
724
747
  {#if display.show_grid !== false}
725
- {#each axis_geom_data[key].grid_geoms[tick_idx] ?? [] as
726
- grid_geom,
727
- grid_idx
728
- (grid_idx)
729
- }
748
+ {#each axis_geom_data[key].grid_geoms[tick_idx] ?? [] as grid_geom, grid_idx (grid_idx)}
730
749
  <T.Line>
731
750
  <T is={grid_geom} />
732
751
  <T.LineBasicMaterial color="#888" opacity={0.4} transparent />
@@ -745,27 +764,12 @@
745
764
  {/if}
746
765
 
747
766
  <!-- Surfaces -->
748
- {#each surfaces.filter((srf) => srf.visible !== false) as
749
- surface
750
- (surface.id ?? surfaces.indexOf(surface))
751
- }
752
- <Surface3D
753
- config={surface}
754
- {x_range}
755
- {y_range}
756
- {z_range}
757
- {scene_x}
758
- {scene_y}
759
- {scene_z}
760
- />
767
+ {#each surfaces.filter((srf) => srf.visible !== false) as surface (surface.id ?? surfaces.indexOf(surface))}
768
+ <Surface3D config={surface} {x_range} {y_range} {z_range} {scene_x} {scene_y} {scene_z} />
761
769
  {/each}
762
770
 
763
771
  <!-- Reference Planes -->
764
- {#each (ref_planes ?? []).filter((plane) => plane.visible !== false) as
765
- ref_plane,
766
- plane_idx
767
- (ref_plane.id ?? plane_idx)
768
- }
772
+ {#each (ref_planes ?? []).filter((plane) => plane.visible !== false) as ref_plane, plane_idx (ref_plane.id ?? plane_idx)}
769
773
  <ReferencePlane
770
774
  {ref_plane}
771
775
  scene_size={[scene_x, scene_y, scene_z]}
@@ -774,11 +778,7 @@
774
778
  {/each}
775
779
 
776
780
  <!-- Reference Lines -->
777
- {#each (ref_lines ?? []).filter((line) => line.visible !== false) as
778
- ref_line,
779
- line_idx
780
- (ref_line.id ?? line_idx)
781
- }
781
+ {#each (ref_lines ?? []).filter((line) => line.visible !== false) as ref_line, line_idx (ref_line.id ?? line_idx)}
782
782
  <ReferenceLine3D
783
783
  {ref_line}
784
784
  scene_size={[scene_x, scene_y, scene_z]}
@@ -841,9 +841,7 @@
841
841
  {#if hovered_point}
842
842
  {@const hp = hovered_point}
843
843
  {@const group = radius_groups.find((grp) =>
844
- grp.points.some((pt) =>
845
- pt.series_idx === hp.series_idx && pt.point_idx === hp.point_idx
846
- )
844
+ grp.points.some((pt) => pt.series_idx === hp.series_idx && pt.point_idx === hp.point_idx),
847
845
  )}
848
846
  <T.Mesh position={[hp.x, hp.y, hp.z]} scale={(group?.radius ?? 0.1) * 1.5}>
849
847
  <T.SphereGeometry args={[1, 16, 16]} />