matterviz 0.4.1 → 0.4.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 (499) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +48 -60
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/api/optimade.js +10 -7
  6. package/dist/app.css +68 -0
  7. package/dist/brillouin/BrillouinZone.svelte +90 -91
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
  9. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
  11. package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
  12. package/dist/brillouin/BrillouinZoneScene.svelte +46 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  14. package/dist/brillouin/compute.js +10 -16
  15. package/dist/brillouin/geometry.js +2 -2
  16. package/dist/chempot-diagram/ChemPotDiagram.svelte +48 -50
  17. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +61 -169
  18. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
  19. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +559 -755
  20. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
  21. package/dist/chempot-diagram/async-compute.svelte.js +13 -14
  22. package/dist/chempot-diagram/color.d.ts +21 -1
  23. package/dist/chempot-diagram/color.js +70 -1
  24. package/dist/chempot-diagram/compute.d.ts +7 -0
  25. package/dist/chempot-diagram/compute.js +85 -26
  26. package/dist/chempot-diagram/controls-state.svelte.js +1 -1
  27. package/dist/chempot-diagram/export.js +1 -6
  28. package/dist/chempot-diagram/temperature.js +9 -10
  29. package/dist/colors/index.d.ts +0 -4
  30. package/dist/colors/index.js +19 -20
  31. package/dist/composition/BarChart.svelte +30 -26
  32. package/dist/composition/BubbleChart.svelte +17 -17
  33. package/dist/composition/Composition.svelte +10 -19
  34. package/dist/composition/Formula.svelte +20 -27
  35. package/dist/composition/FormulaFilter.svelte +115 -184
  36. package/dist/composition/PieChart.svelte +55 -41
  37. package/dist/composition/format.js +7 -9
  38. package/dist/composition/index.d.ts +2 -0
  39. package/dist/composition/index.js +14 -0
  40. package/dist/composition/parse.d.ts +2 -2
  41. package/dist/composition/parse.js +61 -115
  42. package/dist/constants.d.ts +0 -1
  43. package/dist/constants.js +17 -26
  44. package/dist/convex-hull/ConvexHull.svelte +12 -15
  45. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  46. package/dist/convex-hull/ConvexHull2D.svelte +93 -94
  47. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  48. package/dist/convex-hull/ConvexHull3D.svelte +127 -186
  49. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  50. package/dist/convex-hull/ConvexHull4D.svelte +131 -180
  51. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  52. package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
  53. package/dist/convex-hull/ConvexHullControls.svelte +46 -48
  54. package/dist/convex-hull/ConvexHullStats.svelte +193 -195
  55. package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
  56. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  57. package/dist/convex-hull/StructurePopup.svelte +18 -22
  58. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  59. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  60. package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
  61. package/dist/convex-hull/gas-thermodynamics.js +21 -53
  62. package/dist/convex-hull/helpers.d.ts +8 -10
  63. package/dist/convex-hull/helpers.js +37 -43
  64. package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
  65. package/dist/convex-hull/thermodynamics.js +37 -44
  66. package/dist/coordination/CoordinationBarPlot.svelte +49 -53
  67. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  68. package/dist/coordination/calc-coordination.d.ts +1 -1
  69. package/dist/coordination/calc-coordination.js +28 -25
  70. package/dist/element/BohrAtom.svelte +5 -9
  71. package/dist/element/ElementHeading.svelte +4 -1
  72. package/dist/element/ElementPhoto.svelte +11 -9
  73. package/dist/element/ElementStats.svelte +12 -10
  74. package/dist/element/ElementTile.svelte +44 -67
  75. package/dist/element/Nucleus.svelte +4 -2
  76. package/dist/element/data.d.ts +3 -2
  77. package/dist/element/data.js +5 -1
  78. package/dist/element/helpers.d.ts +4 -0
  79. package/dist/element/helpers.js +18 -0
  80. package/dist/element/index.d.ts +2 -5
  81. package/dist/element/index.js +4 -19
  82. package/dist/feedback/DragOverlay.svelte +5 -5
  83. package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
  84. package/dist/feedback/StatusMessage.svelte +7 -4
  85. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  86. package/dist/fermi-surface/FermiSurface.svelte +35 -44
  87. package/dist/fermi-surface/FermiSurface.svelte.d.ts +7 -13
  88. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  89. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  90. package/dist/fermi-surface/FermiSurfaceScene.svelte +64 -136
  91. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  92. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  93. package/dist/fermi-surface/compute.js +25 -58
  94. package/dist/fermi-surface/parse.js +54 -88
  95. package/dist/file-viewer/JsonBrowser.svelte +1043 -0
  96. package/dist/file-viewer/JsonBrowser.svelte.d.ts +9 -0
  97. package/dist/file-viewer/PlotPanel.svelte +350 -0
  98. package/dist/file-viewer/PlotPanel.svelte.d.ts +9 -0
  99. package/dist/file-viewer/TrajectoryWithDos.svelte +30 -0
  100. package/dist/file-viewer/TrajectoryWithDos.svelte.d.ts +10 -0
  101. package/dist/file-viewer/detect.d.ts +11 -0
  102. package/dist/file-viewer/detect.js +381 -0
  103. package/dist/file-viewer/eligibility.d.ts +4 -0
  104. package/dist/file-viewer/eligibility.js +53 -0
  105. package/dist/file-viewer/host-protocol.d.ts +50 -0
  106. package/dist/file-viewer/host-transfer.d.ts +25 -0
  107. package/dist/file-viewer/host-transfer.js +42 -0
  108. package/dist/file-viewer/index.d.ts +5 -0
  109. package/dist/file-viewer/index.js +5 -0
  110. package/dist/file-viewer/main.d.ts +44 -0
  111. package/dist/file-viewer/main.js +535 -0
  112. package/dist/file-viewer/parse.d.ts +9 -0
  113. package/dist/file-viewer/parse.js +170 -0
  114. package/dist/file-viewer/plot-utils.d.ts +24 -0
  115. package/dist/file-viewer/plot-utils.js +191 -0
  116. package/dist/file-viewer/types.d.ts +4 -0
  117. package/dist/file-viewer/types.js +5 -0
  118. package/dist/heatmap-matrix/HeatmapMatrix.svelte +153 -219
  119. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
  120. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
  121. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
  122. package/dist/heatmap-matrix/index.d.ts +5 -0
  123. package/dist/icons.d.ts +4 -0
  124. package/dist/icons.js +4 -0
  125. package/dist/index.d.ts +2 -2
  126. package/dist/index.js +1 -1
  127. package/dist/io/ExportPane.svelte +11 -7
  128. package/dist/io/decompress.d.ts +4 -1
  129. package/dist/io/decompress.js +24 -36
  130. package/dist/io/export.d.ts +11 -4
  131. package/dist/io/export.js +75 -19
  132. package/dist/io/fetch.d.ts +0 -3
  133. package/dist/io/fetch.js +0 -11
  134. package/dist/io/file-drop.js +60 -35
  135. package/dist/io/index.d.ts +0 -1
  136. package/dist/io/index.js +2 -9
  137. package/dist/io/is-binary.d.ts +9 -0
  138. package/dist/io/is-binary.js +45 -1
  139. package/dist/io/url-drop.d.ts +2 -0
  140. package/dist/io/url-drop.js +40 -40
  141. package/dist/isosurface/Isosurface.svelte +700 -215
  142. package/dist/isosurface/Isosurface.svelte.d.ts +7 -1
  143. package/dist/isosurface/IsosurfaceControls.svelte +590 -116
  144. package/dist/isosurface/IsosurfaceControls.svelte.d.ts +1 -1
  145. package/dist/isosurface/VolumeSlice.svelte +224 -0
  146. package/dist/isosurface/VolumeSlice.svelte.d.ts +28 -0
  147. package/dist/isosurface/coloring.d.ts +20 -0
  148. package/dist/isosurface/coloring.js +118 -0
  149. package/dist/isosurface/geometry-worker-types.d.ts +38 -0
  150. package/dist/isosurface/geometry.worker.d.ts +1 -0
  151. package/dist/isosurface/geometry.worker.js +59 -0
  152. package/dist/isosurface/grid.d.ts +10 -0
  153. package/dist/isosurface/grid.js +31 -0
  154. package/dist/isosurface/index.d.ts +4 -0
  155. package/dist/isosurface/index.js +4 -0
  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 +6 -6
  159. package/dist/isosurface/profile.d.ts +12 -0
  160. package/dist/isosurface/profile.js +19 -0
  161. package/dist/isosurface/sampling.d.ts +34 -0
  162. package/dist/isosurface/sampling.js +408 -0
  163. package/dist/isosurface/slice-rendering.d.ts +13 -0
  164. package/dist/isosurface/slice-rendering.js +79 -0
  165. package/dist/isosurface/slice.d.ts +22 -2
  166. package/dist/isosurface/slice.js +200 -116
  167. package/dist/isosurface/types.d.ts +24 -1
  168. package/dist/isosurface/types.js +120 -8
  169. package/dist/json-path.d.ts +4 -0
  170. package/dist/json-path.js +89 -0
  171. package/dist/labels.d.ts +6 -2
  172. package/dist/labels.js +44 -14
  173. package/dist/layout/FullscreenButton.svelte +2 -1
  174. package/dist/layout/FullscreenToggle.svelte +10 -4
  175. package/dist/layout/InfoCard.svelte +8 -21
  176. package/dist/layout/InfoTag.svelte +1 -3
  177. package/dist/layout/NumberRangeInput.svelte +46 -0
  178. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  179. package/dist/layout/PropertyFilter.svelte +2 -6
  180. package/dist/layout/SettingsSection.svelte +57 -62
  181. package/dist/layout/SettingsSection.svelte.d.ts +6 -7
  182. package/dist/layout/SubpageGrid.svelte +3 -1
  183. package/dist/layout/ViewerChrome.svelte +16 -11
  184. package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
  185. package/dist/layout/fullscreen.js +3 -5
  186. package/dist/layout/fullscreen.svelte.js +1 -2
  187. package/dist/layout/index.d.ts +1 -0
  188. package/dist/layout/index.js +1 -0
  189. package/dist/layout/json-tree/JsonNode.svelte +22 -59
  190. package/dist/layout/json-tree/JsonTree.svelte +101 -172
  191. package/dist/layout/json-tree/JsonValue.svelte +9 -32
  192. package/dist/layout/json-tree/utils.d.ts +0 -3
  193. package/dist/layout/json-tree/utils.js +50 -188
  194. package/dist/marching-cubes.d.ts +8 -1
  195. package/dist/marching-cubes.js +115 -48
  196. package/dist/math.d.ts +5 -2
  197. package/dist/math.js +48 -38
  198. package/dist/overlays/ContextMenu.svelte +19 -34
  199. package/dist/overlays/CopyButton.svelte +11 -5
  200. package/dist/overlays/DragControlTab.svelte +6 -1
  201. package/dist/overlays/DraggablePane.svelte +110 -74
  202. package/dist/overlays/DraggablePane.svelte.d.ts +2 -1
  203. package/dist/overlays/GlassChip.svelte +32 -0
  204. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  205. package/dist/overlays/InfoPaneCards.svelte +11 -23
  206. package/dist/overlays/index.d.ts +7 -0
  207. package/dist/overlays/index.js +26 -0
  208. package/dist/overlays/portal.d.ts +2 -0
  209. package/dist/overlays/portal.js +14 -0
  210. package/dist/periodic-table/PeriodicTable.svelte +113 -145
  211. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  212. package/dist/periodic-table/PeriodicTableControls.svelte +37 -115
  213. package/dist/periodic-table/TableInset.svelte +9 -4
  214. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +68 -105
  215. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  216. package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
  217. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  218. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
  219. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
  220. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  221. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  222. package/dist/phase-diagram/build-diagram.js +4 -9
  223. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  224. package/dist/phase-diagram/parse.js +15 -15
  225. package/dist/phase-diagram/svg-to-diagram.js +28 -27
  226. package/dist/phase-diagram/utils.js +2 -3
  227. package/dist/plot/bar/BarPlot.svelte +461 -426
  228. package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
  229. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  230. package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
  231. package/dist/plot/bar/SpacegroupBarPlot.svelte +46 -77
  232. package/dist/plot/bar/data.d.ts +5 -4
  233. package/dist/plot/bar/data.js +2 -1
  234. package/dist/plot/box/BoxPlot.svelte +322 -226
  235. package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
  236. package/dist/plot/box/Violin.svelte.d.ts +1 -0
  237. package/dist/plot/box/box-plot.js +1 -1
  238. package/dist/plot/core/auto-place.d.ts +1 -1
  239. package/dist/plot/core/auto-place.js +2 -2
  240. package/dist/plot/core/axis-utils.d.ts +12 -7
  241. package/dist/plot/core/axis-utils.js +48 -48
  242. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  243. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  244. package/dist/plot/core/components/ColorBar.svelte +101 -106
  245. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  246. package/dist/plot/core/components/FillArea.svelte +10 -17
  247. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  248. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  249. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  250. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  251. package/dist/plot/core/components/Line.svelte +18 -9
  252. package/dist/plot/core/components/Line.svelte.d.ts +2 -0
  253. package/dist/plot/core/components/PlotAxis.svelte +40 -17
  254. package/dist/plot/core/components/PlotControls.svelte +65 -41
  255. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  256. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  257. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  258. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  259. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  260. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  261. package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
  262. package/dist/plot/core/components/ReferencePlane.svelte +7 -8
  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 +27 -474
  271. package/dist/plot/core/data-transform.d.ts +1 -2
  272. package/dist/plot/core/data-transform.js +9 -15
  273. package/dist/plot/core/fill-utils.d.ts +3 -1
  274. package/dist/plot/core/fill-utils.js +28 -6
  275. package/dist/plot/core/index.d.ts +1 -0
  276. package/dist/plot/core/index.js +1 -0
  277. package/dist/plot/core/interactions.js +0 -2
  278. package/dist/plot/core/layout.d.ts +15 -6
  279. package/dist/plot/core/layout.js +57 -38
  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 +2 -4
  283. package/dist/plot/core/pan-zoom.svelte.js +34 -17
  284. package/dist/plot/core/placed-tween.svelte.d.ts +3 -0
  285. package/dist/plot/core/placed-tween.svelte.js +68 -21
  286. package/dist/plot/core/reference-line.js +1 -1
  287. package/dist/plot/core/scales.d.ts +23 -0
  288. package/dist/plot/core/scales.js +39 -13
  289. package/dist/plot/core/svg.js +0 -1
  290. package/dist/plot/core/types/fills.d.ts +101 -0
  291. package/dist/plot/core/types/fills.js +15 -0
  292. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  293. package/dist/plot/core/types/plot-3d.js +4 -0
  294. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  295. package/dist/plot/core/types/reference-lines.js +9 -0
  296. package/dist/plot/core/types.d.ts +29 -324
  297. package/dist/plot/core/types.js +23 -20
  298. package/dist/plot/core/utils/hierarchy-chart.d.ts +52 -0
  299. package/dist/plot/core/utils/hierarchy-chart.js +191 -0
  300. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  301. package/dist/plot/core/utils/hierarchy-labels.js +100 -0
  302. package/dist/plot/core/utils/label-placement.js +2 -2
  303. package/dist/plot/histogram/Histogram.svelte +314 -340
  304. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  305. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  306. package/dist/plot/histogram/histogram.d.ts +31 -0
  307. package/dist/plot/histogram/histogram.js +70 -0
  308. package/dist/plot/histogram/index.d.ts +1 -0
  309. package/dist/plot/histogram/index.js +1 -0
  310. package/dist/plot/index.d.ts +1 -0
  311. package/dist/plot/index.js +1 -0
  312. package/dist/plot/sankey/Sankey.svelte +78 -69
  313. package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
  314. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  315. package/dist/plot/sankey/sankey.js +13 -9
  316. package/dist/plot/scatter/BinnedScatterPlot.svelte +311 -141
  317. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
  318. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  319. package/dist/plot/scatter/ScatterPlot.svelte +517 -410
  320. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
  321. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  322. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  323. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  324. package/dist/plot/scatter/adaptive-density.d.ts +1 -1
  325. package/dist/plot/scatter/adaptive-density.js +36 -20
  326. package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
  327. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  328. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  329. package/dist/plot/scatter/scatter-data.js +8 -7
  330. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
  331. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
  332. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
  333. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
  334. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
  335. package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
  336. package/dist/plot/sunburst/Sunburst.svelte +269 -347
  337. package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
  338. package/dist/plot/sunburst/index.d.ts +1 -1
  339. package/dist/plot/sunburst/index.js +2 -1
  340. package/dist/plot/sunburst/render.d.ts +2 -2
  341. package/dist/plot/sunburst/render.js +47 -22
  342. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  343. package/dist/plot/sunburst/sunburst.js +10 -3
  344. package/dist/plot/treemap/Treemap.svelte +1022 -0
  345. package/dist/plot/treemap/Treemap.svelte.d.ts +90 -0
  346. package/dist/plot/treemap/index.d.ts +4 -0
  347. package/dist/plot/treemap/index.js +4 -0
  348. package/dist/plot/treemap/labels.d.ts +38 -0
  349. package/dist/plot/treemap/labels.js +80 -0
  350. package/dist/plot/treemap/treemap.d.ts +28 -0
  351. package/dist/plot/treemap/treemap.js +102 -0
  352. package/dist/rdf/RdfPlot.svelte +37 -59
  353. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  354. package/dist/rdf/calc-rdf.js +63 -52
  355. package/dist/rdf/index.d.ts +0 -1
  356. package/dist/sanitize.js +85 -27
  357. package/dist/scene/SceneCamera.svelte +1 -1
  358. package/dist/scene/SceneCamera.svelte.d.ts +1 -1
  359. package/dist/scene/bind-renderer.svelte.js +14 -6
  360. package/dist/scene/index.d.ts +1 -2
  361. package/dist/scene/index.js +1 -1
  362. package/dist/scene/{props.js → props.svelte.js} +15 -1
  363. package/dist/settings.d.ts +19 -9
  364. package/dist/settings.js +229 -525
  365. package/dist/spectral/Bands.svelte +207 -221
  366. package/dist/spectral/BandsAndDos.svelte +11 -9
  367. package/dist/spectral/BrillouinBandsDos.svelte +19 -42
  368. package/dist/spectral/Dos.svelte +92 -93
  369. package/dist/spectral/helpers.d.ts +3 -3
  370. package/dist/spectral/helpers.js +65 -140
  371. package/dist/state.svelte.js +5 -18
  372. package/dist/structure/Arrow.svelte +5 -18
  373. package/dist/structure/ArrowInstances.svelte +160 -0
  374. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  375. package/dist/structure/AtomLegend.svelte +120 -85
  376. package/dist/structure/AtomLegend.svelte.d.ts +2 -3
  377. package/dist/structure/Bond.svelte +31 -23
  378. package/dist/structure/CanvasTooltip.svelte +15 -3
  379. package/dist/structure/CellSelect.svelte +45 -35
  380. package/dist/structure/Cylinder.svelte +24 -40
  381. package/dist/structure/InstancedAtoms.svelte +114 -0
  382. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  383. package/dist/structure/Lattice.svelte +85 -149
  384. package/dist/structure/SiteLabels.svelte +122 -0
  385. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  386. package/dist/structure/Structure.svelte +636 -504
  387. package/dist/structure/Structure.svelte.d.ts +4 -2
  388. package/dist/structure/StructureCarousel.svelte +637 -0
  389. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  390. package/dist/structure/StructureControls.svelte +165 -425
  391. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  392. package/dist/structure/StructureExportPane.svelte +17 -21
  393. package/dist/structure/StructureInfoPane.svelte +128 -133
  394. package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
  395. package/dist/structure/StructureScene.svelte +535 -578
  396. package/dist/structure/StructureScene.svelte.d.ts +6 -2
  397. package/dist/structure/StructureViewport.svelte +451 -0
  398. package/dist/structure/StructureViewport.svelte.d.ts +65 -0
  399. package/dist/structure/atom-label-placement.d.ts +16 -12
  400. package/dist/structure/atom-label-placement.js +70 -37
  401. package/dist/structure/atom-properties.d.ts +2 -0
  402. package/dist/structure/atom-properties.js +105 -38
  403. package/dist/structure/bond-order-perception.js +3 -8
  404. package/dist/structure/bonding.d.ts +9 -3
  405. package/dist/structure/bonding.js +95 -46
  406. package/dist/structure/edit-history.d.ts +6 -0
  407. package/dist/structure/edit-history.js +27 -0
  408. package/dist/structure/export.d.ts +1 -0
  409. package/dist/structure/export.js +89 -105
  410. package/dist/structure/format-detect.d.ts +1 -0
  411. package/dist/structure/format-detect.js +20 -0
  412. package/dist/structure/geometry.d.ts +9 -0
  413. package/dist/structure/geometry.js +27 -0
  414. package/dist/structure/index.d.ts +16 -1
  415. package/dist/structure/index.js +15 -10
  416. package/dist/structure/measure.d.ts +1 -1
  417. package/dist/structure/measure.js +6 -12
  418. package/dist/structure/parse.d.ts +2 -1
  419. package/dist/structure/parse.js +272 -313
  420. package/dist/structure/partial-occupancy.js +10 -5
  421. package/dist/structure/pbc.js +85 -107
  422. package/dist/structure/polyhedra.d.ts +0 -1
  423. package/dist/structure/polyhedra.js +7 -21
  424. package/dist/structure/prop-groups.d.ts +85 -0
  425. package/dist/structure/prop-groups.js +18 -0
  426. package/dist/structure/supercell.d.ts +1 -2
  427. package/dist/structure/supercell.js +7 -13
  428. package/dist/symmetry/SymmetryElements.svelte +11 -15
  429. package/dist/symmetry/SymmetryStats.svelte +55 -71
  430. package/dist/symmetry/WyckoffTable.svelte +10 -28
  431. package/dist/symmetry/cell-transform.js +6 -14
  432. package/dist/symmetry/index.d.ts +1 -0
  433. package/dist/symmetry/index.js +13 -10
  434. package/dist/symmetry/spacegroups.js +3 -2
  435. package/dist/table/HeatmapTable.svelte +1142 -447
  436. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  437. package/dist/table/ToggleMenu.svelte +168 -53
  438. package/dist/table/ToggleMenu.svelte.d.ts +1 -1
  439. package/dist/table/index.d.ts +21 -6
  440. package/dist/table/index.js +34 -21
  441. package/dist/theme/ThemeControl.svelte +16 -8
  442. package/dist/theme/embedded.d.ts +18 -0
  443. package/dist/theme/embedded.js +206 -0
  444. package/dist/theme/index.d.ts +5 -5
  445. package/dist/theme/index.js +5 -12
  446. package/dist/theme/themes.mjs +44 -66
  447. package/dist/tooltip/KCoords.svelte +4 -1
  448. package/dist/tooltip/TooltipContent.svelte +3 -6
  449. package/dist/tooltip/TooltipContent.svelte.d.ts +1 -1
  450. package/dist/tooltip/index.d.ts +8 -1
  451. package/dist/trajectory/Trajectory.svelte +613 -386
  452. package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
  453. package/dist/trajectory/TrajectoryError.svelte +12 -74
  454. package/dist/trajectory/TrajectoryExportPane.svelte +14 -32
  455. package/dist/trajectory/TrajectoryInfoPane.svelte +127 -164
  456. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +2 -1
  457. package/dist/trajectory/extract.js +61 -49
  458. package/dist/trajectory/format-detect.d.ts +2 -0
  459. package/dist/trajectory/format-detect.js +17 -13
  460. package/dist/trajectory/frame-reader.d.ts +2 -0
  461. package/dist/trajectory/frame-reader.js +35 -32
  462. package/dist/trajectory/helpers.d.ts +2 -0
  463. package/dist/trajectory/helpers.js +34 -56
  464. package/dist/trajectory/index.d.ts +1 -0
  465. package/dist/trajectory/index.js +5 -8
  466. package/dist/trajectory/parse/ase.js +1 -1
  467. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  468. package/dist/trajectory/parse/h5-utils.js +109 -0
  469. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  470. package/dist/trajectory/parse/hdf5.js +116 -106
  471. package/dist/trajectory/parse/index.d.ts +6 -6
  472. package/dist/trajectory/parse/index.js +25 -33
  473. package/dist/trajectory/parse/lammps.js +8 -12
  474. package/dist/trajectory/parse/vasp.js +10 -7
  475. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  476. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  477. package/dist/trajectory/parse/vaspout-h5.d.ts +4 -0
  478. package/dist/trajectory/parse/vaspout-h5.js +281 -0
  479. package/dist/trajectory/parse/xyz.js +59 -9
  480. package/dist/trajectory/plotting.d.ts +8 -9
  481. package/dist/trajectory/plotting.js +113 -64
  482. package/dist/utils.d.ts +3 -0
  483. package/dist/utils.js +7 -0
  484. package/dist/xrd/XrdPlot.svelte +79 -118
  485. package/dist/xrd/broadening.js +2 -1
  486. package/dist/xrd/calc-xrd.js +24 -62
  487. package/dist/xrd/parse.d.ts +0 -1
  488. package/dist/xrd/parse.js +69 -95
  489. package/package.json +94 -34
  490. package/readme.md +6 -5
  491. package/dist/api/mp.d.ts +0 -6
  492. package/dist/api/mp.js +0 -22
  493. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
  494. package/dist/scene/types.d.ts +0 -26
  495. package/dist/tooltip/types.d.ts +0 -8
  496. package/dist/trajectory/constants.d.ts +0 -6
  497. package/dist/trajectory/constants.js +0 -11
  498. /package/dist/{scene/types.js → file-viewer/host-protocol.js} +0 -0
  499. /package/dist/{tooltip/types.js → isosurface/geometry-worker-types.js} +0 -0
@@ -13,10 +13,30 @@
13
13
  import { create_pulse_animation } from '../../effects.svelte'
14
14
  import ColorBar from '../core/components/ColorBar.svelte'
15
15
  import PlotAxis from '../core/components/PlotAxis.svelte'
16
+ import PlotMarginals from '../core/components/PlotMarginals.svelte'
16
17
  import PlotTooltip from '../core/components/PlotTooltip.svelte'
17
18
  import ZoomRect from '../core/components/ZoomRect.svelte'
18
- import { compute_element_placement, filter_padding } from '../core/layout'
19
+ import { sorted_range } from '../core/interactions'
20
+ import { create_placed_tween } from '../core/placed-tween.svelte'
21
+ import {
22
+ AXIS_TITLE_OFFSET,
23
+ compute_element_placement,
24
+ DEFAULT_PLOT_PADDING,
25
+ filter_padding,
26
+ full_footprint_or,
27
+ LABEL_GAP_DEFAULT,
28
+ point_in_rect,
29
+ } from '../core/layout'
19
30
  import type { Sides } from '../core/layout'
31
+ import { get_series_color } from '../core/data-transform'
32
+ import type { MarginalSeriesInput, MarginalsProp } from '../core/marginals'
33
+ import {
34
+ add_sides,
35
+ marginal_axis,
36
+ marginal_axis_presence,
37
+ normalize_marginals,
38
+ reserve_marginal_pad,
39
+ } from '../core/marginals'
20
40
  import {
21
41
  build_pick_index,
22
42
  bin_points,
@@ -29,9 +49,29 @@
29
49
  series_extents,
30
50
  should_render_points,
31
51
  } from './adaptive-density'
32
- import type { DensityBin, DenseInternalPoint, DensePointSeries } from './adaptive-density'
33
- import { create_color_scale, create_scale, create_size_scale, generate_ticks } from '../core/scales'
34
- import type { AxisConfig, DataSeries, InternalPoint, ScatterHandlerProps } from '../core/types'
52
+ import type {
53
+ DensityBin,
54
+ DenseInternalPoint,
55
+ DensePointSeries,
56
+ } from './adaptive-density'
57
+ import {
58
+ create_color_scale,
59
+ create_scale,
60
+ create_size_scale,
61
+ generate_ticks,
62
+ } from '../core/scales'
63
+ import type {
64
+ AxisConfig,
65
+ DataSeries,
66
+ InternalPoint,
67
+ ScatterHandlerProps,
68
+ } from '../core/types'
69
+ import {
70
+ COLOR_BAR_DEFAULTS,
71
+ REF_LINE_STYLE_DEFAULTS,
72
+ SCALE_DEFAULTS,
73
+ } from '../core/types'
74
+ import { resolve_line_endpoints } from '../core/reference-line'
35
75
  import {
36
76
  compute_label_positions,
37
77
  estimate_label_size,
@@ -43,7 +83,6 @@
43
83
  import type { HTMLAttributes } from 'svelte/elements'
44
84
  import { SvelteMap, SvelteSet } from 'svelte/reactivity'
45
85
  import type {
46
- BinnedColorScaleConfig,
47
86
  BinnedDensityConfig,
48
87
  BinnedOverlaysConfig,
49
88
  BinnedPointDataFn,
@@ -52,6 +91,7 @@
52
91
  BinnedPointTooltipPayload,
53
92
  BinnedSizeScaleConfig,
54
93
  } from './binned-scatter-types'
94
+ import { DEFAULT_BINNED_SIZE_SCALE } from './binned-scatter-types'
55
95
 
56
96
  type RenderMode = `density` | `points`
57
97
  type DensePointEvent = {
@@ -65,29 +105,15 @@
65
105
  event: MouseEvent
66
106
  }
67
107
  type OverlayContext = { height: number; width: number; fullscreen: boolean }
68
- const default_color_bar_size = { width: 220, height: 10 }
69
108
  const default_density_auto_point_mode = { max_points: 25_000, max_points_per_px: 0.12 }
70
109
  const default_density_color_bar: ComponentProps<typeof ColorBar> = { title: `Density` }
71
- const default_density_color_scale = {
72
- type: `linear`,
73
- scheme: `interpolateViridis`,
74
- } satisfies Exclude<BinnedColorScaleConfig, string>
75
- const default_pad = { l: 64, r: 24, t: 24, b: 56 }
76
- const default_point_radius_range: Vec2 = [4, 12]
77
- const default_pick_radius = default_point_radius_range[1]
78
- const default_size_scale = {
79
- type: `linear`,
80
- radius_range: default_point_radius_range,
81
- pick_radius: default_pick_radius,
82
- } satisfies BinnedSizeScaleConfig
83
110
  const max_placement_bins = 500
84
- const default_point_color = `#4dabf7`
85
111
 
86
112
  let {
87
113
  series,
88
114
  x_axis = {},
89
115
  y_axis = {},
90
- size_scale = default_size_scale,
116
+ size_scale = DEFAULT_BINNED_SIZE_SCALE,
91
117
  density: density_config = {},
92
118
  overlays: overlays_config = {},
93
119
  padding: padding_config = {},
@@ -103,6 +129,8 @@
103
129
  fullscreen_toggle = true,
104
130
  children,
105
131
  header_controls,
132
+ annotation,
133
+ marginals = false,
106
134
  ...rest
107
135
  }: Omit<HTMLAttributes<HTMLDivElement>, `children`> & {
108
136
  series: DensePointSeries<Metadata>[]
@@ -124,6 +152,10 @@
124
152
  fullscreen_toggle?: boolean
125
153
  children?: Snippet<[OverlayContext]>
126
154
  header_controls?: Snippet<[OverlayContext]>
155
+ // auto-placed badge (e.g. MAE/R² stats): rendered inside the plot area wherever it
156
+ // overlaps the least data, while also avoiding the auto-placed colorbar
157
+ annotation?: Snippet<[OverlayContext]>
158
+ marginals?: MarginalsProp
127
159
  } = $props()
128
160
 
129
161
  let canvas = $state<HTMLCanvasElement>()
@@ -132,28 +164,84 @@
132
164
  let x_range = $state<Vec2>([0, 1])
133
165
  let y_range = $state<Vec2>([0, 1])
134
166
  let has_user_range = $state(false)
135
- let drag_start = $state<Point2D | null>(null)
136
- let drag_current = $state<Point2D | null>(null)
167
+ let drag_state = $state<{ start: Point2D; current: Point2D } | null>(null)
137
168
  let suppress_next_click = false
138
169
  let hovered_bin = $state<DensityBin | null>(null)
139
170
  let hovered_point = $state<DenseInternalPoint<Metadata> | null>(null)
140
171
  let tooltip_pos = $state<Point2D>({ x: 0, y: 0 })
141
172
  let colorbar_element = $state<HTMLDivElement>()
173
+ let annotation_element = $state<HTMLDivElement>()
174
+ let colorbar_size_revision = $state(0)
142
175
  let label_measure_root = $state<HTMLDivElement>()
143
176
  let label_sizes = new SvelteMap<string, LabelSize>()
144
177
  const clip_path_id = `binned-scatter-plot-area-${next_clip_id++}`
145
178
 
146
- let pad = $derived(filter_padding(padding_config, default_pad))
179
+ const resolved_marginals = $derived(
180
+ normalize_marginals(marginals, { top: true, right: true }),
181
+ )
182
+ // Unlike the other 2D plots this one doesn't auto-grow padding for tick labels, so this
183
+ // shared default is its final pad (merged with any user `padding`), not just a floor.
184
+ let pad = $derived(
185
+ add_sides(
186
+ filter_padding(padding_config, DEFAULT_PLOT_PADDING),
187
+ reserve_marginal_pad(resolved_marginals),
188
+ ),
189
+ )
190
+ const marginal_series = $derived<MarginalSeriesInput[]>(
191
+ series.map((srs, idx) => ({
192
+ x: srs.x,
193
+ y: srs.y,
194
+ color: srs.color ?? get_series_color(idx),
195
+ label: srs.label,
196
+ visible: true,
197
+ })),
198
+ )
199
+ const marginal_has_axis = marginal_axis_presence(false, false)
147
200
  let density_settings = $derived({
148
201
  bin_px: density_config.bin_px ?? 2.8,
149
- color_scale: density_config.color_scale ?? default_density_color_scale,
150
- color_bar: density_config.color_bar === undefined ? default_density_color_bar : density_config.color_bar,
151
- auto_point_mode: density_config.auto_point_mode === undefined
152
- ? default_density_auto_point_mode
153
- : density_config.auto_point_mode,
202
+ color_scale: density_config.color_scale ?? SCALE_DEFAULTS.color,
203
+ color_bar:
204
+ density_config.color_bar === undefined
205
+ ? default_density_color_bar
206
+ : density_config.color_bar,
207
+ auto_point_mode:
208
+ density_config.auto_point_mode === undefined
209
+ ? default_density_auto_point_mode
210
+ : density_config.auto_point_mode,
154
211
  bin_click: density_config.bin_click ?? `zoom`,
155
212
  })
156
- let ref_lines = $derived(overlays_config.ref_lines ?? [])
213
+ // pixel-space endpoints + style per ref line. Declarative RefLine entries (with a
214
+ // `type` field) are resolved against the current axis ranges via the shared core
215
+ // resolver, so e.g. a parity diagonal spans the full plot area and stays correct
216
+ // under zoom; legacy explicit-endpoint entries are scaled as-is (clip path crops
217
+ // out-of-range parts). Annotation/legend/interaction RefLine fields are ignored.
218
+ let resolved_ref_lines = $derived.by(() => {
219
+ const [x_min, x_max] = range_bounds(x_range)
220
+ const [y_min, y_max] = range_bounds(y_range)
221
+ return (overlays_config.ref_lines ?? []).flatMap((line) => {
222
+ if (!(`type` in line)) {
223
+ return {
224
+ x1: x_scale_fn(line.x1),
225
+ y1: y_scale_fn(line.y1),
226
+ x2: x_scale_fn(line.x2),
227
+ y2: y_scale_fn(line.y2),
228
+ color: line.color ?? `currentColor`,
229
+ width: line.width ?? 1.5,
230
+ dash: line.dash ?? `5 4`,
231
+ opacity: 1,
232
+ }
233
+ }
234
+ if (line.visible === false) return []
235
+ const endpoints = resolve_line_endpoints(
236
+ line,
237
+ { x_min, x_max, y_min, y_max },
238
+ { x_scale: x_scale_fn, y_scale: y_scale_fn },
239
+ )
240
+ if (!endpoints) return []
241
+ const [x1, y1, x2, y2] = endpoints
242
+ return { x1, y1, x2, y2, ...REF_LINE_STYLE_DEFAULTS, ...line.style }
243
+ })
244
+ })
157
245
  let point_labels_settings = $derived({
158
246
  font_size: point_labels.font_size ?? `11px`,
159
247
  max_count: point_labels.max_count ?? 50,
@@ -178,14 +266,16 @@
178
266
  const needs_data_range = (range: AxisConfig[`range`] | undefined): boolean =>
179
267
  range?.[0] == null || range?.[1] == null
180
268
 
269
+ let x_scale_type = $derived(x_axis.scale_type ?? `linear`)
270
+ let y_scale_type = $derived(y_axis.scale_type ?? `linear`)
181
271
  let needs_auto_range = $derived(
182
272
  needs_data_range(x_axis.range) || needs_data_range(y_axis.range),
183
273
  )
184
274
  let auto_ranges = $derived(
185
- needs_auto_range ? series_extents(series) : { x: [0, 1] as Vec2, y: [0, 1] as Vec2 },
275
+ needs_auto_range
276
+ ? series_extents(series, x_scale_type, y_scale_type)
277
+ : { x: [0, 1] as Vec2, y: [0, 1] as Vec2 },
186
278
  )
187
- let x_scale_type = $derived(x_axis.scale_type ?? `linear`)
188
- let y_scale_type = $derived(y_axis.scale_type ?? `linear`)
189
279
  let has_plot_size = $derived(width > 0 && height > 0)
190
280
 
191
281
  const axis_range = (axis: AxisConfig, fallback: Vec2): Vec2 => [
@@ -217,14 +307,8 @@
217
307
  width: plot_width,
218
308
  height: plot_height,
219
309
  })
220
- let x_scale_fn = $derived(create_scale(x_scale_type, x_range, [
221
- pad.l,
222
- width - pad.r,
223
- ]))
224
- let y_scale_fn = $derived(create_scale(y_scale_type, y_range, [
225
- height - pad.b,
226
- pad.t,
227
- ]))
310
+ let x_scale_fn = $derived(create_scale(x_scale_type, x_range, [pad.l, width - pad.r]))
311
+ let y_scale_fn = $derived(create_scale(y_scale_type, y_range, [height - pad.b, pad.t]))
228
312
  let x_ticks = $derived(
229
313
  generate_ticks(x_range, x_scale_type, x_axis.ticks, x_scale_fn, {
230
314
  default_count: 7,
@@ -251,10 +335,14 @@
251
335
  const bin_at = (coords: Point2D) =>
252
336
  density_bin_at_point(density_result, coords, plot_rect, x_range, y_range, bin_transforms)
253
337
  let auto_color_range = $derived<Vec2>([1, Math.max(1, density_result.max_count)])
254
- let color_scale_fn = $derived(create_color_scale(density_settings.color_scale, auto_color_range))
338
+ let color_scale_fn = $derived(
339
+ create_color_scale(density_settings.color_scale, auto_color_range),
340
+ )
255
341
  let hovered_bin_color = $derived(hovered_bin ? color_scale_fn(hovered_bin.count) : undefined)
256
342
  let color_scale_type = $derived(
257
- typeof density_settings.color_scale === `string` ? undefined : density_settings.color_scale.type,
343
+ typeof density_settings.color_scale === `string`
344
+ ? undefined
345
+ : density_settings.color_scale.type,
258
346
  )
259
347
  let color_bar_props = $derived.by((): ComponentProps<typeof ColorBar> | null => {
260
348
  const color_bar = density_settings.color_bar
@@ -266,8 +354,9 @@
266
354
  tick_format: color_bar.tick_format ?? `.2~s`,
267
355
  tick_labels: color_bar.tick_labels ?? 4,
268
356
  tick_side: color_bar.tick_side ?? `primary`,
269
- bar_style: color_bar.bar_style ??
270
- `width: ${default_color_bar_size.width}px; height: ${default_color_bar_size.height}px; ${color_bar.style ?? ``}`,
357
+ bar_style:
358
+ color_bar.bar_style ??
359
+ `width: ${COLOR_BAR_DEFAULTS.width}px; height: ${COLOR_BAR_DEFAULTS.binned_bar_height}px; ${color_bar.style ?? ``}`,
271
360
  }
272
361
  })
273
362
  let density_placement_points = $derived.by(() => {
@@ -275,8 +364,8 @@
275
364
  const bin_w = plot_width / density_result.x_bins
276
365
  const bin_h = plot_height / density_result.y_bins
277
366
  let occupied_count = 0
278
- for (let idx = 0; idx < density_result.counts.length; idx++) {
279
- if (density_result.counts[idx]) occupied_count++
367
+ for (const count of density_result.counts) {
368
+ if (count) occupied_count++
280
369
  }
281
370
  const stride = Math.max(1, Math.ceil(occupied_count / max_placement_bins))
282
371
  let occupied_idx = 0
@@ -292,7 +381,14 @@
292
381
  }
293
382
  return points
294
383
  })
295
- let color_bar_placement = $derived.by(() => {
384
+ // Fallback sizes (incl. room for tick labels) used before the colorbar first
385
+ // renders; compute_element_placement measures the real footprint once laid out
386
+ let colorbar_fallback_size = $derived(
387
+ color_bar_props?.orientation === `vertical`
388
+ ? COLOR_BAR_DEFAULTS.vertical_footprint
389
+ : COLOR_BAR_DEFAULTS.horizontal_footprint,
390
+ )
391
+ const get_color_bar_placement = () => {
296
392
  if (
297
393
  !color_bar_props ||
298
394
  render_mode !== `density` ||
@@ -303,34 +399,69 @@
303
399
  return null
304
400
  }
305
401
 
306
- const is_vertical = color_bar_props?.orientation === `vertical`
307
- // Fallback sizes (incl. room for tick labels) used before the colorbar first
308
- // renders; compute_element_placement measures the real footprint once laid out
309
- const fallback_size = is_vertical
310
- ? { width: 56, height: 120 }
311
- : { width: default_color_bar_size.width, height: 50 }
312
-
313
402
  return compute_element_placement({
314
403
  plot_bounds: plot_rect,
315
404
  element: colorbar_element,
316
- element_size: fallback_size,
405
+ element_size: colorbar_fallback_size,
317
406
  // Small gap from the corner; the full-footprint measurement reserves the tick
318
407
  // labels, so this alone keeps the colorbar off the axes
319
408
  axis_clearance: 12,
320
409
  points: density_placement_points,
321
410
  grid_resolution: 12,
322
411
  })
412
+ }
413
+ // Fallback footprint before the annotation snippet first renders; the real
414
+ // footprint is measured once laid out (mirrors colorbar_fallback_size above)
415
+ const annotation_fallback_size = { width: 120, height: 50 }
416
+ // Auto-place the annotation snippet like the colorbar, but with the already-placed
417
+ // colorbar's footprint as an exclusion zone so the two never overlap.
418
+ const get_annotation_placement = () => {
419
+ if (!annotation || !width || !height) return null
420
+
421
+ const color_bar_placement = colorbar_tween.placed()
422
+ ? colorbar_tween.coords.target
423
+ : get_color_bar_placement()
424
+ const colorbar_footprint = full_footprint_or(colorbar_element, colorbar_fallback_size)
425
+ const colorbar_rect = color_bar_placement && {
426
+ ...colorbar_footprint,
427
+ x: color_bar_placement.x + colorbar_footprint.offset_x,
428
+ y: color_bar_placement.y + colorbar_footprint.offset_y,
429
+ }
430
+ return compute_element_placement({
431
+ plot_bounds: plot_rect,
432
+ element: annotation_element,
433
+ element_size: annotation_fallback_size,
434
+ axis_clearance: 12,
435
+ exclude_rects: colorbar_rect ? [colorbar_rect] : [],
436
+ points: density_placement_points,
437
+ grid_resolution: 12,
438
+ })
439
+ }
440
+ const colorbar_tween = create_placed_tween({
441
+ placement: get_color_bar_placement,
442
+ dims: () => ({ width, height }),
443
+ responsive: () => false,
444
+ element: () => colorbar_element,
445
+ on_element_resize: () => (colorbar_size_revision += 1),
446
+ })
447
+ const annotation_tween = create_placed_tween({
448
+ placement: get_annotation_placement,
449
+ dims: () => ({ width, height }),
450
+ responsive: () => false,
451
+ element: () => annotation_element,
452
+ placement_revision: () =>
453
+ `${colorbar_size_revision}:${colorbar_tween.coords.target.x}:${colorbar_tween.coords.target.y}`,
323
454
  })
324
455
 
325
456
  let auto_render_mode = $derived.by((): RenderMode => {
326
457
  const auto_point_mode = density_settings.auto_point_mode
327
458
  if (auto_point_mode === false) return render_mode
328
459
  return should_render_points(
329
- density_result.visible_count,
330
- plot_width * plot_height,
331
- auto_point_mode.max_points ?? default_density_auto_point_mode.max_points,
332
- auto_point_mode.max_points_per_px ?? default_density_auto_point_mode.max_points_per_px,
333
- )
460
+ density_result.visible_count,
461
+ plot_width * plot_height,
462
+ auto_point_mode.max_points ?? default_density_auto_point_mode.max_points,
463
+ auto_point_mode.max_points_per_px ?? default_density_auto_point_mode.max_points_per_px,
464
+ )
334
465
  ? `points`
335
466
  : `density`
336
467
  })
@@ -338,8 +469,7 @@
338
469
  const values: number[] = []
339
470
  for (const srs of series) {
340
471
  if (!srs.size_values) continue
341
- for (let idx = 0; idx < srs.size_values.length; idx++) {
342
- const size_value = srs.size_values[idx]
472
+ for (const size_value of Array.from(srs.size_values)) {
343
473
  if (size_value == null || !Number.isFinite(size_value)) continue
344
474
  values.push(size_value)
345
475
  }
@@ -347,12 +477,16 @@
347
477
  return values
348
478
  })
349
479
  let size_scale_fn = $derived(create_size_scale(size_scale, all_size_values))
350
- let min_point_radius = $derived(size_scale.radius_range?.[0] ?? default_point_radius_range[0])
351
- let max_point_radius = $derived(size_scale.radius_range?.[1] ?? default_point_radius_range[1])
480
+ let min_point_radius = $derived(
481
+ size_scale.radius_range?.[0] ?? SCALE_DEFAULTS.binned_radius[0],
482
+ )
483
+ let max_point_radius = $derived(
484
+ size_scale.radius_range?.[1] ?? SCALE_DEFAULTS.binned_radius[1],
485
+ )
352
486
  let pick_radius_px = $derived(
353
487
  size_scale.pick_radius === `auto`
354
488
  ? max_point_radius
355
- : size_scale.pick_radius ?? default_pick_radius,
489
+ : (size_scale.pick_radius ?? SCALE_DEFAULTS.binned_radius[1]),
356
490
  )
357
491
 
358
492
  $effect(() => {
@@ -411,7 +545,10 @@
411
545
  if (!style) {
412
546
  style = {
413
547
  fill: color_scale_fn(count),
414
- alpha: Math.min(0.95, 0.2 + Math.log1p(count) / Math.log1p(density_result.max_count)),
548
+ alpha: Math.min(
549
+ 0.95,
550
+ 0.2 + Math.log1p(count) / Math.log1p(density_result.max_count),
551
+ ),
415
552
  }
416
553
  style_cache.set(count, style)
417
554
  }
@@ -433,7 +570,7 @@
433
570
  const [y_min, y_max] = range_bounds(y_range)
434
571
  const pulse = selected_pulse.unit
435
572
  for (const [series_idx, srs] of series.entries()) {
436
- ctx.fillStyle = srs.color ?? default_point_color
573
+ ctx.fillStyle = srs.color ?? get_series_color(series_idx)
437
574
  const n_points = Math.min(srs.x.length, srs.y.length)
438
575
  for (let point_idx = 0; point_idx < n_points; point_idx++) {
439
576
  const x = srs.x[point_idx]
@@ -453,7 +590,7 @@
453
590
  ctx.fill()
454
591
  if (is_selected) {
455
592
  ctx.globalAlpha = 0.35 + 0.25 * pulse
456
- ctx.strokeStyle = srs.color ?? default_point_color
593
+ ctx.strokeStyle = srs.color ?? get_series_color(series_idx)
457
594
  ctx.lineWidth = 1.5 + pulse
458
595
  ctx.beginPath()
459
596
  ctx.arc(cx, cy, radius * (1.45 + 0.25 * pulse), 0, 2 * Math.PI)
@@ -482,8 +619,9 @@
482
619
  })
483
620
 
484
621
  function pointer_coords(event: PointerEvent | MouseEvent): Point2D | null {
485
- if (!wrapper) return null
486
- const rect = wrapper.getBoundingClientRect()
622
+ if (!canvas) return null
623
+ // The fullscreen wrapper has a top border outside the canvas coordinate space.
624
+ const rect = canvas.getBoundingClientRect()
487
625
  return { x: event.clientX - rect.left, y: event.clientY - rect.top }
488
626
  }
489
627
 
@@ -514,7 +652,7 @@
514
652
  })
515
653
 
516
654
  const point_color = (point: DenseInternalPoint<Metadata>): string =>
517
- series[point.series_idx]?.color ?? default_point_color
655
+ series[point.series_idx]?.color ?? get_series_color(point.series_idx)
518
656
 
519
657
  const point_label_key = (point: DenseInternalPoint<Metadata>): string =>
520
658
  `${point.series_idx}-${point.point_idx}`
@@ -554,7 +692,7 @@
554
692
  payload: BinnedPointPayload<Metadata, PointData>,
555
693
  ): LabelSize =>
556
694
  label_sizes.get(point_label_key(payload.point)) ??
557
- estimate_label_size(label_measure_text(payload), point_labels_settings.font_size)
695
+ estimate_label_size(label_measure_text(payload), point_labels_settings.font_size)
558
696
 
559
697
  let point_label_payloads = $derived.by(() => {
560
698
  if (!point_labels_settings.render || render_mode !== `points`) return []
@@ -575,7 +713,8 @@
575
713
  x > x_max ||
576
714
  y < y_min ||
577
715
  y > y_max
578
- ) continue
716
+ )
717
+ continue
579
718
  payloads.push(point_payload(make_point(series_idx, point_idx)))
580
719
  if (payloads.length > point_labels_settings.max_count) return []
581
720
  }
@@ -586,20 +725,19 @@
586
725
  let point_label_positions = $derived.by(() => {
587
726
  if (point_label_payloads.length === 0) return {}
588
727
 
589
- const filtered_data: InternalPoint<Metadata>[] = point_label_payloads.map(
590
- (payload) => ({
591
- ...payload.point,
592
- point_label: {
593
- text: label_measure_text(payload),
594
- auto_placement: true,
595
- font_size: point_labels_settings.font_size,
596
- size: label_sizes.get(point_label_key(payload.point)),
597
- },
598
- point_style: {
599
- radius: point_radius_for_value(payload.point.size_value) + point_labels_settings.gap_px,
600
- },
601
- }),
602
- )
728
+ const filtered_data: InternalPoint<Metadata>[] = point_label_payloads.map((payload) => ({
729
+ ...payload.point,
730
+ point_label: {
731
+ text: label_measure_text(payload),
732
+ auto_placement: true,
733
+ font_size: point_labels_settings.font_size,
734
+ size: label_sizes.get(point_label_key(payload.point)),
735
+ },
736
+ point_style: {
737
+ radius:
738
+ point_radius_for_value(payload.point.size_value) + point_labels_settings.gap_px,
739
+ },
740
+ }))
603
741
  const label_series: DataSeries<Metadata>[] = [{ x: [], y: [], filtered_data }]
604
742
 
605
743
  return compute_label_positions(
@@ -615,7 +753,8 @@
615
753
  if (!label_measure_root) return
616
754
 
617
755
  const active_keys = new SvelteSet<string>()
618
- const measured_elements = label_measure_root.querySelectorAll<HTMLElement>(`[data-label-key]`)
756
+ const measured_elements =
757
+ label_measure_root.querySelectorAll<HTMLElement>(`[data-label-key]`)
619
758
  for (const element of measured_elements) {
620
759
  const label_key = element.dataset.labelKey
621
760
  if (!label_key) continue
@@ -641,7 +780,10 @@
641
780
  payload: BinnedPointPayload<Metadata, PointData>,
642
781
  label_position: Point2D,
643
782
  ): { x1: number; y1: number; x2: number; y2: number } | null {
644
- const displacement = Math.hypot(label_position.x - payload.cx, label_position.y - payload.cy)
783
+ const displacement = Math.hypot(
784
+ label_position.x - payload.cx,
785
+ label_position.y - payload.cy,
786
+ )
645
787
  if (displacement <= (actual_label_placement_config.leader_line_threshold ?? 15)) {
646
788
  return null
647
789
  }
@@ -670,7 +812,8 @@
670
812
  hovered_bin?.x_bin !== bin?.x_bin ||
671
813
  hovered_bin?.y_bin !== bin?.y_bin ||
672
814
  hovered_bin?.count !== bin?.count
673
- ) hovered_bin = bin
815
+ )
816
+ hovered_bin = bin
674
817
  return
675
818
  }
676
819
 
@@ -679,7 +822,8 @@
679
822
  if (
680
823
  hovered_point?.series_idx !== point?.series_idx ||
681
824
  hovered_point?.point_idx !== point?.point_idx
682
- ) hovered_point = point
825
+ )
826
+ hovered_point = point
683
827
  }
684
828
 
685
829
  function emit_point_click(
@@ -720,13 +864,7 @@
720
864
  }
721
865
  if (bin.count > 1 && density_settings.bin_click !== `point`) return
722
866
 
723
- const point = first_point_in_bin(
724
- series,
725
- density_result,
726
- bin,
727
- x_scale_fn,
728
- y_scale_fn,
729
- )
867
+ const point = first_point_in_bin(series, density_result, bin, x_scale_fn, y_scale_fn)
730
868
  if (point) emit_point_click(point, event, color_scale_fn(bin.count))
731
869
  return
732
870
  }
@@ -739,43 +877,36 @@
739
877
  function on_pointer_down(event: PointerEvent) {
740
878
  if (event.button !== 0) return
741
879
  const coords = pointer_coords(event)
742
- if (!coords) return
743
- drag_start = coords
744
- drag_current = coords
880
+ if (!coords || !point_in_rect(coords, plot_rect)) return
881
+ drag_state = { start: coords, current: coords }
745
882
  if (event.currentTarget instanceof HTMLElement) {
746
883
  event.currentTarget.setPointerCapture?.(event.pointerId)
747
884
  }
748
885
  }
749
886
 
750
887
  function on_pointer_drag(event: PointerEvent) {
751
- if (!drag_start) {
888
+ if (!drag_state) {
752
889
  on_pointer_move(event)
753
890
  return
754
891
  }
755
892
  const coords = pointer_coords(event)
756
- if (coords) drag_current = coords
893
+ if (coords) drag_state.current = coords
757
894
  }
758
895
 
759
896
  function on_pointer_up(event: PointerEvent) {
760
- const start = drag_start
761
- const end = drag_current
762
- drag_start = null
763
- drag_current = null
764
-
765
- if (start && end && Math.abs(end.x - start.x) > 5 && Math.abs(end.y - start.y) > 5) {
766
- const x0 = x_scale_fn.invert(start.x)
767
- const x1 = x_scale_fn.invert(end.x)
768
- const y0 = y_scale_fn.invert(start.y)
769
- const y1 = y_scale_fn.invert(end.y)
770
- x_range = [Math.min(x0, x1), Math.max(x0, x1)]
771
- y_range = [Math.min(y0, y1), Math.max(y0, y1)]
772
- has_user_range = true
773
- suppress_next_click = true
774
- }
897
+ if (!drag_state) return
898
+ const { start, current: end } = drag_state
899
+ drag_state = null
775
900
 
776
901
  if (event.currentTarget instanceof HTMLElement) {
777
902
  event.currentTarget.releasePointerCapture?.(event.pointerId)
778
903
  }
904
+ if (Math.abs(end.x - start.x) <= 5 || Math.abs(end.y - start.y) <= 5) return
905
+
906
+ x_range = sorted_range(x_scale_fn.invert(start.x), x_scale_fn.invert(end.x))
907
+ y_range = sorted_range(y_scale_fn.invert(start.y), y_scale_fn.invert(end.y))
908
+ has_user_range = true
909
+ suppress_next_click = true
779
910
  }
780
911
 
781
912
  onMount(() => {
@@ -801,7 +932,7 @@
801
932
  <div
802
933
  {...rest}
803
934
  bind:this={wrapper}
804
- class="binned-scatter {rest.class ?? ``}"
935
+ class={[`binned-scatter`, rest.class]}
805
936
  class:fullscreen
806
937
  data-render-mode={render_mode}
807
938
  style:--binned-scatter-label-font-size={point_labels_settings.font_size}
@@ -841,7 +972,7 @@
841
972
 
842
973
  <canvas bind:this={canvas}></canvas>
843
974
 
844
- <svg width={width} height={height} aria-hidden="true">
975
+ <svg {width} {height} aria-hidden="true">
845
976
  <defs>
846
977
  <clipPath id={clip_path_id}>
847
978
  <rect x={pad.l} y={pad.t} width={plot_width} height={plot_height} />
@@ -849,15 +980,16 @@
849
980
  </defs>
850
981
 
851
982
  <g class="reference-lines" clip-path="url(#{clip_path_id})">
852
- {#each ref_lines as line}
983
+ {#each resolved_ref_lines as line}
853
984
  <line
854
- x1={x_scale_fn(line.x1)}
855
- x2={x_scale_fn(line.x2)}
856
- y1={y_scale_fn(line.y1)}
857
- y2={y_scale_fn(line.y2)}
858
- stroke={line.color ?? `currentColor`}
859
- stroke-width={line.width ?? 1.5}
860
- stroke-dasharray={line.dash ?? `5 4`}
985
+ x1={line.x1}
986
+ x2={line.x2}
987
+ y1={line.y1}
988
+ y2={line.y2}
989
+ stroke={line.color}
990
+ stroke-width={line.width}
991
+ stroke-dasharray={line.dash || null}
992
+ stroke-opacity={line.opacity}
861
993
  />
862
994
  {/each}
863
995
  </g>
@@ -872,7 +1004,7 @@
872
1004
  show_grid
873
1005
  tick_label={(tick) => format_value(tick, x_axis.format ?? `.2~g`)}
874
1006
  label_x={pad.l + plot_width / 2}
875
- label_y={height - 12}
1007
+ label_y={height - pad.b + AXIS_TITLE_OFFSET}
876
1008
  />
877
1009
  <PlotAxis
878
1010
  side="y"
@@ -884,17 +1016,19 @@
884
1016
  {height}
885
1017
  show_grid
886
1018
  tick_label={(tick) => format_value(tick, y_axis.format ?? `.2~g`)}
887
- label_x={22}
1019
+ label_x={Math.max(12, pad.l - LABEL_GAP_DEFAULT)}
888
1020
  label_y={pad.t + plot_height / 2}
889
1021
  />
890
1022
 
891
- <ZoomRect start={drag_start} current={drag_current} />
1023
+ <ZoomRect start={drag_state?.start ?? null} current={drag_state?.current ?? null} />
892
1024
 
893
1025
  {#if point_label_payloads.length}
894
1026
  <g class="point-label-leaders" clip-path="url(#{clip_path_id})">
895
1027
  {#each point_label_payloads as payload (point_label_key(payload.point))}
896
1028
  {@const label_position = point_label_positions[point_label_key(payload.point)]}
897
- {@const leader_line = label_position ? label_leader_line(payload, label_position) : null}
1029
+ {@const leader_line = label_position
1030
+ ? label_leader_line(payload, label_position)
1031
+ : null}
898
1032
  {#if leader_line}
899
1033
  <line
900
1034
  x1={leader_line.x1}
@@ -906,6 +1040,21 @@
906
1040
  {/each}
907
1041
  </g>
908
1042
  {/if}
1043
+
1044
+ <!-- Marginal distribution strips -->
1045
+ <PlotMarginals
1046
+ marginals={resolved_marginals}
1047
+ series={marginal_series}
1048
+ {width}
1049
+ {height}
1050
+ {pad}
1051
+ has_axis={marginal_has_axis}
1052
+ axes={{
1053
+ x1: marginal_axis(x_scale_fn, x_range, x_axis),
1054
+ y1: marginal_axis(y_scale_fn, y_range, y_axis),
1055
+ }}
1056
+ id={clip_path_id}
1057
+ />
909
1058
  </svg>
910
1059
 
911
1060
  {#if point_labels_settings.render && point_label_payloads.length}
@@ -938,22 +1087,33 @@
938
1087
  </div>
939
1088
  {/if}
940
1089
 
941
- {#if color_bar_props && render_mode === `density` && density_result.max_count > 0 && color_bar_placement}
1090
+ {#if width > 0 && height > 0 && color_bar_props && render_mode === `density` && density_result.max_count > 0}
942
1091
  <div
943
1092
  bind:this={colorbar_element}
944
1093
  class="color-bar"
945
- style:left={`${color_bar_placement.x}px`}
946
- style:top={`${color_bar_placement.y}px`}
1094
+ style:left={`${colorbar_tween.coords.current.x}px`}
1095
+ style:top={`${colorbar_tween.coords.current.y}px`}
947
1096
  >
948
1097
  <ColorBar
949
1098
  {...color_bar_props}
950
- color_scale_fn={color_scale_fn}
1099
+ {color_scale_fn}
951
1100
  color_scale_domain={auto_color_range}
952
1101
  range={auto_color_range}
953
1102
  />
954
1103
  </div>
955
1104
  {/if}
956
1105
 
1106
+ {#if width > 0 && height > 0 && annotation}
1107
+ <div
1108
+ bind:this={annotation_element}
1109
+ class="annotation"
1110
+ style:left={`${annotation_tween.coords.current.x}px`}
1111
+ style:top={`${annotation_tween.coords.current.y}px`}
1112
+ >
1113
+ {@render annotation({ height, width, fullscreen })}
1114
+ </div>
1115
+ {/if}
1116
+
957
1117
  {#if hovered_bin}
958
1118
  <PlotTooltip
959
1119
  x={tooltip_pos.x}
@@ -961,9 +1121,9 @@
961
1121
  offset={{ x: 0, y: 0 }}
962
1122
  bg_color={hovered_bin_color}
963
1123
  >
964
- {hovered_bin.count.toLocaleString()} samples<br>
1124
+ {hovered_bin.count.toLocaleString()} samples<br />
965
1125
  x: {format_value(hovered_bin.x_range[0], x_axis.format ?? `.3~g`)}
966
- - {format_value(hovered_bin.x_range[1], x_axis.format ?? `.3~g`)}<br>
1126
+ - {format_value(hovered_bin.x_range[1], x_axis.format ?? `.3~g`)}<br />
967
1127
  y: {format_value(hovered_bin.y_range[0], y_axis.format ?? `.3~g`)}
968
1128
  - {format_value(hovered_bin.y_range[1], y_axis.format ?? `.3~g`)}
969
1129
  </PlotTooltip>
@@ -973,7 +1133,7 @@
973
1133
  {#if tooltip}
974
1134
  {@render tooltip(props)}
975
1135
  {:else}
976
- {x_axis.label ?? `x`}: {props.x_formatted}<br>
1136
+ {x_axis.label ?? `x`}: {props.x_formatted}<br />
977
1137
  {y_axis.label ?? `y`}: {props.y_formatted}
978
1138
  {/if}
979
1139
  </PlotTooltip>
@@ -1029,7 +1189,9 @@
1029
1189
  position: absolute;
1030
1190
  right: var(--fullscreen-btn-right, 4px);
1031
1191
  top: var(--ctrl-btn-top, 5pt);
1032
- transition: opacity 0.2s, background-color 0.2s;
1192
+ transition:
1193
+ opacity 0.2s,
1194
+ background-color 0.2s;
1033
1195
  z-index: var(--fullscreen-btn-z-index, 10);
1034
1196
  }
1035
1197
  .header-controls :global(.fullscreen-toggle) {
@@ -1069,7 +1231,10 @@
1069
1231
  opacity: 0.75;
1070
1232
  }
1071
1233
  .point-label-leaders line {
1072
- stroke: var(--binned-scatter-label-leader-color, color-mix(in srgb, currentColor 60%, transparent));
1234
+ stroke: var(
1235
+ --binned-scatter-label-leader-color,
1236
+ color-mix(in srgb, currentColor 60%, transparent)
1237
+ );
1073
1238
  stroke-dasharray: var(--binned-scatter-label-leader-dash, 2 2);
1074
1239
  stroke-width: var(--binned-scatter-label-leader-width, 0.8);
1075
1240
  }
@@ -1111,4 +1276,9 @@
1111
1276
  pointer-events: auto;
1112
1277
  position: absolute;
1113
1278
  }
1279
+ .annotation {
1280
+ pointer-events: none;
1281
+ position: absolute;
1282
+ width: max-content;
1283
+ }
1114
1284
  </style>