matterviz 0.3.7 → 0.4.0

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 (324) hide show
  1. package/dist/Icon.svelte +7 -4
  2. package/dist/MillerIndexInput.svelte +1 -1
  3. package/dist/api/optimade.js +32 -26
  4. package/dist/app.css +0 -3
  5. package/dist/brillouin/BrillouinZone.svelte +8 -3
  6. package/dist/brillouin/BrillouinZone.svelte.d.ts +2 -1
  7. package/dist/brillouin/BrillouinZoneScene.svelte +52 -6
  8. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -0
  9. package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
  10. package/dist/brillouin/compute.js +10 -14
  11. package/dist/chempot-diagram/ChemPotDiagram.svelte +14 -13
  12. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +12 -15
  13. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +8 -10
  14. package/dist/chempot-diagram/async-compute.svelte.js +3 -1
  15. package/dist/chempot-diagram/chempot-worker.js +2 -1
  16. package/dist/chempot-diagram/compute.d.ts +1 -1
  17. package/dist/chempot-diagram/compute.js +17 -19
  18. package/dist/colors/index.js +6 -5
  19. package/dist/composition/FormulaFilter.svelte +12 -6
  20. package/dist/composition/PieChart.svelte +6 -5
  21. package/dist/composition/chem-sys.d.ts +8 -0
  22. package/dist/composition/chem-sys.js +85 -0
  23. package/dist/composition/format.js +4 -2
  24. package/dist/composition/index.d.ts +1 -0
  25. package/dist/composition/index.js +1 -0
  26. package/dist/composition/parse.js +25 -13
  27. package/dist/convex-hull/ConvexHull2D.svelte +12 -10
  28. package/dist/convex-hull/ConvexHull3D.svelte +5 -5
  29. package/dist/convex-hull/ConvexHull4D.svelte +5 -9
  30. package/dist/convex-hull/ConvexHullStats.svelte +12 -12
  31. package/dist/convex-hull/GasPressureControls.svelte +4 -4
  32. package/dist/convex-hull/TemperatureSlider.svelte +2 -2
  33. package/dist/convex-hull/demo-temperature.d.ts +1 -1
  34. package/dist/convex-hull/demo-temperature.js +20 -22
  35. package/dist/convex-hull/gas-thermodynamics.d.ts +2 -2
  36. package/dist/convex-hull/gas-thermodynamics.js +22 -30
  37. package/dist/convex-hull/helpers.d.ts +3 -0
  38. package/dist/convex-hull/helpers.js +17 -9
  39. package/dist/convex-hull/index.d.ts +1 -1
  40. package/dist/convex-hull/thermodynamics.js +83 -78
  41. package/dist/convex-hull/types.d.ts +1 -1
  42. package/dist/coordination/CoordinationBarPlot.svelte +23 -23
  43. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  44. package/dist/element/ElementTile.svelte.d.ts +1 -1
  45. package/dist/fermi-surface/FermiSlice.svelte +13 -5
  46. package/dist/fermi-surface/FermiSurface.svelte +11 -5
  47. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  48. package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
  49. package/dist/fermi-surface/FermiSurfaceScene.svelte +3 -0
  50. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
  51. package/dist/fermi-surface/compute.js +59 -59
  52. package/dist/fermi-surface/export.js +3 -2
  53. package/dist/fermi-surface/parse.js +7 -4
  54. package/dist/fermi-surface/types.d.ts +1 -0
  55. package/dist/heatmap-matrix/HeatmapMatrix.svelte +23 -21
  56. package/dist/heatmap-matrix/index.js +1 -1
  57. package/dist/io/decompress.js +4 -2
  58. package/dist/io/export.d.ts +4 -4
  59. package/dist/io/export.js +47 -25
  60. package/dist/io/fetch.js +5 -1
  61. package/dist/io/file-drop.d.ts +1 -1
  62. package/dist/io/file-drop.js +35 -36
  63. package/dist/io/url-drop.js +64 -33
  64. package/dist/isosurface/parse.js +6 -7
  65. package/dist/isosurface/slice.js +5 -4
  66. package/dist/isosurface/types.js +1 -1
  67. package/dist/keyboard.d.ts +3 -0
  68. package/dist/keyboard.js +23 -0
  69. package/dist/labels.d.ts +1 -1
  70. package/dist/labels.js +8 -7
  71. package/dist/layout/PropertyFilter.svelte +3 -2
  72. package/dist/layout/SettingsSection.svelte +1 -1
  73. package/dist/layout/json-tree/JsonNode.svelte +1 -1
  74. package/dist/layout/json-tree/JsonTree.svelte +2 -2
  75. package/dist/layout/json-tree/utils.js +5 -4
  76. package/dist/marching-cubes.js +8 -13
  77. package/dist/math.d.ts +5 -1
  78. package/dist/math.js +24 -9
  79. package/dist/overlays/DraggablePane.svelte +4 -4
  80. package/dist/periodic-table/PeriodicTable.svelte +20 -9
  81. package/dist/periodic-table/PropertySelect.svelte +1 -0
  82. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +9 -3
  83. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  84. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  85. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
  86. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
  87. package/dist/phase-diagram/build-diagram.js +2 -2
  88. package/dist/phase-diagram/parse.js +6 -5
  89. package/dist/phase-diagram/types.d.ts +1 -1
  90. package/dist/phase-diagram/utils.d.ts +3 -3
  91. package/dist/phase-diagram/utils.js +8 -12
  92. package/dist/plot/{BarPlot.svelte → bar/BarPlot.svelte} +229 -587
  93. package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +5 -5
  94. package/dist/plot/{BarPlotControls.svelte → bar/BarPlotControls.svelte} +6 -5
  95. package/dist/plot/{BarPlotControls.svelte.d.ts → bar/BarPlotControls.svelte.d.ts} +3 -3
  96. package/dist/plot/{SpacegroupBarPlot.svelte → bar/SpacegroupBarPlot.svelte} +6 -6
  97. package/dist/plot/{SpacegroupBarPlot.svelte.d.ts → bar/SpacegroupBarPlot.svelte.d.ts} +1 -1
  98. package/dist/plot/bar/data.d.ts +40 -0
  99. package/dist/plot/bar/data.js +154 -0
  100. package/dist/plot/bar/geometry.d.ts +39 -0
  101. package/dist/plot/bar/geometry.js +60 -0
  102. package/dist/plot/bar/index.d.ts +3 -0
  103. package/dist/plot/bar/index.js +3 -0
  104. package/dist/plot/box/BoxPlot.svelte +1462 -0
  105. package/dist/plot/box/BoxPlot.svelte.d.ts +94 -0
  106. package/dist/plot/box/BoxPlotControls.svelte +109 -0
  107. package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
  108. package/dist/plot/box/Violin.svelte +14 -0
  109. package/dist/plot/box/Violin.svelte.d.ts +70 -0
  110. package/dist/plot/box/box-plot.d.ts +55 -0
  111. package/dist/plot/box/box-plot.js +126 -0
  112. package/dist/plot/box/index.d.ts +5 -0
  113. package/dist/plot/box/index.js +5 -0
  114. package/dist/plot/box/kde.d.ts +16 -0
  115. package/dist/plot/box/kde.js +160 -0
  116. package/dist/plot/box/quantile.d.ts +3 -0
  117. package/dist/plot/box/quantile.js +53 -0
  118. package/dist/plot/{auto-place.js → core/auto-place.js} +2 -2
  119. package/dist/plot/core/axis-utils.d.ts +46 -0
  120. package/dist/plot/core/axis-utils.js +110 -0
  121. package/dist/plot/{AxisLabel.svelte → core/components/AxisLabel.svelte} +2 -2
  122. package/dist/plot/{AxisLabel.svelte.d.ts → core/components/AxisLabel.svelte.d.ts} +1 -1
  123. package/dist/plot/{ColorBar.svelte → core/components/ColorBar.svelte} +36 -33
  124. package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +2 -2
  125. package/dist/plot/{ColorScaleSelect.svelte → core/components/ColorScaleSelect.svelte} +4 -3
  126. package/dist/plot/{ColorScaleSelect.svelte.d.ts → core/components/ColorScaleSelect.svelte.d.ts} +2 -2
  127. package/dist/plot/core/components/ControlPane.svelte +46 -0
  128. package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
  129. package/dist/plot/{FillArea.svelte → core/components/FillArea.svelte} +17 -6
  130. package/dist/plot/{FillArea.svelte.d.ts → core/components/FillArea.svelte.d.ts} +1 -1
  131. package/dist/plot/{InteractiveAxisLabel.svelte → core/components/InteractiveAxisLabel.svelte} +3 -3
  132. package/dist/plot/{InteractiveAxisLabel.svelte.d.ts → core/components/InteractiveAxisLabel.svelte.d.ts} +2 -2
  133. package/dist/plot/{Line.svelte → core/components/Line.svelte} +30 -13
  134. package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +7 -5
  135. package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +3 -2
  136. package/dist/plot/{PlotControls.svelte → core/components/PlotControls.svelte} +17 -29
  137. package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
  138. package/dist/plot/{PlotLegend.svelte → core/components/PlotLegend.svelte} +21 -10
  139. package/dist/plot/{PlotLegend.svelte.d.ts → core/components/PlotLegend.svelte.d.ts} +3 -2
  140. package/dist/plot/{PlotTooltip.svelte → core/components/PlotTooltip.svelte} +17 -1
  141. package/dist/plot/{PlotTooltip.svelte.d.ts → core/components/PlotTooltip.svelte.d.ts} +8 -0
  142. package/dist/plot/{PortalSelect.svelte → core/components/PortalSelect.svelte} +11 -7
  143. package/dist/plot/{ReferenceLine.svelte → core/components/ReferenceLine.svelte} +3 -3
  144. package/dist/plot/{ReferenceLine.svelte.d.ts → core/components/ReferenceLine.svelte.d.ts} +1 -1
  145. package/dist/plot/{ReferenceLine3D.svelte → core/components/ReferenceLine3D.svelte} +4 -4
  146. package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +2 -2
  147. package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +7 -7
  148. package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +2 -2
  149. package/dist/plot/{ZeroLines.svelte → core/components/ZeroLines.svelte} +3 -3
  150. package/dist/plot/{ZeroLines.svelte.d.ts → core/components/ZeroLines.svelte.d.ts} +3 -3
  151. package/dist/plot/{ZoomRect.svelte → core/components/ZoomRect.svelte} +1 -1
  152. package/dist/plot/{ZoomRect.svelte.d.ts → core/components/ZoomRect.svelte.d.ts} +1 -1
  153. package/dist/plot/core/components/index.d.ts +17 -0
  154. package/dist/plot/core/components/index.js +17 -0
  155. package/dist/plot/{data-cleaning.d.ts → core/data-cleaning.d.ts} +71 -1
  156. package/dist/plot/{data-cleaning.js → core/data-cleaning.js} +3 -5
  157. package/dist/plot/{data-transform.d.ts → core/data-transform.d.ts} +2 -2
  158. package/dist/plot/{data-transform.js → core/data-transform.js} +3 -3
  159. package/dist/plot/core/fill-utils.d.ts +33 -0
  160. package/dist/plot/core/fill-utils.js +388 -0
  161. package/dist/plot/{hover-lock.svelte.js → core/hover-lock.svelte.js} +5 -6
  162. package/dist/plot/core/index.d.ts +10 -0
  163. package/dist/plot/core/index.js +11 -0
  164. package/dist/plot/core/interactions.d.ts +35 -0
  165. package/dist/plot/core/interactions.js +195 -0
  166. package/dist/plot/{layout.d.ts → core/layout.d.ts} +1 -0
  167. package/dist/plot/{layout.js → core/layout.js} +16 -8
  168. package/dist/plot/{reference-line.d.ts → core/reference-line.d.ts} +1 -1
  169. package/dist/plot/{reference-line.js → core/reference-line.js} +23 -36
  170. package/dist/plot/{scales.d.ts → core/scales.d.ts} +2 -2
  171. package/dist/plot/{scales.js → core/scales.js} +84 -85
  172. package/dist/plot/core/svg.d.ts +2 -0
  173. package/dist/plot/core/svg.js +41 -0
  174. package/dist/plot/{types.d.ts → core/types.d.ts} +19 -79
  175. package/dist/plot/{types.js → core/types.js} +1 -1
  176. package/dist/plot/{utils → core/utils}/label-placement.d.ts +2 -2
  177. package/dist/plot/core/utils/series-visibility.d.ts +26 -0
  178. package/dist/plot/{utils → core/utils}/series-visibility.js +29 -2
  179. package/dist/plot/core/utils.d.ts +11 -0
  180. package/dist/plot/core/utils.js +27 -0
  181. package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +154 -294
  182. package/dist/plot/{Histogram.svelte.d.ts → histogram/Histogram.svelte.d.ts} +2 -2
  183. package/dist/plot/{HistogramControls.svelte → histogram/HistogramControls.svelte} +6 -6
  184. package/dist/plot/{HistogramControls.svelte.d.ts → histogram/HistogramControls.svelte.d.ts} +4 -4
  185. package/dist/plot/histogram/index.d.ts +2 -0
  186. package/dist/plot/histogram/index.js +2 -0
  187. package/dist/plot/index.d.ts +8 -41
  188. package/dist/plot/index.js +10 -39
  189. package/dist/plot/sankey/Sankey.svelte +700 -0
  190. package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
  191. package/dist/plot/sankey/SankeyControls.svelte +98 -0
  192. package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
  193. package/dist/plot/sankey/index.d.ts +4 -0
  194. package/dist/plot/sankey/index.js +3 -0
  195. package/dist/plot/sankey/sankey-types.d.ts +42 -0
  196. package/dist/plot/sankey/sankey-types.js +4 -0
  197. package/dist/plot/sankey/sankey.d.ts +52 -0
  198. package/dist/plot/sankey/sankey.js +187 -0
  199. package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +61 -59
  200. package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +4 -4
  201. package/dist/plot/{ElementScatter.svelte → scatter/ElementScatter.svelte} +6 -6
  202. package/dist/plot/{ElementScatter.svelte.d.ts → scatter/ElementScatter.svelte.d.ts} +2 -2
  203. package/dist/plot/{ScatterPlot.svelte → scatter/ScatterPlot.svelte} +221 -642
  204. package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +7 -7
  205. package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
  206. package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +1 -1
  207. package/dist/plot/{ScatterPoint.svelte → scatter/ScatterPoint.svelte} +7 -7
  208. package/dist/plot/{ScatterPoint.svelte.d.ts → scatter/ScatterPoint.svelte.d.ts} +3 -3
  209. package/dist/plot/{adaptive-density.d.ts → scatter/adaptive-density.d.ts} +14 -4
  210. package/dist/plot/{adaptive-density.js → scatter/adaptive-density.js} +46 -20
  211. package/dist/plot/{binned-scatter-types.d.ts → scatter/binned-scatter-types.d.ts} +3 -3
  212. package/dist/plot/scatter/index.d.ts +7 -0
  213. package/dist/plot/scatter/index.js +5 -0
  214. package/dist/plot/scatter/scatter-data.d.ts +19 -0
  215. package/dist/plot/scatter/scatter-data.js +212 -0
  216. package/dist/plot/{ScatterPlot3D.svelte → scatter-3d/ScatterPlot3D.svelte} +12 -10
  217. package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +7 -7
  218. package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +5 -4
  219. package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +2 -2
  220. package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +11 -11
  221. package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +3 -3
  222. package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +1 -1
  223. package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +1 -1
  224. package/dist/plot/scatter-3d/index.d.ts +4 -0
  225. package/dist/plot/scatter-3d/index.js +4 -0
  226. package/dist/plot/sunburst/Sunburst.svelte +1045 -0
  227. package/dist/plot/sunburst/Sunburst.svelte.d.ts +96 -0
  228. package/dist/plot/sunburst/SunburstControls.svelte +200 -0
  229. package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
  230. package/dist/plot/sunburst/index.d.ts +4 -0
  231. package/dist/plot/sunburst/index.js +4 -0
  232. package/dist/plot/sunburst/render.d.ts +34 -0
  233. package/dist/plot/sunburst/render.js +122 -0
  234. package/dist/plot/sunburst/sunburst.d.ts +62 -0
  235. package/dist/plot/sunburst/sunburst.js +266 -0
  236. package/dist/rdf/RdfPlot.svelte +2 -1
  237. package/dist/rdf/calc-rdf.js +11 -24
  238. package/dist/sanitize.js +1 -1
  239. package/dist/settings.d.ts +65 -1
  240. package/dist/settings.js +262 -0
  241. package/dist/spectral/Bands.svelte +39 -29
  242. package/dist/spectral/Bands.svelte.d.ts +3 -4
  243. package/dist/spectral/BandsAndDos.svelte +1 -1
  244. package/dist/spectral/BrillouinBandsDos.svelte +39 -27
  245. package/dist/spectral/Dos.svelte +10 -19
  246. package/dist/spectral/Dos.svelte.d.ts +2 -2
  247. package/dist/spectral/helpers.d.ts +3 -1
  248. package/dist/spectral/helpers.js +95 -29
  249. package/dist/structure/AtomLegend.svelte +8 -9
  250. package/dist/structure/CellSelect.svelte +1 -2
  251. package/dist/structure/Cylinder.svelte +12 -8
  252. package/dist/structure/Cylinder.svelte.d.ts +4 -1
  253. package/dist/structure/Structure.svelte +78 -72
  254. package/dist/structure/Structure.svelte.d.ts +1 -1
  255. package/dist/structure/StructureInfoPane.svelte +5 -6
  256. package/dist/structure/StructureScene.svelte +11 -10
  257. package/dist/structure/atom-properties.js +6 -6
  258. package/dist/structure/bond-order-perception.js +1 -1
  259. package/dist/structure/bonding.d.ts +1 -0
  260. package/dist/structure/bonding.js +43 -15
  261. package/dist/structure/export.js +27 -23
  262. package/dist/structure/index.d.ts +2 -4
  263. package/dist/structure/index.js +1 -3
  264. package/dist/structure/label-placement.js +4 -4
  265. package/dist/structure/measure.d.ts +3 -2
  266. package/dist/structure/measure.js +6 -5
  267. package/dist/structure/parse.js +121 -103
  268. package/dist/structure/pbc.js +4 -0
  269. package/dist/symmetry/SymmetryStats.svelte +2 -2
  270. package/dist/symmetry/index.d.ts +1 -1
  271. package/dist/symmetry/index.js +22 -24
  272. package/dist/symmetry/spacegroups.d.ts +7 -0
  273. package/dist/symmetry/spacegroups.js +48 -13
  274. package/dist/table/HeatmapTable.svelte +63 -11
  275. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  276. package/dist/table/index.d.ts +1 -3
  277. package/dist/table/index.js +1 -1
  278. package/dist/theme/index.js +8 -8
  279. package/dist/tooltip/KCoords.svelte +45 -0
  280. package/dist/tooltip/KCoords.svelte.d.ts +8 -0
  281. package/dist/tooltip/index.d.ts +1 -0
  282. package/dist/tooltip/index.js +1 -0
  283. package/dist/trajectory/Trajectory.svelte +66 -40
  284. package/dist/trajectory/Trajectory.svelte.d.ts +2 -1
  285. package/dist/trajectory/TrajectoryExportPane.svelte +2 -1
  286. package/dist/trajectory/TrajectoryInfoPane.svelte +2 -1
  287. package/dist/trajectory/format-detect.d.ts +1 -0
  288. package/dist/trajectory/format-detect.js +25 -11
  289. package/dist/trajectory/frame-reader.js +17 -50
  290. package/dist/trajectory/helpers.js +1 -1
  291. package/dist/trajectory/index.js +1 -1
  292. package/dist/trajectory/parse/hdf5.js +1 -1
  293. package/dist/trajectory/parse/index.js +14 -6
  294. package/dist/trajectory/parse/vasp.js +36 -17
  295. package/dist/trajectory/parse/xyz.d.ts +24 -0
  296. package/dist/trajectory/parse/xyz.js +102 -89
  297. package/dist/trajectory/plotting.d.ts +1 -1
  298. package/dist/trajectory/plotting.js +15 -15
  299. package/dist/utils.d.ts +1 -0
  300. package/dist/utils.js +6 -4
  301. package/dist/xrd/XrdPlot.svelte +2 -1
  302. package/dist/xrd/calc-xrd.js +15 -12
  303. package/dist/xrd/parse.js +2 -2
  304. package/package.json +22 -18
  305. package/dist/plot/PlotControls.svelte.d.ts +0 -4
  306. package/dist/plot/axis-utils.d.ts +0 -19
  307. package/dist/plot/axis-utils.js +0 -78
  308. package/dist/plot/defaults.d.ts +0 -19
  309. package/dist/plot/defaults.js +0 -9
  310. package/dist/plot/fill-utils.d.ts +0 -46
  311. package/dist/plot/fill-utils.js +0 -322
  312. package/dist/plot/interactions.d.ts +0 -12
  313. package/dist/plot/interactions.js +0 -101
  314. package/dist/plot/svg.d.ts +0 -1
  315. package/dist/plot/svg.js +0 -11
  316. package/dist/plot/utils/series-visibility.d.ts +0 -15
  317. package/dist/plot/utils.d.ts +0 -1
  318. package/dist/plot/utils.js +0 -14
  319. /package/dist/plot/{auto-place.d.ts → core/auto-place.d.ts} +0 -0
  320. /package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +0 -0
  321. /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
  322. /package/dist/plot/{hover-lock.svelte.d.ts → core/hover-lock.svelte.d.ts} +0 -0
  323. /package/dist/plot/{utils → core/utils}/label-placement.js +0 -0
  324. /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
@@ -0,0 +1,195 @@
1
+ import { LOG_EPS } from '../../math';
2
+ import { get_arcsinh_threshold, get_scale_type_name } from './types';
3
+ // Get coordinates of a mouse event relative to an element (the event's
4
+ // currentTarget by default; pass `element` when the handler is delegated and the
5
+ // reference frame differs, e.g. coordinates relative to the svg root)
6
+ export function get_relative_coords(evt, element = evt.currentTarget) {
7
+ if (!(element instanceof Element))
8
+ return null;
9
+ const box = element.getBoundingClientRect();
10
+ if (!box)
11
+ return null;
12
+ return { x: evt.clientX - box.left, y: evt.clientY - box.top };
13
+ }
14
+ // Resolve a delegated event to the integer value of the nearest ancestor's data
15
+ // attribute (e.g. data-sunburst-node-idx), scoped to `root` so targets outside the
16
+ // component don't leak in. Returns null when the event didn't hit an indexed element.
17
+ export function closest_data_idx(event, attr, root) {
18
+ const target = event.target instanceof Element ? event.target.closest(`[${attr}]`) : null;
19
+ if (!target || (root && !root.contains(target)))
20
+ return null;
21
+ const idx = Number(target.getAttribute(attr));
22
+ return Number.isInteger(idx) ? idx : null;
23
+ }
24
+ // Normalize Y2 sync config (handle shorthand string vs full object)
25
+ export function normalize_y2_sync(sync) {
26
+ if (!sync || sync === `none`)
27
+ return { mode: `none` };
28
+ if (typeof sync === `string`)
29
+ return { mode: sync };
30
+ return sync;
31
+ }
32
+ // Helper to check if all values in ranges are finite
33
+ const all_finite = (...ranges) => ranges.every(([a, b]) => Number.isFinite(a) && Number.isFinite(b));
34
+ // Calculate synced y2 range based on sync mode
35
+ export function sync_y2_range(y1_range, y2_base_range, sync) {
36
+ if (sync.mode === `none`)
37
+ return y2_base_range;
38
+ if (!all_finite(y1_range, y2_base_range))
39
+ return y2_base_range;
40
+ // Synced: Y2 has exact same range as Y1
41
+ if (sync.mode === `synced`) {
42
+ return [y1_range[0], y1_range[1]];
43
+ }
44
+ // Align: Position so align_val (default 0) is at same relative position on both axes
45
+ // Y2 range expands as needed to show all data while maintaining alignment
46
+ if (sync.mode === `align`) {
47
+ const align_val = sync.align_value ?? 0;
48
+ const y1_span = y1_range[1] - y1_range[0];
49
+ if (y1_span === 0)
50
+ return y2_base_range;
51
+ // Where is align_val in Y1's range? (0 = bottom, 1 = top)
52
+ const rel_pos = (align_val - y1_range[0]) / y1_span;
53
+ // Ensure Y2 range includes both align_val and all data
54
+ const y2_min_data = Math.min(y2_base_range[0], align_val);
55
+ const y2_max_data = Math.max(y2_base_range[1], align_val);
56
+ // Calculate minimum span needed to fit all data while keeping align_val at rel_pos
57
+ // Constraints: y2_min <= y2_min_data AND y2_max >= y2_max_data
58
+ let y2_span = y2_max_data - y2_min_data;
59
+ if (rel_pos > 0) {
60
+ y2_span = Math.max(y2_span, (align_val - y2_min_data) / rel_pos);
61
+ }
62
+ if (rel_pos < 1) {
63
+ y2_span = Math.max(y2_span, (y2_max_data - align_val) / (1 - rel_pos));
64
+ }
65
+ const y2_min_computed = align_val - rel_pos * y2_span;
66
+ const y2_max_computed = align_val + (1 - rel_pos) * y2_span;
67
+ // When align_val is outside y1_range (rel_pos < 0 or > 1), the formula can produce
68
+ // a range that omits y2_base_range or align_val. Ensure both are always included.
69
+ const y2_min = Math.min(y2_min_computed, y2_base_range[0], align_val);
70
+ const y2_max = Math.max(y2_max_computed, y2_base_range[1], align_val);
71
+ return [y2_min, y2_max];
72
+ }
73
+ return y2_base_range;
74
+ }
75
+ // Forward/inverse transform pair mapping an axis's data values onto its visual
76
+ // metric (the space where equal pixel steps are equal steps; identity for
77
+ // linear/time). Pan and pinch must be uniform in *screen* space - doing the math
78
+ // linearly on a log axis stretches one end of the view and shifts past zero into
79
+ // an all-NaN domain. log clamps at LOG_EPS so a non-positive bound (stale explicit
80
+ // range) recovers instead of propagating -Infinity.
81
+ function axis_transform(scale_type) {
82
+ const name = get_scale_type_name(scale_type);
83
+ if (name === `log`) {
84
+ return { to: (val) => Math.log(Math.max(val, LOG_EPS)), from: Math.exp };
85
+ }
86
+ if (name === `arcsinh`) {
87
+ const threshold = get_arcsinh_threshold(scale_type);
88
+ const to = (val) => Math.asinh(val / threshold);
89
+ const from = (val) => Math.sinh(val) * threshold;
90
+ return { to, from };
91
+ }
92
+ return { to: (val) => val, from: (val) => val };
93
+ }
94
+ // Pan a range by a pixel delta, uniformly in screen space: linear axes shift by a
95
+ // constant amount, log axes by a constant factor (which also can't cross zero).
96
+ // `pixel_span` is the plot's pixel extent along the axis.
97
+ export function pan_range_by_pixels(range, pixel_delta, pixel_span, scale_type) {
98
+ if (pixel_span === 0)
99
+ return range;
100
+ const { to, from } = axis_transform(scale_type);
101
+ const [t0, t1] = [to(range[0]), to(range[1])];
102
+ const t_delta = (pixel_delta / pixel_span) * (t1 - t0);
103
+ return [from(t0 + t_delta), from(t1 + t_delta)];
104
+ }
105
+ // Zoom a range about its screen-space center by `factor` (pinch: >1 zooms in).
106
+ // On log axes the fixed point is the geometric mean - the visual center.
107
+ export function zoom_range_by_factor(range, factor, scale_type) {
108
+ // Guard invalid factors (0/negative/NaN) that would emit Infinity/NaN into axis state
109
+ if (!Number.isFinite(factor) || factor <= 0)
110
+ return range;
111
+ const { to, from } = axis_transform(scale_type);
112
+ const [t0, t1] = [to(range[0]), to(range[1])];
113
+ const center = (t0 + t1) / 2;
114
+ const half_span = (t1 - t0) / factor / 2;
115
+ return [from(center - half_span), from(center + half_span)];
116
+ }
117
+ // Coerce a scale.invert result (number, or Date for time scales) to an epoch number
118
+ export const to_epoch_num = (val) => val instanceof Date ? val.getTime() : val;
119
+ // Remove window drag/pan listeners and reset the body cursor. Call from onDestroy:
120
+ // a component unmounting mid-drag would otherwise leak its listeners and leave the
121
+ // cursor stuck (the mouseup that normally cleans up never fires after unmount).
122
+ export function remove_drag_listeners(move_handlers, up_handlers) {
123
+ if (typeof window === `undefined`)
124
+ return;
125
+ for (const handler of move_handlers) {
126
+ window.removeEventListener(`mousemove`, handler);
127
+ }
128
+ for (const handler of up_handlers) {
129
+ window.removeEventListener(`mouseup`, handler);
130
+ }
131
+ document.body.style.cursor = ``;
132
+ }
133
+ // Sorted [min, max] from two scalar bounds (rect-zoom inverts drag start/end,
134
+ // which arrive in either order depending on drag direction)
135
+ export const sorted_range = (a, b) => [Math.min(a, b), Math.max(a, b)];
136
+ // Strict per-bound equality of two [min, max] ranges
137
+ export const vec2_equal = (a, b) => a[0] === b[0] && a[1] === b[1];
138
+ // True when all four axis ranges match. The range-sync effects use this to skip
139
+ // no-op writes that would otherwise re-trigger the effect and loop.
140
+ export const axis_ranges_equal = (a, b) => vec2_equal(a.x, b.x) &&
141
+ vec2_equal(a.x2, b.x2) &&
142
+ vec2_equal(a.y, b.y) &&
143
+ vec2_equal(a.y2, b.y2);
144
+ // Merge each axis's explicit range over its auto range (per-bound: a null bound
145
+ // falls back to the auto value). Returns null if any resolved bound is non-finite so
146
+ // the caller can skip the sync - writing NaN breaks scales and, since NaN !== NaN,
147
+ // makes the change comparison never settle (an infinite effect loop).
148
+ export function resolve_axis_ranges(axes, auto) {
149
+ const resolve = (axis, fallback) => [
150
+ axis.range?.[0] ?? fallback[0],
151
+ axis.range?.[1] ?? fallback[1],
152
+ ];
153
+ const next = {
154
+ x: resolve(axes.x, auto.x),
155
+ x2: resolve(axes.x2, auto.x2),
156
+ y: resolve(axes.y, auto.y),
157
+ y2: resolve(axes.y2, auto.y2),
158
+ };
159
+ for (const [lo, hi] of [next.x, next.x2, next.y, next.y2]) {
160
+ if (!Number.isFinite(lo) || !Number.isFinite(hi))
161
+ return null;
162
+ }
163
+ return next;
164
+ }
165
+ // Threshold for distinguishing pinch-zoom from pan in touch gestures
166
+ // Scale change > this value triggers zoom instead of pan
167
+ export const PINCH_ZOOM_THRESHOLD = 0.1;
168
+ // Minimum start distance (px) between two touches to treat the gesture as a valid pinch.
169
+ // Guards curr_dist / start_dist scale from blowing up on near-coincident touches
170
+ export const MIN_TOUCH_DISTANCE_PIXELS = 10;
171
+ // Helper to check if range is the default [0, 1] sentinel (no data)
172
+ // Note: min === 0 handles -0 correctly since -0 === 0 in JavaScript
173
+ const is_default_range = ([min, max]) => min === 0 && max === 1;
174
+ // Adopt the new data range, unless all series were hidden (sentinel [0, 1] fallback).
175
+ // NOTE: [0, 1] is the "no data" sentinel - when all series are hidden, auto ranges
176
+ // fall back to [0, 1]. Actual data spanning exactly [0, 1] is a rare edge case.
177
+ export function expand_range_if_needed(current, new_range) {
178
+ // Guard against NaN/Infinity - prefer valid range, fall back to sentinel [0, 1] if both invalid
179
+ const current_valid = all_finite(current);
180
+ const new_valid = all_finite(new_range);
181
+ if (!current_valid && !new_valid)
182
+ return { range: [0, 1], changed: true };
183
+ if (!new_valid)
184
+ return { range: current, changed: false };
185
+ if (!current_valid)
186
+ return { range: new_range, changed: true };
187
+ // When all series are hidden, auto ranges fall back to [0, 1] sentinel.
188
+ // Don't shrink to that — preserve the current view so it doesn't jump.
189
+ if (!is_default_range(current) && is_default_range(new_range)) {
190
+ return { range: current, changed: false };
191
+ }
192
+ // Otherwise adopt the new range directly (both expand and shrink)
193
+ const changed = new_range[0] !== current[0] || new_range[1] !== current[1];
194
+ return { range: new_range, changed };
195
+ }
@@ -6,6 +6,7 @@ export type Sides = {
6
6
  r?: number;
7
7
  };
8
8
  export declare const LABEL_GAP_DEFAULT = 30;
9
+ export declare function y2_axis_label_x(axis: AxisConfig, width: number, pad_r: number, max_tick_width: number): number;
9
10
  export declare const filter_padding: (padding: Partial<Sides> | undefined | null, defaults: Required<Sides>) => Required<Sides>;
10
11
  export declare function measure_text_width(text: string, font?: string): number;
11
12
  export declare function measure_full_footprint(el: HTMLElement): {
@@ -1,7 +1,15 @@
1
- import { format_value } from '../labels';
2
- import { euclidean_dist } from '../math';
1
+ import { format_value } from '../../labels';
2
+ import { euclidean_dist } from '../../math';
3
3
  // Default gap between tick labels and axis labels
4
4
  export const LABEL_GAP_DEFAULT = 30;
5
+ // X position for a right-side (y2) axis label: past the plot edge plus tick shift and
6
+ // measured tick-label width (both zero when tick labels render inside the plot)
7
+ export function y2_axis_label_x(axis, width, pad_r, max_tick_width) {
8
+ const inside = axis.tick?.label?.inside ?? false;
9
+ const tick_shift = inside ? 0 : (axis.tick?.label?.shift?.x ?? 0) + 8;
10
+ const label_offset = (inside ? 0 : max_tick_width) + LABEL_GAP_DEFAULT + (axis.label_shift?.x ?? 0);
11
+ return width - pad_r + tick_shift + label_offset;
12
+ }
5
13
  // Filter undefined values from padding to prevent overriding defaults when spreading
6
14
  // Guards against undefined/null padding inputs (common for optional props)
7
15
  export const filter_padding = (padding, defaults) => ({
@@ -157,10 +165,9 @@ export function sample_series_obstacle_points(pixel_points, draws_line, step) {
157
165
  const n_samples = Math.floor(Math.hypot(point.x - prev.x, point.y - prev.y) / step);
158
166
  for (let idx = 1; idx < n_samples; idx++) {
159
167
  const frac = idx / n_samples;
160
- obstacles.push({
161
- x: prev.x + (point.x - prev.x) * frac,
162
- y: prev.y + (point.y - prev.y) * frac,
163
- });
168
+ const x = prev.x + (point.x - prev.x) * frac;
169
+ const y = prev.y + (point.y - prev.y) * frac;
170
+ obstacles.push({ x, y });
164
171
  }
165
172
  }
166
173
  prev = point;
@@ -254,8 +261,9 @@ export function compute_element_placement(config) {
254
261
  const min_distance = min_distance_sq === Infinity ? 0 : Math.sqrt(min_distance_sq);
255
262
  // Corner preference: use element's actual corner (not center) for distance
256
263
  // This ensures a wide element at the left edge gets proper corner credit
257
- const elem_right = cand_x + element_size.width;
258
- const elem_bottom = cand_y + element_size.height;
264
+ // (measured footprint, same as cand_rect — not the element_size fallback)
265
+ const elem_right = cand_x + elem_width;
266
+ const elem_bottom = cand_y + elem_height;
259
267
  // Distance from element's matching corner to each plot corner
260
268
  const min_corner_dist = Math.min(euclidean_dist([cand_x, cand_y], [plot_left, plot_top]), // top-left
261
269
  euclidean_dist([elem_right, cand_y], [plot_right, plot_top]), // top-right
@@ -2,7 +2,7 @@ import type { RefLine, RefLineValue } from './types';
2
2
  export type IndexedRefLine = RefLine & {
3
3
  idx: number;
4
4
  };
5
- export declare function index_ref_lines(ref_lines: RefLine[] | undefined): IndexedRefLine[];
5
+ export declare const index_ref_lines: (ref_lines: RefLine[] | undefined) => IndexedRefLine[];
6
6
  export interface RefLinesByZIndex {
7
7
  below_grid: IndexedRefLine[];
8
8
  below_lines: IndexedRefLine[];
@@ -1,9 +1,7 @@
1
1
  // Create indexed ref_lines, filtering out invisible ones
2
- export function index_ref_lines(ref_lines) {
3
- return (ref_lines ?? [])
4
- .filter((line) => line.visible !== false)
5
- .map((line, idx) => ({ ...line, idx }));
6
- }
2
+ export const index_ref_lines = (ref_lines) => (ref_lines ?? [])
3
+ .filter((line) => line.visible !== false)
4
+ .map((line, idx) => ({ ...line, idx }));
7
5
  // Map z-index type values to object keys
8
6
  const Z_INDEX_KEY_MAP = {
9
7
  'below-grid': `below_grid`,
@@ -158,31 +156,18 @@ export function resolve_line_endpoints(ref_line, { x_min, x_max, y_min, y_max, }
158
156
  }
159
157
  }
160
158
  if (!handled_as_vertical) {
161
- // Clip line to y bounds
162
- let x1 = x_min;
163
- let x2 = x_max;
164
- let y1 = slope * x_min + intercept;
165
- let y2 = slope * x_max + intercept;
166
- if (slope === 0) {
167
- if (y1 < y_min || y1 > y_max)
168
- return null;
169
- }
170
- else {
171
- // Clip each endpoint to y bounds
172
- const clip_y = (x, y, bound) => y < y_min || y > y_max ? [(bound - intercept) / slope, bound] : [x, y];
173
- [x1, y1] = clip_y(x1, y1, y1 < y_min ? y_min : y_max);
174
- [x2, y2] = clip_y(x2, y2, y2 < y_min ? y_min : y_max);
175
- // If both endpoints clipped to same point, line is entirely outside bounds
176
- if (x1 === x2 && y1 === y2)
177
- return null;
178
- }
179
- // Ensure consistent ordering before applying span constraints
180
- const [x_lo, x_hi] = x1 <= x2 ? [x1, x2] : [x2, x1];
181
- const [y_lo, y_hi] = y1 <= y2 ? [y1, y2] : [y2, y1];
182
- [x1_data, x2_data] = apply_x_span(x_lo, x_hi);
183
- [y1_data, y2_data] = apply_y_span(y_lo, y_hi);
184
- if (x1_data > x_max || x2_data < x_min)
159
+ // Intersect bounds with span constraints, then clip the line segment spanning the
160
+ // clipped x-extent to that rect — keeps endpoints paired on y = slope·x + intercept
161
+ const [x_lo, x_hi] = apply_x_span(x_min, x_max);
162
+ const [y_lo, y_hi] = apply_y_span(y_min, y_max);
163
+ if (x_lo > x_hi || y_lo > y_hi)
164
+ return null;
165
+ const [y_at_lo, y_at_hi] = [slope * x_lo + intercept, slope * x_hi + intercept];
166
+ const seg = clip_segment_to_rect(x_lo, y_at_lo, x_hi, y_at_hi, x_lo, x_hi, y_lo, y_hi);
167
+ // Degenerate (single-point) result means the line only grazes a corner
168
+ if (!seg || (seg[0] === seg[2] && seg[1] === seg[3]))
185
169
  return null;
170
+ [x1_data, y1_data, x2_data, y2_data] = seg;
186
171
  }
187
172
  }
188
173
  else if (line_type === `segment`) {
@@ -243,19 +228,21 @@ export function calculate_annotation_position(x1, y1, x2, y2, annotation) {
243
228
  // Perpendicular vector (normalized)
244
229
  const nx = -dy / len;
245
230
  const ny = dx / len;
231
+ let sign;
246
232
  if (side === `above` || side === `below`) {
247
233
  // In SVG, y increases downward. Flip sign if 'above' and perpendicular points down (ny > 0),
248
234
  // or if 'below' and perpendicular points up (ny <= 0), to ensure offset is in correct direction
249
- const sign = (side === `above`) === ny > 0 ? -1 : 1;
250
- perp_x = sign * nx * gap;
251
- perp_y = sign * ny * gap;
235
+ sign = (side === `above`) === ny > 0 ? -1 : 1;
252
236
  }
253
237
  else {
254
- // left = perpendicular to the "left" of direction vector, right = opposite
255
- const sign = side === `left` ? 1 : -1;
256
- perp_x = sign * nx * gap;
257
- perp_y = sign * ny * gap;
238
+ // left/right offset to the side of the line in screen space (right -> +x, left -> -x), stable
239
+ // regardless of endpoint order vertical ref lines are stored bottom->top, which flips the
240
+ // perpendicular. Horizontal lines (nx == 0) fall back to right = up (-y), left = down (+y).
241
+ const want_right = side === `right`;
242
+ sign = Math.abs(nx) > 1e-9 ? (want_right ? 1 : -1) * Math.sign(nx) : want_right ? -1 : 1;
258
243
  }
244
+ perp_x = sign * nx * gap;
245
+ perp_y = sign * ny * gap;
259
246
  }
260
247
  const final_x = base_x + perp_x + offset_x;
261
248
  const final_y = base_y + perp_y + offset_y;
@@ -1,5 +1,5 @@
1
- import type { D3ColorSchemeName, D3InterpolateName } from '../colors';
2
- import type { Point, ScaleType, TimeInterval } from './';
1
+ import type { D3ColorSchemeName, D3InterpolateName } from '../../colors';
2
+ import type { Point, ScaleType, TimeInterval } from '..';
3
3
  import type { ScaleContinuousNumeric, ScaleTime } from 'd3-scale';
4
4
  export type TicksOption = number | number[] | TimeInterval | Record<number, string>;
5
5
  export interface ArcsinhScale {
@@ -1,5 +1,5 @@
1
- import * as math from '../math';
2
- import { get_arcsinh_threshold, get_scale_type_name, is_time_scale } from './types';
1
+ import * as math from '../../math';
2
+ import { get_arcsinh_threshold, get_scale_type_name, is_time_scale, } from './types';
3
3
  import { extent, range } from 'd3-array';
4
4
  import { scaleLinear, scaleLog, scaleSequential, scaleSequentialLog, scaleTime, } from 'd3-scale';
5
5
  import * as d3_sc from 'd3-scale-chromatic';
@@ -83,9 +83,8 @@ export function scale_arcsinh(threshold = 1) {
83
83
  return scale;
84
84
  }
85
85
  // Generate nice tick values for arcsinh scale
86
- // Strategy: symmetric around zero when possible, with powers of 10 for large values
87
- // Note: For small count values (1 or 2) on mixed ranges, zero takes priority as the
88
- // most important tick. E.g., count=1 yields [0], count=2 yields [0] plus one boundary.
86
+ // Strategy: symmetric around zero when possible, with powers of 10 for large values.
87
+ // On mixed ranges, count=1 yields just [0]; count>=2 yields zero plus symmetric powers per side.
89
88
  export function generate_arcsinh_ticks(min, max, threshold = 1, count = 10) {
90
89
  // Guard against invalid/non-positive threshold to prevent division issues
91
90
  const safe_threshold = Math.max(threshold, Number.EPSILON);
@@ -101,9 +100,10 @@ export function generate_arcsinh_ticks(min, max, threshold = 1, count = 10) {
101
100
  .map((tick) => -tick)
102
101
  .toReversed();
103
102
  }
104
- // Mixed range: symmetric ticks around zero (includes_zero is always true here)
105
- // For very small counts, we prioritize zero as the most meaningful tick
106
- const half_count = Math.floor((count - 1) / 2);
103
+ // Mixed range: symmetric ticks around zero (includes_zero is always here). Split the budget
104
+ // across both sides (zero is shared/free) so e.g. count=4 yields ~5 ticks (0, ±a, ±b) rather
105
+ // than collapsing to 3 matching how linear/log colorbars render a similar count.
106
+ const half_count = Math.floor(count / 2);
107
107
  const ticks = [0];
108
108
  // Add positive ticks
109
109
  const pos_ticks = generate_positive_arcsinh_ticks(0, hi, safe_threshold, half_count);
@@ -111,19 +111,6 @@ export function generate_arcsinh_ticks(min, max, threshold = 1, count = 10) {
111
111
  // Add negative ticks (mirror of positive)
112
112
  const neg_ticks = generate_positive_arcsinh_ticks(0, -lo, safe_threshold, half_count);
113
113
  ticks.push(...neg_ticks.filter((tick) => tick > 0).map((tick) => -tick));
114
- // For small counts where half_count is 0 or 1, ensure at least some boundary coverage
115
- if (half_count <= 1 && count >= 2) {
116
- // Add boundaries if not already present and we have room
117
- const sorted = dedupe_sort(ticks);
118
- if (sorted.length < count) {
119
- // Snap the larger-magnitude boundary to a clean power of 10 (raw extremes would render
120
- // as long unrounded labels); keeps some coverage for very small tick counts.
121
- const boundary = Math.abs(hi) >= Math.abs(lo) ? hi : lo;
122
- const nice = Math.sign(boundary) * 10 ** Math.floor(Math.log10(Math.abs(boundary)));
123
- if (Number.isFinite(nice) && nice !== 0 && !sorted.includes(nice))
124
- ticks.push(nice);
125
- }
126
- }
127
114
  return dedupe_sort(ticks);
128
115
  }
129
116
  // Generate positive arcsinh ticks (helper)
@@ -133,46 +120,49 @@ function generate_positive_arcsinh_ticks(min, max, threshold, count) {
133
120
  if (count <= 0 || max <= min)
134
121
  return [];
135
122
  const ticks = [];
136
- // For values near threshold, use linear-like spacing
137
- // For values >> threshold, use log-like spacing (powers of 10)
123
+ // Small range near threshold: use linear-like spacing
138
124
  if (max <= threshold * 2) {
139
- // Small range: use linear ticks
140
125
  const step = (max - min) / count;
141
126
  for (let idx = 0; idx <= count; idx++) {
142
127
  const val = min + step * idx;
143
128
  if (val >= min && val <= max)
144
129
  ticks.push(val);
145
130
  }
131
+ return dedupe_sort(ticks);
146
132
  }
147
- else {
148
- // Large range: combine linear near zero with powers of 10.
149
- // Domain endpoints are intentionally NOT added as ticks: raw extremes render as long
150
- // unrounded labels (e.g. 1325.8239811994677). Powers of 10 plus 2x/5x multiples below
151
- // already give clean round ticks; pass axis.ticks/axis.format for custom labels.
152
- // Add threshold as a tick if in range
153
- if (threshold >= min && threshold <= max)
154
- ticks.push(threshold);
155
- // Add powers of 10 that are in range
156
- const min_power = Math.floor(Math.log10(Math.max(min, threshold / 10)));
157
- const max_power = Math.ceil(Math.log10(max));
158
- for (let power = min_power; power <= max_power; power++) {
159
- const val = Math.pow(10, power);
160
- if (val >= min && val <= max)
161
- ticks.push(val);
162
- }
163
- // Add intermediate values (2x, 5x) for sparser regions
164
- if (ticks.length < count) {
165
- for (let power = min_power; power < max_power; power++) {
166
- const base = Math.pow(10, power);
167
- for (const mult of [2, 5]) {
168
- const val = base * mult;
169
- if (val >= min && val <= max)
170
- ticks.push(val);
171
- }
133
+ // Large range: log-like spacing via powers of 10.
134
+ // Domain endpoints are intentionally NOT added as ticks: raw extremes render as long
135
+ // unrounded labels (e.g. 1325.8239811994677). Powers of 10 plus 2x/5x multiples below
136
+ // already give clean round ticks; pass axis.ticks/axis.format for custom labels.
137
+ // Add threshold as a tick if in range
138
+ if (threshold >= min && threshold <= max)
139
+ ticks.push(threshold);
140
+ // Add powers of 10 that are in range. Start at the threshold (not a decade below): values
141
+ // below it sit in arcsinh's near-linear region and map almost onto 0, so sub-threshold powers
142
+ // (e.g. ±1 when threshold=10) would pile up on the zero tick and overlap.
143
+ const min_power = Math.floor(Math.log10(Math.max(min, threshold)));
144
+ const max_power = Math.ceil(Math.log10(max));
145
+ for (let power = min_power; power <= max_power; power++) {
146
+ const val = 10 ** power;
147
+ if (val >= min && val <= max)
148
+ ticks.push(val);
149
+ }
150
+ // Add intermediate values (2x, 5x) for sparser regions
151
+ if (ticks.length < count) {
152
+ for (let power = min_power; power < max_power; power++) {
153
+ const base = 10 ** power;
154
+ for (const mult of [2, 5]) {
155
+ const val = base * mult;
156
+ if (val >= min && val <= max)
157
+ ticks.push(val);
172
158
  }
173
159
  }
174
160
  }
175
- return dedupe_sort(ticks);
161
+ const result = dedupe_sort(ticks);
162
+ // Respect `count`: surplus small powers sit near zero in arcsinh space (their values map almost
163
+ // onto 0) and crowd the labels. Keep the largest-magnitude ticks — they anchor the range extent
164
+ // and are the most spread out — dropping near-zero ones first.
165
+ return result.length > count ? result.slice(-count) : result;
176
166
  }
177
167
  // Create a scale function based on type, domain, and range
178
168
  // Note: Time scales are handled separately via create_time_scale() since ScaleTime
@@ -182,8 +172,13 @@ export function create_scale(scale_type, domain, output_range) {
182
172
  const [min_val, max_val] = domain;
183
173
  const type_name = get_scale_type_name(scale_type);
184
174
  if (type_name === `log`) {
175
+ // Clamp BOTH ends to the positive floor: panning shifts ranges linearly, so a
176
+ // log axis panned past zero can arrive with max <= 0 — an unclamped max makes
177
+ // every scale output (and invert) NaN, blanking the chart and polluting axis
178
+ // ranges. A clamped degenerate domain just renders flat and stays recoverable.
179
+ const lo = Math.max(min_val, math.LOG_EPS);
185
180
  return scaleLog()
186
- .domain([Math.max(min_val, math.LOG_EPS), max_val])
181
+ .domain([lo, Math.max(max_val, lo)])
187
182
  .range(output_range);
188
183
  }
189
184
  if (type_name === `arcsinh`) {
@@ -284,15 +279,15 @@ export function get_nice_data_range(points, get_value, limits, scale_type, paddi
284
279
  const span = data_max - data_min;
285
280
  if (is_time) {
286
281
  const padding_ms = span * padding_factor;
287
- data_min = data_min - padding_ms;
288
- data_max = data_max + padding_ms;
282
+ data_min -= padding_ms;
283
+ data_max += padding_ms;
289
284
  }
290
285
  else if (type_name === `log`) {
291
286
  const log_min = Math.log10(Math.max(data_min, math.LOG_EPS));
292
287
  const log_max = Math.log10(Math.max(data_max, math.LOG_EPS));
293
288
  const log_span = log_max - log_min;
294
- data_min = Math.pow(10, log_min - log_span * padding_factor);
295
- data_max = Math.pow(10, log_max + log_span * padding_factor);
289
+ data_min = 10 ** (log_min - log_span * padding_factor);
290
+ data_max = 10 ** (log_max + log_span * padding_factor);
296
291
  }
297
292
  else if (type_name === `arcsinh`) {
298
293
  // Arcsinh: apply padding in arcsinh-transformed space
@@ -307,35 +302,33 @@ export function get_nice_data_range(points, get_value, limits, scale_type, paddi
307
302
  else {
308
303
  // Linear scale
309
304
  const padding_abs = span * padding_factor;
310
- data_min = data_min - padding_abs;
311
- data_max = data_max + padding_abs;
305
+ data_min -= padding_abs;
306
+ data_max += padding_abs;
312
307
  }
308
+ // Handle single data point case with fixed relative padding
309
+ }
310
+ else if (is_time) {
311
+ const one_day = 86_400_000; // milliseconds in a day
312
+ data_min -= one_day;
313
+ data_max += one_day;
314
+ }
315
+ else if (type_name === `log`) {
316
+ data_min = Math.max(math.LOG_EPS, data_min / 1.1); // 10% multiplicative padding
317
+ data_max *= 1.1;
318
+ }
319
+ else if (type_name === `arcsinh`) {
320
+ // Arcsinh: 10% padding in transformed space
321
+ // Guard against extremely small thresholds that could cause precision issues
322
+ const threshold = Math.max(get_arcsinh_threshold(scale_type), Number.EPSILON);
323
+ const asinh_val = Math.asinh(data_min / threshold);
324
+ const padding = Math.abs(asinh_val) * 0.1 || 0.1; // Use 0.1 if transformed value is 0 (i.e. data_min = 0)
325
+ data_min = Math.sinh(asinh_val - padding) * threshold;
326
+ data_max = Math.sinh(asinh_val + padding) * threshold;
313
327
  }
314
328
  else {
315
- // Handle single data point case with fixed relative padding
316
- if (is_time) {
317
- const one_day = 86_400_000; // milliseconds in a day
318
- data_min = data_min - one_day;
319
- data_max = data_max + one_day;
320
- }
321
- else if (type_name === `log`) {
322
- data_min = Math.max(math.LOG_EPS, data_min / 1.1); // 10% multiplicative padding
323
- data_max = data_max * 1.1;
324
- }
325
- else if (type_name === `arcsinh`) {
326
- // Arcsinh: 10% padding in transformed space
327
- // Guard against extremely small thresholds that could cause precision issues
328
- const threshold = Math.max(get_arcsinh_threshold(scale_type), Number.EPSILON);
329
- const asinh_val = Math.asinh(data_min / threshold);
330
- const padding = Math.abs(asinh_val) * 0.1 || 0.1; // Use 0.1 if transformed value is 0 (i.e. data_min = 0)
331
- data_min = Math.sinh(asinh_val - padding) * threshold;
332
- data_max = Math.sinh(asinh_val + padding) * threshold;
333
- }
334
- else {
335
- const padding_abs = data_min === 0 ? 1 : Math.abs(data_min * 0.1); // 10% additive padding, or 1 if value is 0
336
- data_min = data_min - padding_abs;
337
- data_max = data_max + padding_abs;
338
- }
329
+ const padding_abs = data_min === 0 ? 1 : Math.abs(data_min * 0.1); // 10% additive padding, or 1 if value is 0
330
+ data_min -= padding_abs;
331
+ data_max += padding_abs;
339
332
  }
340
333
  }
341
334
  // If time or no range after padding, return the (potentially padded) domain directly
@@ -371,20 +364,26 @@ export function generate_log_ticks(min, max, ticks_option) {
371
364
  const range_size = max_power - min_power;
372
365
  const extended_min_power = range_size <= 2 ? min_power - 1 : min_power - Math.max(1, Math.floor(range_size / 4));
373
366
  const extended_max_power = range_size <= 2 ? max_power + 1 : max_power;
374
- const powers = range(extended_min_power, extended_max_power + 1).map((power) => Math.pow(10, power));
367
+ const powers = range(extended_min_power, extended_max_power + 1).map((power) => 10 ** power);
375
368
  // For narrow ranges, include intermediate values
376
369
  if (max_power - min_power < 3 && typeof ticks_option === `number` && ticks_option > 5) {
377
370
  const detailed_ticks = [];
378
371
  powers.forEach((power) => {
379
372
  detailed_ticks.push(power);
380
- if (power * 2 <= Math.pow(10, extended_max_power))
373
+ if (power * 2 <= 10 ** extended_max_power)
381
374
  detailed_ticks.push(power * 2);
382
- if (power * 5 <= Math.pow(10, extended_max_power))
375
+ if (power * 5 <= 10 ** extended_max_power)
383
376
  detailed_ticks.push(power * 5);
384
377
  });
385
378
  return detailed_ticks.filter((tick) => tick >= min && tick <= max);
386
379
  }
387
- return powers.filter((power) => power >= min && power <= max);
380
+ const filtered_powers = powers.filter((power) => power >= min && power <= max);
381
+ if (filtered_powers.length >= 2)
382
+ return filtered_powers;
383
+ // Sub-decade domains (e.g. after zoom) have <2 powers of 10 — use d3's mantissa log ticks
384
+ const tick_count = typeof ticks_option === `number` && ticks_option > 0 ? ticks_option : 5;
385
+ const fallback = scaleLog().domain([min, max]).ticks(tick_count);
386
+ return fallback.length > 0 ? fallback : filtered_powers;
388
387
  }
389
388
  // Get custom label for a tick value if provided, otherwise return null
390
389
  export function get_tick_label(tick_value, ticks_option) {
@@ -0,0 +1,2 @@
1
+ export declare function violin_path(grid_px: readonly number[], half_offsets_px: readonly number[], center: number, side: `both` | `positive` | `negative`, orient: (cross: number, val: number) => [number, number]): string;
2
+ export declare function bar_path(x: number, y: number, w: number, h: number, r: number, vertical?: boolean): string;