matterviz 0.3.4 → 0.3.6

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 (852) hide show
  1. package/.vscode/launch.json +13 -0
  2. package/.vscodeignore +7 -0
  3. package/dist/assets/STLExporter-BpTH3YHE.js +8 -0
  4. package/dist/assets/browser-DdDecX_W.js +1 -0
  5. package/dist/assets/export-qgn-H9y6.js +2 -0
  6. package/dist/assets/main-DiKYzti2.css +1 -0
  7. package/dist/assets/moyo_wasm_bg-0ocwg7xY.wasm +0 -0
  8. package/dist/extension.js +31293 -0
  9. package/dist/src/lib/FilePicker.svelte +360 -0
  10. package/dist/src/lib/MillerIndexInput.svelte +66 -0
  11. package/dist/src/lib/api/mp.ts +26 -0
  12. package/dist/src/lib/api/optimade.ts +204 -0
  13. package/dist/src/lib/app.css +247 -0
  14. package/dist/src/lib/brillouin/BrillouinZone.svelte +549 -0
  15. package/dist/src/lib/brillouin/BrillouinZoneControls.svelte +144 -0
  16. package/dist/src/lib/brillouin/BrillouinZoneExportPane.svelte +146 -0
  17. package/dist/src/lib/brillouin/BrillouinZoneInfoPane.svelte +146 -0
  18. package/dist/src/lib/brillouin/BrillouinZoneScene.svelte +476 -0
  19. package/dist/src/lib/brillouin/BrillouinZoneTooltip.svelte +92 -0
  20. package/dist/src/lib/brillouin/compute.ts +529 -0
  21. package/dist/src/lib/brillouin/index.ts +8 -0
  22. package/dist/src/lib/brillouin/types.ts +51 -0
  23. package/dist/src/lib/chempot-diagram/ChemPotDiagram.svelte +327 -0
  24. package/dist/src/lib/chempot-diagram/ChemPotDiagram2D.svelte +846 -0
  25. package/dist/src/lib/chempot-diagram/ChemPotDiagram3D.svelte +3193 -0
  26. package/dist/src/lib/chempot-diagram/async-compute.svelte.ts +94 -0
  27. package/dist/src/lib/chempot-diagram/chempot-worker.ts +11 -0
  28. package/dist/src/lib/chempot-diagram/color.ts +42 -0
  29. package/dist/src/lib/chempot-diagram/compute.ts +1014 -0
  30. package/dist/src/lib/chempot-diagram/index.ts +6 -0
  31. package/dist/src/lib/chempot-diagram/pointer.ts +56 -0
  32. package/dist/src/lib/chempot-diagram/temperature.ts +77 -0
  33. package/dist/src/lib/chempot-diagram/types.ts +130 -0
  34. package/dist/src/lib/colors/index.ts +249 -0
  35. package/dist/src/lib/composition/BarChart.svelte +297 -0
  36. package/dist/src/lib/composition/BubbleChart.svelte +218 -0
  37. package/dist/src/lib/composition/Composition.svelte +165 -0
  38. package/dist/src/lib/composition/Formula.svelte +268 -0
  39. package/dist/src/lib/composition/FormulaFilter.svelte +1257 -0
  40. package/dist/src/lib/composition/PieChart.svelte +323 -0
  41. package/dist/src/lib/composition/format.ts +155 -0
  42. package/dist/src/lib/composition/index.ts +37 -0
  43. package/dist/src/lib/composition/parse.ts +605 -0
  44. package/dist/src/lib/constants.ts +134 -0
  45. package/dist/src/lib/controls.ts +42 -0
  46. package/dist/src/lib/convex-hull/ConvexHull.svelte +157 -0
  47. package/dist/src/lib/convex-hull/ConvexHull2D.svelte +825 -0
  48. package/dist/src/lib/convex-hull/ConvexHull3D.svelte +1801 -0
  49. package/dist/src/lib/convex-hull/ConvexHull4D.svelte +1398 -0
  50. package/dist/src/lib/convex-hull/ConvexHullControls.svelte +535 -0
  51. package/dist/src/lib/convex-hull/ConvexHullInfoPane.svelte +125 -0
  52. package/dist/src/lib/convex-hull/ConvexHullStats.svelte +929 -0
  53. package/dist/src/lib/convex-hull/ConvexHullTooltip.svelte +131 -0
  54. package/dist/src/lib/convex-hull/GasPressureControls.svelte +247 -0
  55. package/dist/src/lib/convex-hull/StructurePopup.svelte +151 -0
  56. package/dist/src/lib/convex-hull/TemperatureSlider.svelte +140 -0
  57. package/dist/src/lib/convex-hull/barycentric-coords.ts +246 -0
  58. package/dist/src/lib/convex-hull/demo-temperature.ts +63 -0
  59. package/dist/src/lib/convex-hull/gas-thermodynamics.ts +405 -0
  60. package/dist/src/lib/convex-hull/helpers.ts +932 -0
  61. package/dist/src/lib/convex-hull/index.ts +202 -0
  62. package/dist/src/lib/convex-hull/thermodynamics.ts +2192 -0
  63. package/dist/src/lib/convex-hull/types.ts +267 -0
  64. package/dist/src/lib/coordination/CoordinationBarPlot.svelte +311 -0
  65. package/dist/src/lib/coordination/calc-coordination.ts +93 -0
  66. package/dist/src/lib/coordination/index.ts +9 -0
  67. package/dist/src/lib/effects.svelte.ts +48 -0
  68. package/dist/src/lib/element/BohrAtom.svelte +147 -0
  69. package/dist/src/lib/element/ElementHeading.svelte +26 -0
  70. package/dist/src/lib/element/ElementPhoto.svelte +57 -0
  71. package/dist/src/lib/element/ElementStats.svelte +80 -0
  72. package/dist/src/lib/element/ElementTile.svelte +484 -0
  73. package/dist/src/lib/element/data.json.gz.d.ts +4 -0
  74. package/dist/src/lib/element/data.ts +14 -0
  75. package/dist/src/lib/element/index.ts +8 -0
  76. package/dist/src/lib/element/types.ts +62 -0
  77. package/dist/src/lib/feedback/ClickFeedback.svelte +58 -0
  78. package/dist/src/lib/feedback/DragOverlay.svelte +42 -0
  79. package/dist/src/lib/feedback/index.ts +4 -0
  80. package/dist/src/lib/fermi-surface/FermiSlice.svelte +189 -0
  81. package/dist/src/lib/fermi-surface/FermiSurface.svelte +600 -0
  82. package/dist/src/lib/fermi-surface/FermiSurfaceControls.svelte +448 -0
  83. package/dist/src/lib/fermi-surface/FermiSurfaceScene.svelte +794 -0
  84. package/dist/src/lib/fermi-surface/FermiSurfaceTooltip.svelte +111 -0
  85. package/dist/src/lib/fermi-surface/compute.ts +728 -0
  86. package/dist/src/lib/fermi-surface/constants.ts +32 -0
  87. package/dist/src/lib/fermi-surface/export.ts +64 -0
  88. package/dist/src/lib/fermi-surface/index.ts +14 -0
  89. package/dist/src/lib/fermi-surface/marching-cubes.ts +3 -0
  90. package/dist/src/lib/fermi-surface/parse.ts +574 -0
  91. package/dist/src/lib/fermi-surface/symmetry.ts +56 -0
  92. package/dist/src/lib/fermi-surface/types.ts +159 -0
  93. package/dist/src/lib/heatmap-matrix/HeatmapMatrix.svelte +1545 -0
  94. package/dist/src/lib/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
  95. package/dist/src/lib/heatmap-matrix/index.ts +167 -0
  96. package/dist/src/lib/heatmap-matrix/shared.ts +7 -0
  97. package/dist/src/lib/icons.ts +650 -0
  98. package/dist/src/lib/index.ts +61 -0
  99. package/dist/src/lib/io/decompress.ts +92 -0
  100. package/dist/src/lib/io/export.ts +385 -0
  101. package/dist/src/lib/io/fetch.ts +46 -0
  102. package/dist/src/lib/io/file-drop.ts +51 -0
  103. package/dist/src/lib/io/index.ts +7 -0
  104. package/dist/src/lib/io/is-binary.ts +24 -0
  105. package/dist/src/lib/io/types.ts +8 -0
  106. package/dist/src/lib/io/url-drop.ts +141 -0
  107. package/dist/src/lib/isosurface/Isosurface.svelte +285 -0
  108. package/dist/src/lib/isosurface/IsosurfaceControls.svelte +277 -0
  109. package/dist/src/lib/isosurface/index.ts +7 -0
  110. package/dist/src/lib/isosurface/parse.ts +656 -0
  111. package/dist/src/lib/isosurface/slice.ts +175 -0
  112. package/dist/src/lib/isosurface/types.ts +309 -0
  113. package/dist/src/lib/labels.ts +320 -0
  114. package/dist/src/lib/layout/FullscreenToggle.svelte +50 -0
  115. package/dist/src/lib/layout/InfoCard.svelte +120 -0
  116. package/dist/src/lib/layout/InfoTag.svelte +185 -0
  117. package/dist/src/lib/layout/PropertyFilter.svelte +246 -0
  118. package/dist/src/lib/layout/SettingsSection.svelte +148 -0
  119. package/dist/src/lib/layout/SubpageGrid.svelte +82 -0
  120. package/dist/src/lib/layout/fullscreen.ts +65 -0
  121. package/dist/src/lib/layout/index.ts +11 -0
  122. package/dist/src/lib/layout/json-tree/JsonNode.svelte +548 -0
  123. package/dist/src/lib/layout/json-tree/JsonTree.svelte +1230 -0
  124. package/dist/src/lib/layout/json-tree/JsonValue.svelte +334 -0
  125. package/dist/src/lib/layout/json-tree/index.ts +3 -0
  126. package/dist/src/lib/layout/json-tree/types.ts +126 -0
  127. package/dist/src/lib/layout/json-tree/utils.ts +682 -0
  128. package/dist/src/lib/marching-cubes.ts +614 -0
  129. package/dist/src/lib/math.ts +1081 -0
  130. package/dist/src/lib/overlays/ContextMenu.svelte +162 -0
  131. package/dist/src/lib/overlays/CopyButton.svelte +45 -0
  132. package/dist/src/lib/overlays/DragControlTab.svelte +98 -0
  133. package/dist/src/lib/overlays/DraggablePane.svelte +487 -0
  134. package/dist/src/lib/overlays/InfoPaneCards.svelte +149 -0
  135. package/dist/src/lib/overlays/index.ts +3 -0
  136. package/dist/src/lib/periodic-table/PeriodicTable.svelte +469 -0
  137. package/dist/src/lib/periodic-table/PeriodicTableControls.svelte +557 -0
  138. package/dist/src/lib/periodic-table/PropertySelect.svelte +37 -0
  139. package/dist/src/lib/periodic-table/index.ts +12 -0
  140. package/dist/src/lib/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +1086 -0
  141. package/dist/src/lib/phase-diagram/PhaseDiagramControls.svelte +444 -0
  142. package/dist/src/lib/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
  143. package/dist/src/lib/phase-diagram/PhaseDiagramExportPane.svelte +184 -0
  144. package/dist/src/lib/phase-diagram/PhaseDiagramTooltip.svelte +391 -0
  145. package/dist/src/lib/phase-diagram/TdbInfoPanel.svelte +203 -0
  146. package/dist/src/lib/phase-diagram/build-diagram.ts +186 -0
  147. package/dist/src/lib/phase-diagram/colors.ts +58 -0
  148. package/dist/src/lib/phase-diagram/diagram-input.ts +40 -0
  149. package/dist/src/lib/phase-diagram/index.ts +13 -0
  150. package/dist/src/lib/phase-diagram/parse.ts +348 -0
  151. package/dist/src/lib/phase-diagram/svg-to-diagram.ts +1023 -0
  152. package/dist/src/lib/phase-diagram/types.ts +144 -0
  153. package/dist/src/lib/phase-diagram/utils.ts +775 -0
  154. package/dist/src/lib/plot/AxisLabel.svelte +51 -0
  155. package/dist/src/lib/plot/BarPlot.svelte +2113 -0
  156. package/dist/src/lib/plot/BarPlotControls.svelte +66 -0
  157. package/dist/src/lib/plot/BinnedScatterPlot.svelte +1114 -0
  158. package/dist/src/lib/plot/ColorBar.svelte +721 -0
  159. package/dist/src/lib/plot/ColorScaleSelect.svelte +54 -0
  160. package/dist/src/lib/plot/ElementScatter.svelte +63 -0
  161. package/dist/src/lib/plot/FillArea.svelte +223 -0
  162. package/dist/src/lib/plot/Histogram.svelte +1558 -0
  163. package/dist/src/lib/plot/HistogramControls.svelte +212 -0
  164. package/dist/src/lib/plot/InteractiveAxisLabel.svelte +96 -0
  165. package/dist/src/lib/plot/Line.svelte +84 -0
  166. package/dist/src/lib/plot/PlotAxis.svelte +169 -0
  167. package/dist/src/lib/plot/PlotControls.svelte +537 -0
  168. package/dist/src/lib/plot/PlotLegend.svelte +569 -0
  169. package/dist/src/lib/plot/PlotTooltip.svelte +67 -0
  170. package/dist/src/lib/plot/PortalSelect.svelte +253 -0
  171. package/dist/src/lib/plot/ReferenceLine3D.svelte +156 -0
  172. package/dist/src/lib/plot/ReferencePlane.svelte +175 -0
  173. package/dist/src/lib/plot/ScatterPlot.svelte +2778 -0
  174. package/dist/src/lib/plot/ScatterPlot3D.svelte +529 -0
  175. package/dist/src/lib/plot/ScatterPlot3DControls.svelte +437 -0
  176. package/dist/src/lib/plot/ScatterPlot3DScene.svelte +912 -0
  177. package/dist/src/lib/plot/ScatterPlotControls.svelte +306 -0
  178. package/dist/src/lib/plot/ScatterPoint.svelte +182 -0
  179. package/dist/src/lib/plot/SpacegroupBarPlot.svelte +293 -0
  180. package/dist/src/lib/plot/Surface3D.svelte +197 -0
  181. package/dist/src/lib/plot/ZeroLines.svelte +97 -0
  182. package/dist/src/lib/plot/ZoomRect.svelte +23 -0
  183. package/dist/src/lib/plot/adaptive-density.ts +316 -0
  184. package/dist/src/lib/plot/auto-place.ts +184 -0
  185. package/dist/src/lib/plot/axis-utils.ts +122 -0
  186. package/dist/src/lib/plot/binned-scatter-types.ts +83 -0
  187. package/dist/src/lib/plot/data-cleaning.ts +1069 -0
  188. package/dist/src/lib/plot/data-transform.ts +69 -0
  189. package/dist/src/lib/plot/defaults.ts +9 -0
  190. package/dist/src/lib/plot/fill-utils.ts +494 -0
  191. package/dist/src/lib/plot/hover-lock.svelte.ts +60 -0
  192. package/dist/src/lib/plot/index.ts +53 -0
  193. package/dist/src/lib/plot/interactions.ts +119 -0
  194. package/dist/src/lib/plot/layout.ts +425 -0
  195. package/dist/src/lib/plot/reference-line.ts +426 -0
  196. package/dist/src/lib/plot/scales.ts +654 -0
  197. package/dist/src/lib/plot/svg.ts +23 -0
  198. package/dist/src/lib/plot/types.ts +1144 -0
  199. package/dist/src/lib/plot/utils/label-placement.ts +541 -0
  200. package/dist/src/lib/plot/utils/series-visibility.ts +140 -0
  201. package/dist/src/lib/plot/utils.ts +11 -0
  202. package/dist/src/lib/rdf/RdfPlot.svelte +247 -0
  203. package/dist/src/lib/rdf/calc-rdf.ts +167 -0
  204. package/dist/src/lib/rdf/index.ts +27 -0
  205. package/dist/src/lib/sanitize.ts +126 -0
  206. package/dist/src/lib/settings.ts +1479 -0
  207. package/dist/src/lib/spectral/Bands.svelte +1040 -0
  208. package/dist/src/lib/spectral/BandsAndDos.svelte +134 -0
  209. package/dist/src/lib/spectral/BrillouinBandsDos.svelte +252 -0
  210. package/dist/src/lib/spectral/Dos.svelte +697 -0
  211. package/dist/src/lib/spectral/helpers.ts +1381 -0
  212. package/dist/src/lib/spectral/index.ts +8 -0
  213. package/dist/src/lib/spectral/types.ts +112 -0
  214. package/dist/src/lib/state.svelte.ts +64 -0
  215. package/dist/src/lib/structure/Arrow.svelte +72 -0
  216. package/dist/src/lib/structure/AtomLegend.svelte +815 -0
  217. package/dist/src/lib/structure/Bond.svelte +140 -0
  218. package/dist/src/lib/structure/CanvasTooltip.svelte +33 -0
  219. package/dist/src/lib/structure/CellSelect.svelte +349 -0
  220. package/dist/src/lib/structure/Cylinder.svelte +45 -0
  221. package/dist/src/lib/structure/Lattice.svelte +196 -0
  222. package/dist/src/lib/structure/Structure.svelte +2248 -0
  223. package/dist/src/lib/structure/StructureControls.svelte +1273 -0
  224. package/dist/src/lib/structure/StructureExportPane.svelte +252 -0
  225. package/dist/src/lib/structure/StructureInfoPane.svelte +737 -0
  226. package/dist/src/lib/structure/StructureScene.svelte +2255 -0
  227. package/dist/src/lib/structure/atom-properties.ts +316 -0
  228. package/dist/src/lib/structure/bond-order-perception.ts +447 -0
  229. package/dist/src/lib/structure/bonding.ts +944 -0
  230. package/dist/src/lib/structure/export.ts +861 -0
  231. package/dist/src/lib/structure/index.ts +291 -0
  232. package/dist/src/lib/structure/label-placement.ts +130 -0
  233. package/dist/src/lib/structure/measure.ts +45 -0
  234. package/dist/src/lib/structure/parse.ts +1705 -0
  235. package/dist/src/lib/structure/partial-occupancy.ts +183 -0
  236. package/dist/src/lib/structure/pbc.ts +164 -0
  237. package/dist/src/lib/structure/supercell.ts +226 -0
  238. package/dist/src/lib/structure/validation.ts +11 -0
  239. package/dist/src/lib/symmetry/SymmetryStats.svelte +226 -0
  240. package/dist/src/lib/symmetry/WyckoffTable.svelte +120 -0
  241. package/dist/src/lib/symmetry/cell-transform.ts +118 -0
  242. package/dist/src/lib/symmetry/index.ts +348 -0
  243. package/dist/src/lib/symmetry/spacegroups.ts +404 -0
  244. package/dist/src/lib/table/HeatmapTable.svelte +1833 -0
  245. package/dist/src/lib/table/ToggleMenu.svelte +385 -0
  246. package/dist/src/lib/table/index.ts +139 -0
  247. package/dist/src/lib/theme/ThemeControl.svelte +53 -0
  248. package/dist/src/lib/theme/index.ts +107 -0
  249. package/dist/src/lib/theme/themes.mjs +297 -0
  250. package/dist/src/lib/time.ts +71 -0
  251. package/dist/src/lib/tooltip/TooltipContent.svelte +58 -0
  252. package/dist/src/lib/tooltip/index.ts +2 -0
  253. package/dist/src/lib/tooltip/types.ts +13 -0
  254. package/dist/src/lib/trajectory/Trajectory.svelte +1545 -0
  255. package/dist/src/lib/trajectory/TrajectoryError.svelte +128 -0
  256. package/dist/src/lib/trajectory/TrajectoryExportPane.svelte +357 -0
  257. package/dist/src/lib/trajectory/TrajectoryInfoPane.svelte +313 -0
  258. package/dist/src/lib/trajectory/constants.ts +7 -0
  259. package/dist/src/lib/trajectory/extract.ts +196 -0
  260. package/dist/src/lib/trajectory/format-detect.ts +96 -0
  261. package/dist/src/lib/trajectory/frame-reader.ts +456 -0
  262. package/dist/src/lib/trajectory/helpers.ts +217 -0
  263. package/dist/src/lib/trajectory/index.ts +218 -0
  264. package/dist/src/lib/trajectory/parse/ase.ts +109 -0
  265. package/dist/src/lib/trajectory/parse/hdf5.ts +173 -0
  266. package/dist/src/lib/trajectory/parse/index.ts +411 -0
  267. package/dist/src/lib/trajectory/parse/lammps.ts +215 -0
  268. package/dist/src/lib/trajectory/parse/vasp.ts +102 -0
  269. package/dist/src/lib/trajectory/parse/xyz.ts +143 -0
  270. package/dist/src/lib/trajectory/plotting.ts +599 -0
  271. package/dist/src/lib/trajectory/types.ts +13 -0
  272. package/dist/src/lib/utils.ts +56 -0
  273. package/dist/src/lib/xrd/XrdPlot.svelte +615 -0
  274. package/dist/src/lib/xrd/broadening.ts +130 -0
  275. package/dist/src/lib/xrd/calc-xrd.ts +397 -0
  276. package/dist/src/lib/xrd/index.ts +38 -0
  277. package/dist/src/lib/xrd/parse.ts +858 -0
  278. package/dist/webview.js +29421 -0
  279. package/icon.png +0 -0
  280. package/license +1 -1
  281. package/matterviz-0.3.2.vsix +0 -0
  282. package/matterviz-0.3.4.vsix +0 -0
  283. package/matterviz-0.3.5.vsix +0 -0
  284. package/package.json +1461 -231
  285. package/readme.md +171 -98
  286. package/scripts/sync-config.ts +101 -0
  287. package/src/declarations.d.ts +2 -0
  288. package/src/extension.ts +972 -0
  289. package/src/node-io.ts +65 -0
  290. package/src/types.ts +17 -0
  291. package/src/webview/JsonBrowser.svelte +1079 -0
  292. package/src/webview/PlotPanel.svelte +346 -0
  293. package/src/webview/detect.ts +444 -0
  294. package/src/webview/main.ts +764 -0
  295. package/src/webview/plot-utils.ts +250 -0
  296. package/test-fixtures/all-viz-types.json.gz +0 -0
  297. package/test-fixtures/plot-demo-data.json.gz +0 -0
  298. package/tests/detect.test.ts +604 -0
  299. package/tests/extension.test.ts +2041 -0
  300. package/tests/node-io.test.ts +39 -0
  301. package/tests/plot-utils.test.ts +302 -0
  302. package/tests/vite-plugin-json-gz.test.ts +114 -0
  303. package/tests/vscode-mock.ts +18 -0
  304. package/tests/webview.test.ts +231 -0
  305. package/tsconfig.json +20 -0
  306. package/vite-plugin-json-gz.ts +29 -0
  307. package/vite.config.ts +34 -0
  308. package/vite.extension.config.ts +34 -0
  309. package/dist/EmptyState.svelte.d.ts +0 -9
  310. package/dist/FilePicker.svelte +0 -360
  311. package/dist/FilePicker.svelte.d.ts +0 -17
  312. package/dist/Icon.svelte.d.ts +0 -13
  313. package/dist/MillerIndexInput.svelte +0 -66
  314. package/dist/MillerIndexInput.svelte.d.ts +0 -7
  315. package/dist/api/mp.d.ts +0 -6
  316. package/dist/api/mp.js +0 -22
  317. package/dist/api/optimade.d.ts +0 -45
  318. package/dist/api/optimade.js +0 -135
  319. package/dist/app.css +0 -240
  320. package/dist/brillouin/BrillouinZone.svelte +0 -543
  321. package/dist/brillouin/BrillouinZone.svelte.d.ts +0 -83
  322. package/dist/brillouin/BrillouinZoneControls.svelte +0 -144
  323. package/dist/brillouin/BrillouinZoneControls.svelte.d.ts +0 -17
  324. package/dist/brillouin/BrillouinZoneExportPane.svelte +0 -148
  325. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +0 -15
  326. package/dist/brillouin/BrillouinZoneInfoPane.svelte +0 -146
  327. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +0 -13
  328. package/dist/brillouin/BrillouinZoneScene.svelte +0 -476
  329. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +0 -48
  330. package/dist/brillouin/BrillouinZoneTooltip.svelte +0 -92
  331. package/dist/brillouin/BrillouinZoneTooltip.svelte.d.ts +0 -8
  332. package/dist/brillouin/compute.d.ts +0 -17
  333. package/dist/brillouin/compute.js +0 -422
  334. package/dist/brillouin/index.d.ts +0 -8
  335. package/dist/brillouin/index.js +0 -8
  336. package/dist/brillouin/types.d.ts +0 -48
  337. package/dist/brillouin/types.js +0 -1
  338. package/dist/chempot-diagram/ChemPotDiagram.svelte +0 -327
  339. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +0 -13
  340. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +0 -847
  341. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +0 -16
  342. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +0 -3194
  343. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +0 -16
  344. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +0 -7
  345. package/dist/chempot-diagram/async-compute.svelte.d.ts +0 -3
  346. package/dist/chempot-diagram/async-compute.svelte.js +0 -77
  347. package/dist/chempot-diagram/chempot-worker.d.ts +0 -1
  348. package/dist/chempot-diagram/chempot-worker.js +0 -11
  349. package/dist/chempot-diagram/color.d.ts +0 -10
  350. package/dist/chempot-diagram/color.js +0 -32
  351. package/dist/chempot-diagram/compute.d.ts +0 -48
  352. package/dist/chempot-diagram/compute.js +0 -812
  353. package/dist/chempot-diagram/index.d.ts +0 -6
  354. package/dist/chempot-diagram/index.js +0 -6
  355. package/dist/chempot-diagram/pointer.d.ts +0 -16
  356. package/dist/chempot-diagram/pointer.js +0 -40
  357. package/dist/chempot-diagram/temperature.d.ts +0 -15
  358. package/dist/chempot-diagram/temperature.js +0 -36
  359. package/dist/chempot-diagram/types.d.ts +0 -86
  360. package/dist/chempot-diagram/types.js +0 -28
  361. package/dist/colors/index.d.ts +0 -47
  362. package/dist/colors/index.js +0 -203
  363. package/dist/composition/BarChart.svelte +0 -297
  364. package/dist/composition/BarChart.svelte.d.ts +0 -39
  365. package/dist/composition/BubbleChart.svelte +0 -218
  366. package/dist/composition/BubbleChart.svelte.d.ts +0 -28
  367. package/dist/composition/Composition.svelte +0 -164
  368. package/dist/composition/Composition.svelte.d.ts +0 -15
  369. package/dist/composition/Formula.svelte +0 -265
  370. package/dist/composition/Formula.svelte.d.ts +0 -19
  371. package/dist/composition/FormulaFilter.svelte +0 -1259
  372. package/dist/composition/FormulaFilter.svelte.d.ts +0 -51
  373. package/dist/composition/PieChart.svelte +0 -323
  374. package/dist/composition/PieChart.svelte.d.ts +0 -37
  375. package/dist/composition/format.d.ts +0 -15
  376. package/dist/composition/format.js +0 -109
  377. package/dist/composition/index.d.ts +0 -20
  378. package/dist/composition/index.js +0 -14
  379. package/dist/composition/parse.d.ts +0 -55
  380. package/dist/composition/parse.js +0 -459
  381. package/dist/constants.d.ts +0 -29
  382. package/dist/constants.js +0 -105
  383. package/dist/controls.d.ts +0 -14
  384. package/dist/controls.js +0 -30
  385. package/dist/convex-hull/ConvexHull.svelte +0 -157
  386. package/dist/convex-hull/ConvexHull.svelte.d.ts +0 -13
  387. package/dist/convex-hull/ConvexHull2D.svelte +0 -813
  388. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +0 -11
  389. package/dist/convex-hull/ConvexHull3D.svelte +0 -1788
  390. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +0 -8
  391. package/dist/convex-hull/ConvexHull4D.svelte +0 -1374
  392. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +0 -8
  393. package/dist/convex-hull/ConvexHullControls.svelte +0 -546
  394. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +0 -48
  395. package/dist/convex-hull/ConvexHullInfoPane.svelte +0 -115
  396. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +0 -18
  397. package/dist/convex-hull/ConvexHullStats.svelte +0 -905
  398. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +0 -15
  399. package/dist/convex-hull/ConvexHullTooltip.svelte +0 -131
  400. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +0 -33
  401. package/dist/convex-hull/GasPressureControls.svelte +0 -247
  402. package/dist/convex-hull/GasPressureControls.svelte.d.ts +0 -11
  403. package/dist/convex-hull/StructurePopup.svelte +0 -116
  404. package/dist/convex-hull/StructurePopup.svelte.d.ts +0 -18
  405. package/dist/convex-hull/TemperatureSlider.svelte +0 -137
  406. package/dist/convex-hull/TemperatureSlider.svelte.d.ts +0 -8
  407. package/dist/convex-hull/barycentric-coords.d.ts +0 -18
  408. package/dist/convex-hull/barycentric-coords.js +0 -182
  409. package/dist/convex-hull/demo-temperature.d.ts +0 -6
  410. package/dist/convex-hull/demo-temperature.js +0 -40
  411. package/dist/convex-hull/gas-thermodynamics.d.ts +0 -16
  412. package/dist/convex-hull/gas-thermodynamics.js +0 -316
  413. package/dist/convex-hull/helpers.d.ts +0 -103
  414. package/dist/convex-hull/helpers.js +0 -671
  415. package/dist/convex-hull/index.d.ts +0 -118
  416. package/dist/convex-hull/index.js +0 -57
  417. package/dist/convex-hull/thermodynamics.d.ts +0 -66
  418. package/dist/convex-hull/thermodynamics.js +0 -1752
  419. package/dist/convex-hull/types.d.ts +0 -162
  420. package/dist/convex-hull/types.js +0 -36
  421. package/dist/coordination/CoordinationBarPlot.svelte +0 -311
  422. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +0 -30
  423. package/dist/coordination/calc-coordination.d.ts +0 -15
  424. package/dist/coordination/calc-coordination.js +0 -63
  425. package/dist/coordination/index.d.ts +0 -8
  426. package/dist/coordination/index.js +0 -7
  427. package/dist/element/BohrAtom.svelte +0 -149
  428. package/dist/element/BohrAtom.svelte.d.ts +0 -20
  429. package/dist/element/ElementHeading.svelte +0 -26
  430. package/dist/element/ElementHeading.svelte.d.ts +0 -8
  431. package/dist/element/ElementPhoto.svelte +0 -57
  432. package/dist/element/ElementPhoto.svelte.d.ts +0 -9
  433. package/dist/element/ElementStats.svelte +0 -80
  434. package/dist/element/ElementStats.svelte.d.ts +0 -8
  435. package/dist/element/ElementTile.svelte +0 -484
  436. package/dist/element/ElementTile.svelte.d.ts +0 -29
  437. package/dist/element/Nucleus.svelte.d.ts +0 -17
  438. package/dist/element/data.d.ts +0 -3
  439. package/dist/element/data.js +0 -2
  440. package/dist/element/data.json.gz.d.ts +0 -2
  441. package/dist/element/index.d.ts +0 -8
  442. package/dist/element/index.js +0 -8
  443. package/dist/element/types.d.ts +0 -57
  444. package/dist/element/types.js +0 -1
  445. package/dist/feedback/ClickFeedback.svelte +0 -58
  446. package/dist/feedback/ClickFeedback.svelte.d.ts +0 -12
  447. package/dist/feedback/DragOverlay.svelte +0 -42
  448. package/dist/feedback/DragOverlay.svelte.d.ts +0 -7
  449. package/dist/feedback/Spinner.svelte.d.ts +0 -7
  450. package/dist/feedback/StatusMessage.svelte.d.ts +0 -9
  451. package/dist/feedback/index.d.ts +0 -4
  452. package/dist/feedback/index.js +0 -4
  453. package/dist/fermi-surface/FermiSlice.svelte +0 -189
  454. package/dist/fermi-surface/FermiSlice.svelte.d.ts +0 -24
  455. package/dist/fermi-surface/FermiSurface.svelte +0 -597
  456. package/dist/fermi-surface/FermiSurface.svelte.d.ts +0 -83
  457. package/dist/fermi-surface/FermiSurfaceControls.svelte +0 -452
  458. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +0 -35
  459. package/dist/fermi-surface/FermiSurfaceScene.svelte +0 -792
  460. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +0 -50
  461. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +0 -111
  462. package/dist/fermi-surface/FermiSurfaceTooltip.svelte.d.ts +0 -8
  463. package/dist/fermi-surface/compute.d.ts +0 -5
  464. package/dist/fermi-surface/compute.js +0 -538
  465. package/dist/fermi-surface/constants.d.ts +0 -9
  466. package/dist/fermi-surface/constants.js +0 -27
  467. package/dist/fermi-surface/export.d.ts +0 -5
  468. package/dist/fermi-surface/export.js +0 -63
  469. package/dist/fermi-surface/index.d.ts +0 -12
  470. package/dist/fermi-surface/index.js +0 -13
  471. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  472. package/dist/fermi-surface/marching-cubes.js +0 -2
  473. package/dist/fermi-surface/parse.d.ts +0 -2
  474. package/dist/fermi-surface/parse.js +0 -495
  475. package/dist/fermi-surface/symmetry.d.ts +0 -3
  476. package/dist/fermi-surface/symmetry.js +0 -46
  477. package/dist/fermi-surface/types.d.ts +0 -113
  478. package/dist/fermi-surface/types.js +0 -4
  479. package/dist/heatmap-matrix/HeatmapMatrix.svelte +0 -1527
  480. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +0 -110
  481. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +0 -225
  482. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +0 -30
  483. package/dist/heatmap-matrix/index.d.ts +0 -53
  484. package/dist/heatmap-matrix/index.js +0 -100
  485. package/dist/heatmap-matrix/shared.d.ts +0 -2
  486. package/dist/heatmap-matrix/shared.js +0 -4
  487. package/dist/icons.d.ts +0 -569
  488. package/dist/icons.js +0 -648
  489. package/dist/index.d.ts +0 -39
  490. package/dist/index.js +0 -39
  491. package/dist/io/decompress.d.ts +0 -10
  492. package/dist/io/decompress.js +0 -69
  493. package/dist/io/export.d.ts +0 -16
  494. package/dist/io/export.js +0 -312
  495. package/dist/io/fetch.d.ts +0 -5
  496. package/dist/io/fetch.js +0 -39
  497. package/dist/io/file-drop.d.ts +0 -7
  498. package/dist/io/file-drop.js +0 -43
  499. package/dist/io/index.d.ts +0 -7
  500. package/dist/io/index.js +0 -7
  501. package/dist/io/is-binary.d.ts +0 -1
  502. package/dist/io/is-binary.js +0 -5
  503. package/dist/io/types.d.ts +0 -8
  504. package/dist/io/types.js +0 -1
  505. package/dist/io/url-drop.d.ts +0 -2
  506. package/dist/io/url-drop.js +0 -117
  507. package/dist/isosurface/Isosurface.svelte +0 -285
  508. package/dist/isosurface/Isosurface.svelte.d.ts +0 -8
  509. package/dist/isosurface/IsosurfaceControls.svelte +0 -291
  510. package/dist/isosurface/IsosurfaceControls.svelte.d.ts +0 -9
  511. package/dist/isosurface/index.d.ts +0 -5
  512. package/dist/isosurface/index.js +0 -6
  513. package/dist/isosurface/parse.d.ts +0 -6
  514. package/dist/isosurface/parse.js +0 -553
  515. package/dist/isosurface/slice.d.ts +0 -11
  516. package/dist/isosurface/slice.js +0 -140
  517. package/dist/isosurface/types.d.ts +0 -56
  518. package/dist/isosurface/types.js +0 -227
  519. package/dist/labels.d.ts +0 -53
  520. package/dist/labels.js +0 -274
  521. package/dist/layout/FullscreenToggle.svelte +0 -50
  522. package/dist/layout/FullscreenToggle.svelte.d.ts +0 -7
  523. package/dist/layout/InfoCard.svelte +0 -120
  524. package/dist/layout/InfoCard.svelte.d.ts +0 -21
  525. package/dist/layout/InfoTag.svelte +0 -183
  526. package/dist/layout/InfoTag.svelte.d.ts +0 -19
  527. package/dist/layout/PropertyFilter.svelte +0 -244
  528. package/dist/layout/PropertyFilter.svelte.d.ts +0 -24
  529. package/dist/layout/SettingsSection.svelte +0 -148
  530. package/dist/layout/SettingsSection.svelte.d.ts +0 -17
  531. package/dist/layout/SubpageGrid.svelte +0 -82
  532. package/dist/layout/SubpageGrid.svelte.d.ts +0 -14
  533. package/dist/layout/fullscreen.d.ts +0 -9
  534. package/dist/layout/fullscreen.js +0 -53
  535. package/dist/layout/index.d.ts +0 -10
  536. package/dist/layout/index.js +0 -8
  537. package/dist/layout/json-tree/JsonNode.svelte +0 -547
  538. package/dist/layout/json-tree/JsonNode.svelte.d.ts +0 -11
  539. package/dist/layout/json-tree/JsonTree.svelte +0 -1222
  540. package/dist/layout/json-tree/JsonTree.svelte.d.ts +0 -6
  541. package/dist/layout/json-tree/JsonValue.svelte +0 -334
  542. package/dist/layout/json-tree/JsonValue.svelte.d.ts +0 -9
  543. package/dist/layout/json-tree/index.d.ts +0 -3
  544. package/dist/layout/json-tree/index.js +0 -3
  545. package/dist/layout/json-tree/types.d.ts +0 -73
  546. package/dist/layout/json-tree/types.js +0 -3
  547. package/dist/layout/json-tree/utils.d.ts +0 -29
  548. package/dist/layout/json-tree/utils.js +0 -648
  549. package/dist/marching-cubes.d.ts +0 -14
  550. package/dist/marching-cubes.js +0 -542
  551. package/dist/math.d.ts +0 -91
  552. package/dist/math.js +0 -896
  553. package/dist/overlays/ContextMenu.svelte +0 -162
  554. package/dist/overlays/ContextMenu.svelte.d.ts +0 -25
  555. package/dist/overlays/DraggablePane.svelte +0 -564
  556. package/dist/overlays/DraggablePane.svelte.d.ts +0 -36
  557. package/dist/overlays/index.d.ts +0 -2
  558. package/dist/overlays/index.js +0 -2
  559. package/dist/periodic-table/PeriodicTable.svelte +0 -469
  560. package/dist/periodic-table/PeriodicTable.svelte.d.ts +0 -55
  561. package/dist/periodic-table/PeriodicTableControls.svelte +0 -557
  562. package/dist/periodic-table/PeriodicTableControls.svelte.d.ts +0 -24
  563. package/dist/periodic-table/PropertySelect.svelte +0 -37
  564. package/dist/periodic-table/PropertySelect.svelte.d.ts +0 -13
  565. package/dist/periodic-table/TableInset.svelte.d.ts +0 -9
  566. package/dist/periodic-table/index.d.ts +0 -10
  567. package/dist/periodic-table/index.js +0 -4
  568. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +0 -1086
  569. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +0 -44
  570. package/dist/phase-diagram/PhaseDiagramControls.svelte +0 -451
  571. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +0 -30
  572. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +0 -126
  573. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +0 -15
  574. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +0 -192
  575. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +0 -19
  576. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +0 -392
  577. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +0 -16
  578. package/dist/phase-diagram/TdbInfoPanel.svelte +0 -203
  579. package/dist/phase-diagram/TdbInfoPanel.svelte.d.ts +0 -12
  580. package/dist/phase-diagram/build-diagram.d.ts +0 -11
  581. package/dist/phase-diagram/build-diagram.js +0 -167
  582. package/dist/phase-diagram/colors.d.ts +0 -35
  583. package/dist/phase-diagram/colors.js +0 -51
  584. package/dist/phase-diagram/diagram-input.d.ts +0 -33
  585. package/dist/phase-diagram/diagram-input.js +0 -3
  586. package/dist/phase-diagram/index.d.ts +0 -13
  587. package/dist/phase-diagram/index.js +0 -13
  588. package/dist/phase-diagram/parse.d.ts +0 -55
  589. package/dist/phase-diagram/parse.js +0 -276
  590. package/dist/phase-diagram/svg-to-diagram.d.ts +0 -2
  591. package/dist/phase-diagram/svg-to-diagram.js +0 -869
  592. package/dist/phase-diagram/types.d.ts +0 -99
  593. package/dist/phase-diagram/types.js +0 -1
  594. package/dist/phase-diagram/utils.d.ts +0 -118
  595. package/dist/phase-diagram/utils.js +0 -606
  596. package/dist/plot/AxisLabel.svelte +0 -51
  597. package/dist/plot/AxisLabel.svelte.d.ts +0 -16
  598. package/dist/plot/BarPlot.svelte +0 -2256
  599. package/dist/plot/BarPlot.svelte.d.ts +0 -82
  600. package/dist/plot/BarPlotControls.svelte +0 -66
  601. package/dist/plot/BarPlotControls.svelte.d.ts +0 -18
  602. package/dist/plot/ColorBar.svelte +0 -719
  603. package/dist/plot/ColorBar.svelte.d.ts +0 -31
  604. package/dist/plot/ColorScaleSelect.svelte +0 -54
  605. package/dist/plot/ColorScaleSelect.svelte.d.ts +0 -15
  606. package/dist/plot/ElementScatter.svelte +0 -63
  607. package/dist/plot/ElementScatter.svelte.d.ts +0 -14
  608. package/dist/plot/FillArea.svelte +0 -226
  609. package/dist/plot/FillArea.svelte.d.ts +0 -20
  610. package/dist/plot/Histogram.svelte +0 -1654
  611. package/dist/plot/Histogram.svelte.d.ts +0 -50
  612. package/dist/plot/HistogramControls.svelte +0 -212
  613. package/dist/plot/HistogramControls.svelte.d.ts +0 -22
  614. package/dist/plot/InteractiveAxisLabel.svelte +0 -94
  615. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +0 -14
  616. package/dist/plot/Line.svelte +0 -85
  617. package/dist/plot/Line.svelte.d.ts +0 -15
  618. package/dist/plot/PlotControls.svelte +0 -537
  619. package/dist/plot/PlotControls.svelte.d.ts +0 -4
  620. package/dist/plot/PlotLegend.svelte +0 -498
  621. package/dist/plot/PlotLegend.svelte.d.ts +0 -25
  622. package/dist/plot/PlotTooltip.svelte +0 -67
  623. package/dist/plot/PlotTooltip.svelte.d.ts +0 -17
  624. package/dist/plot/PortalSelect.svelte +0 -253
  625. package/dist/plot/PortalSelect.svelte.d.ts +0 -16
  626. package/dist/plot/ReferenceLine.svelte.d.ts +0 -20
  627. package/dist/plot/ReferenceLine3D.svelte +0 -154
  628. package/dist/plot/ReferenceLine3D.svelte.d.ts +0 -14
  629. package/dist/plot/ReferencePlane.svelte +0 -178
  630. package/dist/plot/ReferencePlane.svelte.d.ts +0 -14
  631. package/dist/plot/ScatterPlot.svelte +0 -2831
  632. package/dist/plot/ScatterPlot.svelte.d.ts +0 -92
  633. package/dist/plot/ScatterPlot3D.svelte +0 -499
  634. package/dist/plot/ScatterPlot3D.svelte.d.ts +0 -94
  635. package/dist/plot/ScatterPlot3DControls.svelte +0 -437
  636. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +0 -20
  637. package/dist/plot/ScatterPlot3DScene.svelte +0 -912
  638. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +0 -74
  639. package/dist/plot/ScatterPlotControls.svelte +0 -307
  640. package/dist/plot/ScatterPlotControls.svelte.d.ts +0 -17
  641. package/dist/plot/ScatterPoint.svelte +0 -185
  642. package/dist/plot/ScatterPoint.svelte.d.ts +0 -19
  643. package/dist/plot/SpacegroupBarPlot.svelte +0 -292
  644. package/dist/plot/SpacegroupBarPlot.svelte.d.ts +0 -9
  645. package/dist/plot/Surface3D.svelte +0 -200
  646. package/dist/plot/Surface3D.svelte.d.ts +0 -13
  647. package/dist/plot/ZeroLines.svelte +0 -96
  648. package/dist/plot/ZeroLines.svelte.d.ts +0 -32
  649. package/dist/plot/ZoomRect.svelte +0 -23
  650. package/dist/plot/ZoomRect.svelte.d.ts +0 -8
  651. package/dist/plot/axis-utils.d.ts +0 -19
  652. package/dist/plot/axis-utils.js +0 -80
  653. package/dist/plot/data-cleaning.d.ts +0 -37
  654. package/dist/plot/data-cleaning.js +0 -855
  655. package/dist/plot/data-transform.d.ts +0 -16
  656. package/dist/plot/data-transform.js +0 -45
  657. package/dist/plot/defaults.d.ts +0 -19
  658. package/dist/plot/defaults.js +0 -9
  659. package/dist/plot/fill-utils.d.ts +0 -51
  660. package/dist/plot/fill-utils.js +0 -337
  661. package/dist/plot/hover-lock.svelte.d.ts +0 -14
  662. package/dist/plot/hover-lock.svelte.js +0 -46
  663. package/dist/plot/index.d.ts +0 -43
  664. package/dist/plot/index.js +0 -37
  665. package/dist/plot/interactions.d.ts +0 -12
  666. package/dist/plot/interactions.js +0 -100
  667. package/dist/plot/layout.d.ts +0 -60
  668. package/dist/plot/layout.js +0 -230
  669. package/dist/plot/reference-line.d.ts +0 -60
  670. package/dist/plot/reference-line.js +0 -316
  671. package/dist/plot/scales.d.ts +0 -48
  672. package/dist/plot/scales.js +0 -484
  673. package/dist/plot/svg.d.ts +0 -1
  674. package/dist/plot/svg.js +0 -11
  675. package/dist/plot/types.d.ts +0 -863
  676. package/dist/plot/types.js +0 -103
  677. package/dist/plot/utils/label-placement.d.ts +0 -47
  678. package/dist/plot/utils/label-placement.js +0 -256
  679. package/dist/plot/utils/series-visibility.d.ts +0 -9
  680. package/dist/plot/utils/series-visibility.js +0 -67
  681. package/dist/plot/utils.d.ts +0 -1
  682. package/dist/plot/utils.js +0 -14
  683. package/dist/rdf/RdfPlot.svelte +0 -247
  684. package/dist/rdf/RdfPlot.svelte.d.ts +0 -27
  685. package/dist/rdf/calc-rdf.d.ts +0 -4
  686. package/dist/rdf/calc-rdf.js +0 -111
  687. package/dist/rdf/index.d.ts +0 -23
  688. package/dist/rdf/index.js +0 -2
  689. package/dist/sanitize.d.ts +0 -4
  690. package/dist/sanitize.js +0 -107
  691. package/dist/settings.d.ts +0 -253
  692. package/dist/settings.js +0 -1123
  693. package/dist/spectral/Bands.svelte +0 -1040
  694. package/dist/spectral/Bands.svelte.d.ts +0 -40
  695. package/dist/spectral/BandsAndDos.svelte +0 -128
  696. package/dist/spectral/BandsAndDos.svelte.d.ts +0 -18
  697. package/dist/spectral/BrillouinBandsDos.svelte +0 -248
  698. package/dist/spectral/BrillouinBandsDos.svelte.d.ts +0 -20
  699. package/dist/spectral/Dos.svelte +0 -697
  700. package/dist/spectral/Dos.svelte.d.ts +0 -29
  701. package/dist/spectral/helpers.d.ts +0 -117
  702. package/dist/spectral/helpers.js +0 -1023
  703. package/dist/spectral/index.d.ts +0 -6
  704. package/dist/spectral/index.js +0 -7
  705. package/dist/spectral/types.d.ts +0 -84
  706. package/dist/spectral/types.js +0 -2
  707. package/dist/state.svelte.d.ts +0 -25
  708. package/dist/state.svelte.js +0 -45
  709. package/dist/structure/Arrow.svelte +0 -72
  710. package/dist/structure/Arrow.svelte.d.ts +0 -15
  711. package/dist/structure/AtomLegend.svelte +0 -798
  712. package/dist/structure/AtomLegend.svelte.d.ts +0 -34
  713. package/dist/structure/Bond.svelte +0 -140
  714. package/dist/structure/Bond.svelte.d.ts +0 -9
  715. package/dist/structure/CanvasTooltip.svelte +0 -33
  716. package/dist/structure/CanvasTooltip.svelte.d.ts +0 -12
  717. package/dist/structure/CellSelect.svelte +0 -351
  718. package/dist/structure/CellSelect.svelte.d.ts +0 -13
  719. package/dist/structure/Cylinder.svelte +0 -45
  720. package/dist/structure/Cylinder.svelte.d.ts +0 -10
  721. package/dist/structure/Lattice.svelte +0 -196
  722. package/dist/structure/Lattice.svelte.d.ts +0 -17
  723. package/dist/structure/Structure.svelte +0 -1857
  724. package/dist/structure/Structure.svelte.d.ts +0 -83
  725. package/dist/structure/StructureControls.svelte +0 -1184
  726. package/dist/structure/StructureControls.svelte.d.ts +0 -31
  727. package/dist/structure/StructureExportPane.svelte +0 -251
  728. package/dist/structure/StructureExportPane.svelte.d.ts +0 -17
  729. package/dist/structure/StructureInfoPane.svelte +0 -434
  730. package/dist/structure/StructureInfoPane.svelte.d.ts +0 -18
  731. package/dist/structure/StructureScene.svelte +0 -1574
  732. package/dist/structure/StructureScene.svelte.d.ts +0 -104
  733. package/dist/structure/atom-properties.d.ts +0 -37
  734. package/dist/structure/atom-properties.js +0 -198
  735. package/dist/structure/bonding.d.ts +0 -33
  736. package/dist/structure/bonding.js +0 -304
  737. package/dist/structure/export.d.ts +0 -20
  738. package/dist/structure/export.js +0 -725
  739. package/dist/structure/ferrox-wasm-types.d.ts +0 -46
  740. package/dist/structure/ferrox-wasm-types.js +0 -18
  741. package/dist/structure/ferrox-wasm.d.ts +0 -94
  742. package/dist/structure/ferrox-wasm.js +0 -249
  743. package/dist/structure/index.d.ts +0 -110
  744. package/dist/structure/index.js +0 -168
  745. package/dist/structure/measure.d.ts +0 -6
  746. package/dist/structure/measure.js +0 -29
  747. package/dist/structure/parse.d.ts +0 -65
  748. package/dist/structure/parse.js +0 -1374
  749. package/dist/structure/partial-occupancy.d.ts +0 -25
  750. package/dist/structure/partial-occupancy.js +0 -99
  751. package/dist/structure/pbc.d.ts +0 -9
  752. package/dist/structure/pbc.js +0 -123
  753. package/dist/structure/supercell.d.ts +0 -8
  754. package/dist/structure/supercell.js +0 -137
  755. package/dist/structure/validation.d.ts +0 -2
  756. package/dist/structure/validation.js +0 -10
  757. package/dist/symmetry/SymmetryStats.svelte +0 -226
  758. package/dist/symmetry/SymmetryStats.svelte.d.ts +0 -21
  759. package/dist/symmetry/WyckoffTable.svelte +0 -113
  760. package/dist/symmetry/WyckoffTable.svelte.d.ts +0 -11
  761. package/dist/symmetry/cell-transform.d.ts +0 -12
  762. package/dist/symmetry/cell-transform.js +0 -77
  763. package/dist/symmetry/index.d.ts +0 -43
  764. package/dist/symmetry/index.js +0 -229
  765. package/dist/symmetry/spacegroups.d.ts +0 -9
  766. package/dist/symmetry/spacegroups.js +0 -394
  767. package/dist/table/HeatmapTable.svelte +0 -1854
  768. package/dist/table/HeatmapTable.svelte.d.ts +0 -49
  769. package/dist/table/ToggleMenu.svelte +0 -376
  770. package/dist/table/ToggleMenu.svelte.d.ts +0 -11
  771. package/dist/table/index.d.ts +0 -74
  772. package/dist/table/index.js +0 -38
  773. package/dist/theme/ThemeControl.svelte +0 -53
  774. package/dist/theme/ThemeControl.svelte.d.ts +0 -9
  775. package/dist/theme/index.d.ts +0 -29
  776. package/dist/theme/index.js +0 -79
  777. package/dist/theme/themes.mjs +0 -285
  778. package/dist/time.d.ts +0 -4
  779. package/dist/time.js +0 -70
  780. package/dist/tooltip/TooltipContent.svelte +0 -58
  781. package/dist/tooltip/TooltipContent.svelte.d.ts +0 -31
  782. package/dist/tooltip/index.d.ts +0 -2
  783. package/dist/tooltip/index.js +0 -2
  784. package/dist/tooltip/types.d.ts +0 -8
  785. package/dist/tooltip/types.js +0 -1
  786. package/dist/trajectory/Trajectory.svelte +0 -1517
  787. package/dist/trajectory/Trajectory.svelte.d.ts +0 -77
  788. package/dist/trajectory/TrajectoryError.svelte +0 -128
  789. package/dist/trajectory/TrajectoryError.svelte.d.ts +0 -13
  790. package/dist/trajectory/TrajectoryExportPane.svelte +0 -357
  791. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +0 -17
  792. package/dist/trajectory/TrajectoryInfoPane.svelte +0 -387
  793. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +0 -17
  794. package/dist/trajectory/constants.d.ts +0 -6
  795. package/dist/trajectory/constants.js +0 -7
  796. package/dist/trajectory/extract.d.ts +0 -5
  797. package/dist/trajectory/extract.js +0 -162
  798. package/dist/trajectory/format-detect.d.ts +0 -9
  799. package/dist/trajectory/format-detect.js +0 -76
  800. package/dist/trajectory/frame-reader.d.ts +0 -17
  801. package/dist/trajectory/frame-reader.js +0 -332
  802. package/dist/trajectory/helpers.d.ts +0 -14
  803. package/dist/trajectory/helpers.js +0 -172
  804. package/dist/trajectory/index.d.ts +0 -63
  805. package/dist/trajectory/index.js +0 -126
  806. package/dist/trajectory/parse/ase.d.ts +0 -2
  807. package/dist/trajectory/parse/ase.js +0 -77
  808. package/dist/trajectory/parse/hdf5.d.ts +0 -2
  809. package/dist/trajectory/parse/hdf5.js +0 -129
  810. package/dist/trajectory/parse/index.d.ts +0 -12
  811. package/dist/trajectory/parse/index.js +0 -299
  812. package/dist/trajectory/parse/lammps.d.ts +0 -5
  813. package/dist/trajectory/parse/lammps.js +0 -179
  814. package/dist/trajectory/parse/vasp.d.ts +0 -2
  815. package/dist/trajectory/parse/vasp.js +0 -68
  816. package/dist/trajectory/parse/xyz.d.ts +0 -2
  817. package/dist/trajectory/parse/xyz.js +0 -110
  818. package/dist/trajectory/plotting.d.ts +0 -28
  819. package/dist/trajectory/plotting.js +0 -423
  820. package/dist/trajectory/types.d.ts +0 -11
  821. package/dist/trajectory/types.js +0 -1
  822. package/dist/utils.d.ts +0 -5
  823. package/dist/utils.js +0 -36
  824. package/dist/xrd/XrdPlot.svelte +0 -615
  825. package/dist/xrd/XrdPlot.svelte.d.ts +0 -28
  826. package/dist/xrd/broadening.d.ts +0 -20
  827. package/dist/xrd/broadening.js +0 -97
  828. package/dist/xrd/calc-xrd.d.ts +0 -37
  829. package/dist/xrd/calc-xrd.js +0 -337
  830. package/dist/xrd/index.d.ts +0 -37
  831. package/dist/xrd/index.js +0 -4
  832. package/dist/xrd/parse.d.ts +0 -13
  833. package/dist/xrd/parse.js +0 -749
  834. /package/dist/{EmptyState.svelte → src/lib/EmptyState.svelte} +0 -0
  835. /package/dist/{Icon.svelte → src/lib/Icon.svelte} +0 -0
  836. /package/dist/{chempot-diagram → src/lib/chempot-diagram}/ChemPotScene3D.svelte +0 -0
  837. /package/dist/{colors → src/lib/colors}/alloy-colors.json +0 -0
  838. /package/dist/{colors → src/lib/colors}/dark-mode-colors.json +0 -0
  839. /package/dist/{colors → src/lib/colors}/jmol-colors.json +0 -0
  840. /package/dist/{colors → src/lib/colors}/muted-colors.json +0 -0
  841. /package/dist/{colors → src/lib/colors}/pastel-colors.json +0 -0
  842. /package/dist/{colors → src/lib/colors}/vesta-colors.json +0 -0
  843. /package/dist/{element → src/lib/element}/Nucleus.svelte +0 -0
  844. /package/dist/{element → src/lib/element}/data.json +0 -0
  845. /package/dist/{element → src/lib/element}/data.json.gz +0 -0
  846. /package/dist/{element → src/lib/element}/data.schema.json +0 -0
  847. /package/dist/{element-image-urls.json → src/lib/element-image-urls.json} +0 -0
  848. /package/dist/{feedback → src/lib/feedback}/Spinner.svelte +0 -0
  849. /package/dist/{feedback → src/lib/feedback}/StatusMessage.svelte +0 -0
  850. /package/dist/{periodic-table → src/lib/periodic-table}/TableInset.svelte +0 -0
  851. /package/dist/{plot → src/lib/plot}/ReferenceLine.svelte +0 -0
  852. /package/dist/{xrd → src/lib/xrd}/atomic_scattering_params.json +0 -0
@@ -1,2256 +0,0 @@
1
- <script
2
- lang="ts"
3
- generics="Metadata extends Record<string, unknown> = Record<string, unknown>"
4
- >
5
- import type { D3ColorSchemeName, D3InterpolateName } from '../colors'
6
- import { format_value } from '../labels'
7
- import { sanitize_html } from '../sanitize'
8
- import { FullscreenToggle, set_fullscreen_bg } from '../layout'
9
- import type {
10
- AxisLoadError,
11
- BarHandlerProps,
12
- BarMode,
13
- BarSeries,
14
- BarStyle,
15
- BasePlotProps,
16
- DataLoaderFn,
17
- InitialRanges,
18
- InternalPoint,
19
- LegendConfig,
20
- LegendItem,
21
- LineStyle,
22
- Orientation,
23
- PanConfig,
24
- PlotConfig,
25
- RefLine,
26
- RefLineEvent,
27
- ScaleType,
28
- TweenedOptions,
29
- UserContentProps,
30
- XyObj,
31
- } from './'
32
- import {
33
- AxisLabel,
34
- BarPlotControls,
35
- compute_element_placement,
36
- PlotLegend,
37
- ReferenceLine,
38
- ScatterPoint,
39
- } from './'
40
- import type { AxisChangeState } from './axis-utils'
41
- import { create_axis_change_handler } from './axis-utils'
42
- import { process_prop } from './data-transform'
43
- import {
44
- create_dimension_tracker,
45
- create_hover_lock,
46
- } from './hover-lock.svelte'
47
- import {
48
- get_relative_coords,
49
- pan_range,
50
- PINCH_ZOOM_THRESHOLD,
51
- pixels_to_data_delta,
52
- } from './interactions'
53
- import type { IndexedRefLine } from './reference-line'
54
- import { group_ref_lines_by_z, index_ref_lines } from './reference-line'
55
- import {
56
- create_color_scale,
57
- create_scale,
58
- create_size_scale,
59
- generate_ticks,
60
- get_nice_data_range,
61
- get_tick_label,
62
- } from './scales'
63
- import {
64
- DEFAULT_GRID_STYLE,
65
- DEFAULT_MARKERS,
66
- get_scale_type_name,
67
- } from './types'
68
- import { DEFAULTS } from '../settings'
69
- import { extent } from 'd3-array'
70
- import type { Snippet } from 'svelte'
71
- import { untrack } from 'svelte'
72
- import type { HTMLAttributes } from 'svelte/elements'
73
- import { Tween } from 'svelte/motion'
74
- import { SvelteMap } from 'svelte/reactivity'
75
- import type { Vec2 } from '../math'
76
- import {
77
- calc_auto_padding,
78
- constrain_tooltip_position,
79
- filter_padding,
80
- LABEL_GAP_DEFAULT,
81
- measure_max_tick_width,
82
- } from './layout'
83
- import PlotTooltip from './PlotTooltip.svelte'
84
- import { bar_path } from './svg'
85
- import ZeroLines from './ZeroLines.svelte'
86
- import ZoomRect from './ZoomRect.svelte'
87
-
88
- // Handler props for line marker events (extends BarHandlerProps with point-specific data)
89
- interface LineMarkerHandlerProps extends BarHandlerProps<Metadata> {
90
- point: InternalPoint<Metadata>
91
- }
92
-
93
- // Extended point type with computed screen coordinates (used internally for rendering)
94
- type LineSeriesPoint = InternalPoint<Metadata> & {
95
- x: number // Screen x coordinate
96
- y: number // Screen y coordinate
97
- data_x: number // Original data x value
98
- data_y: number // Original data y value
99
- idx: number // Index in series
100
- }
101
-
102
- let {
103
- series = $bindable([]),
104
- orientation = $bindable(`vertical`),
105
- mode = $bindable(`overlay`),
106
- x_axis = $bindable({}),
107
- x2_axis = $bindable({}),
108
- y_axis = $bindable({}),
109
- y2_axis = $bindable({}),
110
- display = $bindable(DEFAULTS.bar.display),
111
- x_range = [null, null],
112
- x2_range = [null, null],
113
- y_range = [null, null],
114
- y2_range = [null, null],
115
- range_padding = 0.05,
116
- padding = { t: 20, b: 60, l: 60, r: 20 },
117
- legend = {},
118
- show_legend,
119
- bar = {},
120
- line = {},
121
- tooltip,
122
- user_content,
123
- hovered = $bindable(false),
124
- change = () => {},
125
- on_bar_click,
126
- on_bar_hover,
127
- // Line marker props (matching ScatterPlot)
128
- color_scale = {
129
- type: `linear`,
130
- scheme: `interpolateViridis`,
131
- value_range: undefined,
132
- },
133
- size_scale = { type: `linear`, radius_range: [2, 10], value_range: undefined },
134
- point_tween,
135
- on_point_click,
136
- on_point_hover,
137
- ref_lines = $bindable([]),
138
- on_ref_line_click,
139
- on_ref_line_hover,
140
- show_controls = $bindable(true),
141
- controls_open = $bindable(false),
142
- controls_toggle_props,
143
- controls_pane_props,
144
- fullscreen = $bindable(false),
145
- fullscreen_toggle = true,
146
- children,
147
- header_controls,
148
- controls_extra,
149
- data_loader,
150
- on_axis_change,
151
- on_error,
152
- pan = {},
153
- ...rest
154
- }: HTMLAttributes<HTMLDivElement> & BasePlotProps & PlotConfig & {
155
- series?: BarSeries<Metadata>[]
156
- // Component-specific props
157
- orientation?: Orientation
158
- mode?: BarMode
159
- legend?: LegendConfig | null
160
- show_legend?: boolean
161
- bar?: BarStyle
162
- line?: LineStyle
163
- tooltip?: Snippet<[BarHandlerProps<Metadata>]>
164
- user_content?: Snippet<[UserContentProps]>
165
- header_controls?: Snippet<
166
- [{ height: number; width: number; fullscreen: boolean }]
167
- >
168
- controls_extra?: Snippet<
169
- [{ orientation: Orientation; mode: BarMode } & Required<PlotConfig>]
170
- >
171
- change?: (data: BarHandlerProps<Metadata> | null) => void
172
- on_bar_click?: (
173
- data: BarHandlerProps<Metadata> & { event: MouseEvent | KeyboardEvent },
174
- ) => void
175
- on_bar_hover?: (
176
- data:
177
- | (BarHandlerProps<Metadata> & {
178
- event: MouseEvent | FocusEvent | KeyboardEvent
179
- })
180
- | null,
181
- ) => void
182
- // Line marker props (matching ScatterPlot)
183
- // Note: For line series with markers, BOTH on_bar_* AND on_point_* events fire.
184
- // Use on_point_* for marker-specific data (includes `point` with InternalPoint details)
185
- // or on_bar_* for backward compatibility with bar-style event handling.
186
- color_scale?: {
187
- type?: ScaleType
188
- scheme?: D3ColorSchemeName | D3InterpolateName
189
- value_range?: [number, number]
190
- } | D3InterpolateName
191
- size_scale?: {
192
- type?: ScaleType
193
- radius_range?: [number, number]
194
- value_range?: [number, number]
195
- }
196
- point_tween?: TweenedOptions<XyObj>
197
- on_point_click?: (
198
- data: LineMarkerHandlerProps & { event: MouseEvent | KeyboardEvent },
199
- ) => void
200
- on_point_hover?: (
201
- data:
202
- | (LineMarkerHandlerProps & {
203
- event: MouseEvent | FocusEvent | KeyboardEvent
204
- })
205
- | null,
206
- ) => void
207
- ref_lines?: RefLine[]
208
- on_ref_line_click?: (event: RefLineEvent) => void
209
- on_ref_line_hover?: (event: RefLineEvent | null) => void
210
- // Interactive axis props
211
- data_loader?: DataLoaderFn<Metadata, BarSeries<Metadata>>
212
- on_axis_change?: (
213
- axis: `x` | `x2` | `y` | `y2`,
214
- key: string,
215
- new_series: BarSeries<Metadata>[],
216
- ) => void
217
- on_error?: (error: AxisLoadError) => void
218
- pan?: PanConfig
219
- } = $props()
220
-
221
- // Initialize bar, line, y2_axis with defaults - using $derived for reactivity
222
- let bar_state = $derived({ ...DEFAULTS.bar.bar, ...bar })
223
- let line_state = $derived({ ...DEFAULTS.bar.line, ...line })
224
- y2_axis = {
225
- format: ``,
226
- scale_type: `linear`,
227
- ticks: 5,
228
- label_shift: { y: 60 },
229
- tick: { label: { shift: { x: 0, y: 0 } } }, // base offset handled in rendering
230
- range: [null, null],
231
- ...y2_axis,
232
- }
233
- x2_axis = {
234
- format: ``,
235
- scale_type: `linear`,
236
- ticks: 5,
237
- label_shift: { x: 0, y: 40 },
238
- tick: { label: { shift: { x: 0, y: 0 } } },
239
- range: [null, null],
240
- ...x2_axis,
241
- }
242
-
243
- let [width, height] = $state([0, 0])
244
- let wrapper: HTMLDivElement | undefined = $state()
245
- let svg_element: SVGElement | null = $state(null)
246
- let clip_path_id = `chart-clip-${crypto?.randomUUID?.()}`
247
-
248
- // Reference line hover state
249
- let hovered_ref_line_idx = $state<number | null>(null)
250
-
251
- // Interactive axis loading state
252
- let axis_loading = $state<`x` | `x2` | `y` | `y2` | null>(null)
253
-
254
- // Compute ref_lines with index and group by z-index (using shared utilities)
255
- let indexed_ref_lines = $derived(index_ref_lines(ref_lines))
256
- let ref_lines_by_z = $derived(group_ref_lines_by_z(indexed_ref_lines))
257
-
258
- // === Categorical Normalization ===
259
- // Internal type with guaranteed numeric x (for downstream scale/rendering code)
260
- type NumericBarSeries = Omit<BarSeries<Metadata>, `x`> & { x: readonly number[] }
261
-
262
- let is_categorical = $derived(
263
- series.some((srs) => srs.x.some((val) => typeof val === `string`)),
264
- )
265
-
266
- let category_list = $derived.by(() => {
267
- if (!is_categorical) return [] as string[]
268
- if (x_axis.categories?.length) return [...x_axis.categories]
269
- return [...new Set(series.flatMap((srs) => srs.x.map(String)))]
270
- })
271
-
272
- let category_indices = $derived(
273
- category_list.length ? category_list.map((_, idx) => idx) : null,
274
- )
275
-
276
- let internal_series = $derived.by<NumericBarSeries[]>(() => {
277
- // safe: when !category_indices, all x values are numeric (is_categorical is false)
278
- if (!category_indices) return series as unknown as NumericBarSeries[]
279
- return series.map((srs) => {
280
- const orig_map = new Map(srs.x.map((val, idx) => [String(val), idx]))
281
- if (orig_map.size < srs.x.length) {
282
- console.warn(
283
- `BarPlot: series "${
284
- srs.label ?? `?`
285
- }" has duplicate x values — last occurrence wins`,
286
- )
287
- }
288
- // Resolve original index for each category (undefined if series lacks it)
289
- const orig_indices = category_list.map((cat) => orig_map.get(cat))
290
- const remap = <T>(arr: readonly T[] | null | undefined, fallback: T): T[] =>
291
- orig_indices.map((oi) => oi != null ? (arr?.[oi] ?? fallback) : fallback)
292
- const bw_arr = Array.isArray(srs.bar_width) ? srs.bar_width : null
293
- const meta_arr = Array.isArray(srs.metadata) ? srs.metadata : null
294
- return {
295
- ...srs,
296
- x: category_indices,
297
- y: remap(srs.y, srs.render_mode === `line` ? NaN : 0),
298
- labels: remap(srs.labels, null),
299
- metadata: orig_indices.map((oi) =>
300
- oi != null ? (meta_arr ? meta_arr[oi] : srs.metadata) : undefined
301
- ) as Metadata[],
302
- ...(bw_arr ? { bar_width: remap(bw_arr, 0.5) } : {}),
303
- ...(srs.color_values ? { color_values: remap(srs.color_values, null) } : {}),
304
- ...(srs.size_values ? { size_values: remap(srs.size_values, null) } : {}),
305
- } as NumericBarSeries
306
- })
307
- })
308
-
309
- // Compute auto ranges from visible series
310
- let visible_series = $derived(
311
- internal_series.filter((srs) => srs?.visible ?? true),
312
- )
313
-
314
- // Separate series by y-axis
315
- let y1_series = $derived(
316
- visible_series.filter((srs) => (srs.y_axis ?? `y1`) === `y1`),
317
- )
318
- let y2_series = $derived(
319
- visible_series.filter((srs) => srs.y_axis === `y2`),
320
- )
321
- let x2_series = $derived(
322
- visible_series.filter((srs) => srs.x_axis === `x2`),
323
- )
324
-
325
- let auto_ranges = $derived.by(() => {
326
- // Calculate separate ranges for y1 and y2 axes
327
- const calc_y_range = (
328
- series_list: typeof visible_series,
329
- y_limit: typeof y_range,
330
- scale_type: ScaleType,
331
- ) => {
332
- let points = series_list.flatMap((srs) =>
333
- srs.x.map((x_val, idx) => ({ x: x_val, y: srs.y[idx] }))
334
- )
335
-
336
- // In stacked mode, calculate stacked totals for accurate range (only for bars on the same axis)
337
- if (mode === `stacked`) {
338
- const stacked_totals = new SvelteMap<number, { pos: number; neg: number }>()
339
-
340
- // Only include visible bar series (not lines) in stacking
341
- series_list
342
- .filter((srs) => srs.render_mode !== `line`)
343
- .forEach((srs) =>
344
- srs.x.forEach((x_val, idx) => {
345
- const y_val = srs.y[idx] ?? 0
346
- const totals = stacked_totals.get(x_val) ?? { pos: 0, neg: 0 }
347
- if (y_val >= 0) totals.pos += y_val
348
- else totals.neg += y_val
349
- stacked_totals.set(x_val, totals)
350
- })
351
- )
352
-
353
- // Replace points with stacked totals + line series (which don't stack)
354
- points = [
355
- ...Array.from(stacked_totals).flatMap(([x_val, { pos, neg }]) => [
356
- ...(pos > 0 ? [{ x: x_val, y: pos }] : []),
357
- ...(neg < 0 ? [{ x: x_val, y: neg }] : []),
358
- ]),
359
- ...series_list
360
- .filter((srs) => srs.render_mode === `line`)
361
- .flatMap((srs) =>
362
- srs.x.map((x_val, idx) => ({ x: x_val, y: srs.y[idx] }))
363
- ),
364
- ]
365
- }
366
-
367
- if (!points.length) return [0, 1]
368
-
369
- let y_range = get_nice_data_range(
370
- points,
371
- (pt) => pt.y,
372
- y_limit,
373
- scale_type,
374
- range_padding,
375
- false,
376
- )
377
-
378
- // For bar plots, ensure the value axis starts at 0 unless there are negative values
379
- // Only apply zero-clamping for linear and arcsinh scales (not log)
380
- const type_name = get_scale_type_name(scale_type)
381
- if (type_name === `linear` || type_name === `arcsinh`) {
382
- const has_negative = points.some((pt) => pt.y < 0)
383
- const has_positive = points.some((pt) => pt.y > 0)
384
-
385
- // Only adjust if no explicit y_range is set
386
- if (y_limit?.[0] == null && y_limit?.[1] == null) {
387
- if (has_positive && !has_negative) y_range = [0, y_range[1]]
388
- else if (has_negative && !has_positive) y_range = [y_range[0], 0]
389
- }
390
- }
391
-
392
- return y_range
393
- }
394
-
395
- // Get x values split by axis for range calculation
396
- // For categorical data, use fixed range centered on integer indices
397
- let x_auto_range: number[]
398
- if (category_list.length) {
399
- x_auto_range = [-0.5, category_list.length - 0.5]
400
- } else {
401
- const x1_x_points = visible_series
402
- .filter((srs) => (srs.x_axis ?? `x1`) === `x1`)
403
- .flatMap((srs) => srs.x.map((x_val) => ({ x: x_val, y: 0 })))
404
- x_auto_range = x1_x_points.length
405
- ? get_nice_data_range(
406
- x1_x_points,
407
- (pt) => pt.x,
408
- x_range,
409
- x_axis.scale_type ?? `linear`,
410
- range_padding,
411
- x_axis.format?.startsWith(`%`) || false,
412
- )
413
- : [0, 1]
414
- }
415
-
416
- const x2_x_points = x2_series.flatMap((srs) =>
417
- srs.x.map((x_val) => ({ x: x_val, y: 0 }))
418
- )
419
- const x2_scale_type = x2_axis.scale_type ?? `linear`
420
- const x2_auto_range = x2_x_points.length
421
- ? get_nice_data_range(
422
- x2_x_points,
423
- (pt) => pt.x,
424
- x2_range,
425
- x2_scale_type,
426
- range_padding,
427
- x2_axis.format?.startsWith(`%`) || false,
428
- )
429
- : [0, 1]
430
-
431
- const y1_range = calc_y_range(y1_series, y_range, y_axis.scale_type ?? `linear`)
432
- const y2_auto_range = calc_y_range(
433
- y2_series,
434
- y2_range,
435
- y2_axis.scale_type ?? `linear`,
436
- )
437
-
438
- // Map data ranges to axis ranges depending on orientation
439
- return orientation === `horizontal`
440
- ? ({ x: y1_range, x2: x2_auto_range, y: x_auto_range, y2: y2_auto_range })
441
- : ({ x: x_auto_range, x2: x2_auto_range, y: y1_range, y2: y2_auto_range })
442
- })
443
-
444
- // Initialize and current ranges
445
- let ranges = $state<{
446
- initial: { x: Vec2; x2: Vec2; y: Vec2; y2: Vec2 }
447
- current: { x: Vec2; x2: Vec2; y: Vec2; y2: Vec2 }
448
- }>({
449
- initial: { x: [0, 1], x2: [0, 1], y: [0, 1], y2: [0, 1] },
450
- current: { x: [0, 1], x2: [0, 1], y: [0, 1], y2: [0, 1] },
451
- })
452
-
453
- $effect(() => { // handle x_axis.range / x2_axis.range / y_axis.range / y2_axis.range changes
454
- const new_x = [
455
- x_axis.range?.[0] ?? auto_ranges.x[0],
456
- x_axis.range?.[1] ?? auto_ranges.x[1],
457
- ] as Vec2
458
- const new_x2 = [
459
- x2_axis.range?.[0] ?? auto_ranges.x2[0],
460
- x2_axis.range?.[1] ?? auto_ranges.x2[1],
461
- ] as Vec2
462
- const new_y = [
463
- y_axis.range?.[0] ?? auto_ranges.y[0],
464
- y_axis.range?.[1] ?? auto_ranges.y[1],
465
- ] as Vec2
466
- const new_y2 = [
467
- y2_axis.range?.[0] ?? auto_ranges.y2[0],
468
- y2_axis.range?.[1] ?? auto_ranges.y2[1],
469
- ] as Vec2
470
- // Only update if the initial (data-driven) ranges changed, not when user pans
471
- // Comparing against initial preserves user's pan/zoom state
472
- if (
473
- ranges.initial.x[0] !== new_x[0] ||
474
- ranges.initial.x[1] !== new_x[1] ||
475
- ranges.initial.x2[0] !== new_x2[0] ||
476
- ranges.initial.x2[1] !== new_x2[1] ||
477
- ranges.initial.y[0] !== new_y[0] ||
478
- ranges.initial.y[1] !== new_y[1] ||
479
- ranges.initial.y2[0] !== new_y2[0] ||
480
- ranges.initial.y2[1] !== new_y2[1]
481
- ) {
482
- ranges = {
483
- initial: { x: new_x, x2: new_x2, y: new_y, y2: new_y2 },
484
- current: { x: new_x, x2: new_x2, y: new_y, y2: new_y2 },
485
- }
486
- }
487
- })
488
-
489
- // Layout: dynamic padding based on tick label widths
490
- const default_padding = { t: 20, b: 60, l: 60, r: 20 }
491
- let pad = $derived(filter_padding(padding, default_padding))
492
-
493
- // Update padding when format or ticks change
494
- $effect(() => {
495
- const new_pad = width && height && ticks.y.length
496
- ? calc_auto_padding({
497
- padding,
498
- default_padding,
499
- x2_axis: { ...x2_axis, tick_values: ticks.x2 },
500
- y_axis: { ...y_axis, tick_values: ticks.y },
501
- y2_axis: { ...y2_axis, tick_values: ticks.y2 },
502
- })
503
- : filter_padding(padding, default_padding)
504
- // Expand right padding if y2 ticks are shown (only for vertical orientation)
505
- if (
506
- width && height && y2_series.length && ticks.y2.length &&
507
- orientation === `vertical`
508
- ) {
509
- // Need space for: tick shift + tick width + gap (30px) + label space (20px if present)
510
- // When ticks are inside, they don't contribute to padding
511
- const inside = y2_axis.tick?.label?.inside ?? false
512
- const tick_shift = inside ? 0 : (y2_axis.tick?.label?.shift?.x ?? 0) + 8
513
- const tick_width_contribution = inside ? 0 : tick_label_widths.y2_max
514
- const label_space = y2_axis.label ? 20 : 0
515
- new_pad.r = Math.max(
516
- new_pad.r,
517
- tick_shift + tick_width_contribution + 30 + label_space,
518
- )
519
- }
520
- // Expand top padding if x2 ticks are shown (only for vertical orientation)
521
- if (
522
- width && height && x2_series.length && ticks.x2.length &&
523
- orientation === `vertical`
524
- ) {
525
- const inside = x2_axis.tick?.label?.inside ?? false
526
- const tick_shift = inside ? 0 : Math.abs(x2_axis.tick?.label?.shift?.y ?? 0) + 5
527
- const tick_height = inside ? 0 : 16
528
- const label_space = x2_axis.label ? 20 : 0
529
- new_pad.t = Math.max(new_pad.t, tick_shift + tick_height + 30 + label_space)
530
- }
531
-
532
- // Only update if padding actually changed (prevents infinite loop)
533
- if (
534
- pad.t !== new_pad.t || pad.b !== new_pad.b || pad.l !== new_pad.l ||
535
- pad.r !== new_pad.r
536
- ) pad = new_pad
537
- })
538
- const chart_width = $derived(Math.max(1, width - pad.l - pad.r))
539
- const chart_height = $derived(Math.max(1, height - pad.t - pad.b))
540
-
541
- // Scales
542
- let scales = $derived({
543
- x: create_scale(x_axis.scale_type ?? `linear`, ranges.current.x, [
544
- pad.l,
545
- width - pad.r,
546
- ]),
547
- x2: create_scale(x2_axis.scale_type ?? `linear`, ranges.current.x2, [
548
- pad.l,
549
- width - pad.r,
550
- ]),
551
- y: create_scale(y_axis.scale_type ?? `linear`, ranges.current.y, [
552
- height - pad.b,
553
- pad.t,
554
- ]),
555
- y2: create_scale(y2_axis.scale_type ?? `linear`, ranges.current.y2, [
556
- height - pad.b,
557
- pad.t,
558
- ]),
559
- })
560
-
561
- // Compute plot center for point tweening origin
562
- let plot_center_x = $derived(pad.l + (width - pad.r - pad.l) / 2)
563
- let plot_center_y = $derived(pad.t + (height - pad.b - pad.t) / 2)
564
-
565
- // Compute color values from line series for color scaling (filter to numbers only)
566
- let all_color_values = $derived(
567
- visible_series
568
- .filter((srs: BarSeries<Metadata>) => srs.render_mode === `line`)
569
- .flatMap((srs: BarSeries<Metadata>) =>
570
- (srs.color_values ?? []).filter(
571
- (val): val is number => typeof val === `number`,
572
- )
573
- ),
574
- )
575
-
576
- // Create auto color range (safely handle empty arrays or undefined extent results)
577
- let auto_color_range: [number, number] = $derived.by(() => {
578
- if (all_color_values.length === 0) return [0, 1]
579
- const [min_val, max_val] = extent(all_color_values)
580
- return [min_val ?? 0, max_val ?? 1]
581
- })
582
-
583
- // All size values from line series (for size scale, filter to numbers only)
584
- let all_size_values = $derived(
585
- visible_series
586
- .filter((srs: BarSeries<Metadata>) => srs.render_mode === `line`)
587
- .flatMap((srs: BarSeries<Metadata>) =>
588
- [...(srs.size_values ?? [])].filter(
589
- (val): val is number => typeof val === `number`,
590
- )
591
- ),
592
- )
593
-
594
- // Color scale function (using shared utility)
595
- let color_scale_fn = $derived(create_color_scale(color_scale, auto_color_range))
596
-
597
- // Size scale function (using shared utility)
598
- let size_scale_fn = $derived(create_size_scale(size_scale, all_size_values))
599
-
600
- // Auto-generate tick labels for categorical data (unless user provides explicit ticks)
601
- // In vertical mode categories are on x-axis; in horizontal mode on y-axis
602
- let cat_axis = $derived(orientation === `horizontal` ? `y` : `x`)
603
- let effective_cat_ticks = $derived.by(() => {
604
- if (!category_list.length) return undefined
605
- // Only respect user ticks when they're a Record (custom label mapping),
606
- // not a number (tick count) or array (tick positions)
607
- const user_ticks = cat_axis === `x` ? x_axis.ticks : y_axis.ticks
608
- if (
609
- user_ticks != null && typeof user_ticks === `object` &&
610
- !Array.isArray(user_ticks)
611
- ) return user_ticks
612
- return Object.fromEntries(
613
- category_list.map((cat, idx) => [idx, cat]),
614
- ) as Record<number, string>
615
- })
616
-
617
- // Ticks
618
- let ticks = $derived({
619
- x: width && height
620
- ? (category_indices && cat_axis === `x` ? category_indices : generate_ticks(
621
- ranges.current.x,
622
- x_axis.scale_type ?? `linear`,
623
- x_axis.ticks,
624
- scales.x,
625
- { default_count: 8 },
626
- ))
627
- : [],
628
- y: width && height
629
- ? (category_indices && cat_axis === `y` ? category_indices : generate_ticks(
630
- ranges.current.y,
631
- y_axis.scale_type ?? `linear`,
632
- y_axis.ticks,
633
- scales.y,
634
- { default_count: 6 },
635
- ))
636
- : [],
637
- y2: width && height && y2_series.length > 0 && orientation === `vertical`
638
- ? generate_ticks(
639
- ranges.current.y2,
640
- y2_axis.scale_type ?? `linear`,
641
- y2_axis.ticks,
642
- scales.y2,
643
- {
644
- default_count: 6,
645
- },
646
- )
647
- : [],
648
- x2: width && height && x2_series.length > 0 && orientation === `vertical`
649
- ? generate_ticks(
650
- ranges.current.x2,
651
- x2_axis.scale_type ?? `linear`,
652
- x2_axis.ticks,
653
- scales.x2,
654
- {
655
- default_count: 8,
656
- },
657
- )
658
- : [],
659
- })
660
-
661
- // Cache measured tick-label widths so expensive canvas text measurement
662
- // only runs when ticks/format change, not on every template rerender.
663
- let tick_label_widths = $derived({
664
- y_max: measure_max_tick_width(ticks.y, y_axis.format ?? ``),
665
- y2_max: measure_max_tick_width(ticks.y2, y2_axis.format ?? ``),
666
- x2_max: measure_max_tick_width(ticks.x2, x2_axis.format ?? ``),
667
- })
668
-
669
- // Zoom drag state
670
- let drag_state = $state<{
671
- start: { x: number; y: number } | null
672
- current: { x: number; y: number } | null
673
- bounds: DOMRect | null
674
- }>({ start: null, current: null, bounds: null })
675
-
676
- // Pan state
677
- let is_focused = $state(false)
678
- let shift_held = $state(false)
679
- let pan_drag_state = $state<
680
- InitialRanges & { start: { x: number; y: number } } | null
681
- >(null)
682
- let touch_state = $state<
683
- InitialRanges & { start_touches: { x: number; y: number }[] } | null
684
- >(null)
685
- const on_window_mouse_move = (evt: MouseEvent) => {
686
- if (!drag_state.start || !drag_state.bounds) return
687
- drag_state.current = {
688
- x: evt.clientX - drag_state.bounds.left,
689
- y: evt.clientY - drag_state.bounds.top,
690
- }
691
- }
692
- const on_window_mouse_up = () => {
693
- if (drag_state.start && drag_state.current) {
694
- const x1_raw = scales.x.invert(drag_state.start.x) as number | Date
695
- const x2_raw = scales.x.invert(drag_state.current.x) as number | Date
696
- const y1 = scales.y.invert(drag_state.start.y)
697
- const y2 = scales.y.invert(drag_state.current.y)
698
- const y2_1 = scales.y2.invert(drag_state.start.y)
699
- const y2_2 = scales.y2.invert(drag_state.current.y)
700
- const x2a_1_raw = scales.x2.invert(drag_state.start.x) as number | Date
701
- const x2a_2_raw = scales.x2.invert(drag_state.current.x) as number | Date
702
- const dx = Math.abs(drag_state.start.x - drag_state.current.x)
703
- const dy = Math.abs(drag_state.start.y - drag_state.current.y)
704
-
705
- let xr1: number, xr2: number
706
- if (x1_raw instanceof Date && x2_raw instanceof Date) {
707
- ;[xr1, xr2] = [x1_raw.getTime(), x2_raw.getTime()]
708
- } else if (typeof x1_raw === `number` && typeof x2_raw === `number`) {
709
- ;[xr1, xr2] = [x1_raw, x2_raw]
710
- } else [xr1, xr2] = [NaN, NaN] // bail: mixed types
711
-
712
- let x2r1: number, x2r2: number
713
- if (x2a_1_raw instanceof Date && x2a_2_raw instanceof Date) {
714
- ;[x2r1, x2r2] = [x2a_1_raw.getTime(), x2a_2_raw.getTime()]
715
- } else if (typeof x2a_1_raw === `number` && typeof x2a_2_raw === `number`) {
716
- ;[x2r1, x2r2] = [x2a_1_raw, x2a_2_raw]
717
- } else [x2r1, x2r2] = [NaN, NaN]
718
-
719
- if (dx > 5 && dy > 5 && Number.isFinite(xr1) && Number.isFinite(xr2)) {
720
- // Update axis ranges to trigger reactivity and prevent effect from overriding
721
- x_axis = { ...x_axis, range: [Math.min(xr1, xr2), Math.max(xr1, xr2)] }
722
- if (x2_series.length > 0 && Number.isFinite(x2r1) && Number.isFinite(x2r2)) {
723
- x2_axis = {
724
- ...x2_axis,
725
- range: [Math.min(x2r1, x2r2), Math.max(x2r1, x2r2)],
726
- }
727
- }
728
- y_axis = { ...y_axis, range: [Math.min(y1, y2), Math.max(y1, y2)] }
729
- y2_axis = { ...y2_axis, range: [Math.min(y2_1, y2_2), Math.max(y2_1, y2_2)] }
730
- }
731
- }
732
- drag_state = { start: null, current: null, bounds: null }
733
- window.removeEventListener(`mousemove`, on_window_mouse_move)
734
- window.removeEventListener(`mouseup`, on_window_mouse_up)
735
- document.body.style.cursor = `default`
736
- }
737
-
738
- // Pan drag handlers
739
- const on_pan_move = (evt: MouseEvent) => {
740
- if (!pan_drag_state) return
741
- const dx = evt.clientX - pan_drag_state.start.x
742
- const dy = evt.clientY - pan_drag_state.start.y
743
-
744
- // Convert pixel delta to data delta (note: drag direction is inverted for natural pan feel)
745
- const sensitivity = pan?.drag_sensitivity ?? 1
746
-
747
- const x_delta = pixels_to_data_delta(
748
- -dx * sensitivity,
749
- pan_drag_state.initial_x_range,
750
- chart_width,
751
- )
752
- const x2_delta = pixels_to_data_delta(
753
- -dx * sensitivity,
754
- pan_drag_state.initial_x2_range,
755
- chart_width,
756
- )
757
- const y_delta = pixels_to_data_delta(
758
- dy * sensitivity,
759
- pan_drag_state.initial_y_range,
760
- chart_height,
761
- )
762
- const y2_delta = pixels_to_data_delta(
763
- dy * sensitivity,
764
- pan_drag_state.initial_y2_range,
765
- chart_height,
766
- )
767
-
768
- ranges.current.x = pan_range(pan_drag_state.initial_x_range, x_delta)
769
- ranges.current.x2 = pan_range(pan_drag_state.initial_x2_range, x2_delta)
770
- ranges.current.y = pan_range(pan_drag_state.initial_y_range, y_delta)
771
- ranges.current.y2 = pan_range(pan_drag_state.initial_y2_range, y2_delta)
772
- }
773
-
774
- const on_pan_end = () => {
775
- pan_drag_state = null
776
- document.body.style.cursor = ``
777
- window.removeEventListener(`mousemove`, on_pan_move)
778
- window.removeEventListener(`mouseup`, on_pan_end)
779
- }
780
-
781
- function handle_mouse_down(evt: MouseEvent) {
782
- const coords = get_relative_coords(evt)
783
- if (!coords || !svg_element) return
784
-
785
- // Check if pan is enabled and shift is held for pan mode
786
- const pan_enabled = pan?.enabled !== false
787
- if (pan_enabled && evt.shiftKey) {
788
- evt.preventDefault()
789
- pan_drag_state = {
790
- start: { x: evt.clientX, y: evt.clientY },
791
- initial_x_range: [...ranges.current.x] as [number, number],
792
- initial_x2_range: [...ranges.current.x2] as [number, number],
793
- initial_y_range: [...ranges.current.y] as [number, number],
794
- initial_y2_range: [...ranges.current.y2] as [number, number],
795
- }
796
- document.body.style.cursor = `grabbing`
797
- window.addEventListener(`mousemove`, on_pan_move)
798
- window.addEventListener(`mouseup`, on_pan_end)
799
- return
800
- }
801
-
802
- drag_state = {
803
- start: coords,
804
- current: coords,
805
- bounds: svg_element.getBoundingClientRect(),
806
- }
807
- window.addEventListener(`mousemove`, on_window_mouse_move)
808
- window.addEventListener(`mouseup`, on_window_mouse_up)
809
- evt.preventDefault()
810
- }
811
-
812
- // Wheel handler for pan (requires focus and shift)
813
- function handle_wheel(evt: WheelEvent) {
814
- const pan_enabled = pan?.enabled !== false
815
- // Only capture wheel when focused AND Shift is held
816
- // Use shift_held state (tracked via keydown/keyup) for compatibility with synthetic events
817
- if (!pan_enabled || !is_focused || !shift_held) return
818
-
819
- evt.preventDefault()
820
-
821
- const sensitivity = pan?.wheel_sensitivity ?? 1
822
-
823
- // Determine pan direction based on wheel delta
824
- const x_delta = pixels_to_data_delta(
825
- evt.deltaX * sensitivity,
826
- ranges.current.x,
827
- chart_width,
828
- )
829
- const x2_delta = pixels_to_data_delta(
830
- evt.deltaX * sensitivity,
831
- ranges.current.x2,
832
- chart_width,
833
- )
834
- const y_delta = pixels_to_data_delta(
835
- evt.deltaY * sensitivity,
836
- ranges.current.y,
837
- chart_height,
838
- )
839
- const y2_delta = pixels_to_data_delta(
840
- evt.deltaY * sensitivity,
841
- ranges.current.y2,
842
- chart_height,
843
- )
844
-
845
- if (Math.abs(evt.deltaX) > Math.abs(evt.deltaY)) {
846
- ranges.current.x = pan_range(ranges.current.x, x_delta)
847
- ranges.current.x2 = pan_range(ranges.current.x2, x2_delta)
848
- } else {
849
- ranges.current.y = pan_range(ranges.current.y, y_delta)
850
- ranges.current.y2 = pan_range(ranges.current.y2, y2_delta)
851
- }
852
- }
853
-
854
- // Touch handlers for pinch-zoom and two-finger pan
855
- function handle_touch_start(evt: TouchEvent) {
856
- const touch_enabled = pan?.enabled !== false && pan?.touch_enabled !== false
857
- if (!touch_enabled || evt.touches.length !== 2) return
858
-
859
- evt.preventDefault()
860
- const touches = Array.from(evt.touches)
861
- touch_state = {
862
- start_touches: touches.map((touch) => ({ x: touch.clientX, y: touch.clientY })),
863
- initial_x_range: [...ranges.current.x] as [number, number],
864
- initial_x2_range: [...ranges.current.x2] as [number, number],
865
- initial_y_range: [...ranges.current.y] as [number, number],
866
- initial_y2_range: [...ranges.current.y2] as [number, number],
867
- }
868
- }
869
-
870
- function handle_touch_move(evt: TouchEvent) {
871
- if (!touch_state || evt.touches.length !== 2) return
872
- evt.preventDefault()
873
-
874
- const [t1, t2] = Array.from(evt.touches)
875
- const [s1, s2] = touch_state.start_touches
876
-
877
- // Calculate center movement for pan
878
- const start_center = { x: (s1.x + s2.x) / 2, y: (s1.y + s2.y) / 2 }
879
- const curr_center = {
880
- x: (t1.clientX + t2.clientX) / 2,
881
- y: (t1.clientY + t2.clientY) / 2,
882
- }
883
- const dx = curr_center.x - start_center.x
884
- const dy = curr_center.y - start_center.y
885
-
886
- // Calculate pinch scale (curr/start so spread = zoom out, pinch = zoom in)
887
- const start_dist = Math.hypot(s2.x - s1.x, s2.y - s1.y)
888
- // Guard against zero-distance pinch to avoid Infinity scale
889
- if (start_dist < Number.EPSILON) return
890
- const curr_dist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY)
891
- const scale = curr_dist / start_dist
892
-
893
- // If scale changed significantly, treat as pinch-zoom
894
- // Also guard against scale being too small to avoid division by zero
895
- if (Math.abs(scale - 1) > PINCH_ZOOM_THRESHOLD && scale > Number.EPSILON) {
896
- // Pinch zoom centered on gesture center
897
- // Divide by scale so spread (scale > 1) = smaller span (zoom in)
898
- const x_span = touch_state.initial_x_range[1] - touch_state.initial_x_range[0]
899
- const x2_span = touch_state.initial_x2_range[1] -
900
- touch_state.initial_x2_range[0]
901
- const y_span = touch_state.initial_y_range[1] - touch_state.initial_y_range[0]
902
- const y2_span = touch_state.initial_y2_range[1] -
903
- touch_state.initial_y2_range[0]
904
- const x_center =
905
- (touch_state.initial_x_range[0] + touch_state.initial_x_range[1]) / 2
906
- const x2_center =
907
- (touch_state.initial_x2_range[0] + touch_state.initial_x2_range[1]) / 2
908
- const y_center =
909
- (touch_state.initial_y_range[0] + touch_state.initial_y_range[1]) / 2
910
- const y2_center =
911
- (touch_state.initial_y2_range[0] + touch_state.initial_y2_range[1]) / 2
912
-
913
- ranges.current.x = [
914
- x_center - x_span / scale / 2,
915
- x_center + x_span / scale / 2,
916
- ]
917
- ranges.current.x2 = [
918
- x2_center - x2_span / scale / 2,
919
- x2_center + x2_span / scale / 2,
920
- ]
921
- ranges.current.y = [
922
- y_center - y_span / scale / 2,
923
- y_center + y_span / scale / 2,
924
- ]
925
- ranges.current.y2 = [
926
- y2_center - y2_span / scale / 2,
927
- y2_center + y2_span / scale / 2,
928
- ]
929
- } else {
930
- // Pan
931
- const x_delta = pixels_to_data_delta(
932
- -dx,
933
- touch_state.initial_x_range,
934
- chart_width,
935
- )
936
- const x2_delta = pixels_to_data_delta(
937
- -dx,
938
- touch_state.initial_x2_range,
939
- chart_width,
940
- )
941
- const y_delta = pixels_to_data_delta(
942
- dy,
943
- touch_state.initial_y_range,
944
- chart_height,
945
- )
946
- const y2_delta = pixels_to_data_delta(
947
- dy,
948
- touch_state.initial_y2_range,
949
- chart_height,
950
- )
951
- ranges.current.x = pan_range(touch_state.initial_x_range, x_delta)
952
- ranges.current.x2 = pan_range(touch_state.initial_x2_range, x2_delta)
953
- ranges.current.y = pan_range(touch_state.initial_y_range, y_delta)
954
- ranges.current.y2 = pan_range(touch_state.initial_y2_range, y2_delta)
955
- }
956
- }
957
-
958
- function handle_touch_end() {
959
- touch_state = null
960
- }
961
-
962
- // Legend data and handlers
963
- let legend_data = $derived.by<LegendItem[]>(() =>
964
- series.map((srs: BarSeries<Metadata>, idx: number) => {
965
- const is_line = srs.render_mode === `line`
966
- const series_markers = srs.markers ?? DEFAULT_MARKERS
967
- const has_line = series_markers === `line` || series_markers === `line+points`
968
- const has_points = series_markers === `points` ||
969
- series_markers === `line+points`
970
- const series_color = srs.color ?? (is_line ? line_state.color : bar_state.color)
971
-
972
- // Get point style for symbol color (handle array or single object)
973
- const first_point_style = Array.isArray(srs.point_style)
974
- ? srs.point_style[0]
975
- : srs.point_style
976
- const first_color_value = srs.color_values?.[0]
977
- const point_color = first_color_value != null
978
- ? color_scale_fn(first_color_value)
979
- : first_point_style?.fill ?? series_color
980
-
981
- if (is_line) {
982
- // Line series: show line and/or symbol based on markers
983
- return {
984
- series_idx: idx,
985
- label: srs.label ?? `Series ${idx + 1}`,
986
- visible: srs.visible ?? true,
987
- legend_group: srs.legend_group,
988
- display_style: {
989
- ...(has_line
990
- ? {
991
- line_color: series_color,
992
- line_dash: srs.line_style?.line_dash,
993
- }
994
- : {}),
995
- ...(has_points
996
- ? {
997
- symbol_type: first_point_style?.symbol_type ??
998
- DEFAULTS.scatter.symbol_type,
999
- symbol_color: point_color,
1000
- }
1001
- : {}),
1002
- },
1003
- }
1004
- }
1005
- // Bar series: show square symbol
1006
- return {
1007
- series_idx: idx,
1008
- label: srs.label ?? `Series ${idx + 1}`,
1009
- visible: srs.visible ?? true,
1010
- legend_group: srs.legend_group,
1011
- display_style: {
1012
- symbol_type: `Square` as const,
1013
- symbol_color: series_color,
1014
- },
1015
- }
1016
- })
1017
- )
1018
-
1019
- function toggle_series_visibility(series_idx: number) {
1020
- if (series_idx >= 0 && series_idx < series.length) {
1021
- series = series.map((srs, idx) =>
1022
- idx === series_idx ? { ...srs, visible: !(srs.visible ?? true) } : srs
1023
- )
1024
- }
1025
- }
1026
-
1027
- function toggle_group_visibility(_group_name: string, series_indices: number[]) {
1028
- // Filter to valid indices upfront (consistent with shared toggle_group_visibility)
1029
- const valid_indices = series_indices.filter((idx) =>
1030
- idx >= 0 && idx < series.length
1031
- )
1032
- if (valid_indices.length === 0) return
1033
-
1034
- const idx_set = new Set(valid_indices)
1035
- // Check if all series in the group are currently visible
1036
- const all_visible = valid_indices.every((idx) => series[idx].visible ?? true)
1037
- // Toggle: if all visible, hide all; otherwise show all
1038
- const new_visibility = !all_visible
1039
- series = series.map((srs, idx) =>
1040
- idx_set.has(idx) ? { ...srs, visible: new_visibility } : srs
1041
- )
1042
- }
1043
-
1044
- // Collect bar and line positions for legend placement
1045
- let bar_points_for_placement = $derived.by(() => {
1046
- if (!width || !height || !visible_series.length) return []
1047
-
1048
- return internal_series.flatMap((srs, series_idx) => {
1049
- if (!(srs?.visible ?? true)) return []
1050
- const is_line = srs.render_mode === `line`
1051
- const series_offsets = stacked_offsets[series_idx] ?? []
1052
- const use_y2 = srs.y_axis === `y2`
1053
- const y_scale = use_y2 ? scales.y2 : scales.y
1054
- const use_x2_pl = srs.x_axis === `x2`
1055
- const x_scale_pl = use_x2_pl ? scales.x2 : scales.x
1056
- return srs.x
1057
- .map((x_val, bar_idx) => {
1058
- const y_val = srs.y[bar_idx]
1059
- const base = !is_line && mode === `stacked`
1060
- ? (series_offsets[bar_idx] ?? 0)
1061
- : 0
1062
- const [bar_x, bar_y] = orientation === `vertical`
1063
- ? [x_scale_pl(x_val), y_scale(base + y_val)]
1064
- : [x_scale_pl(base + y_val), scales.y(x_val)]
1065
- return { x: bar_x, y: bar_y }
1066
- })
1067
- .filter(({ x, y }) => isFinite(x) && isFinite(y))
1068
- })
1069
- })
1070
-
1071
- // Legend placement stability state
1072
- let legend_element = $state<HTMLDivElement | undefined>()
1073
- const legend_hover = create_hover_lock()
1074
- const dim_tracker = create_dimension_tracker()
1075
- let has_initial_legend_placement = $state(false)
1076
-
1077
- // Clear pending hover lock timeout on unmount
1078
- $effect(() => () => legend_hover.cleanup())
1079
-
1080
- // Calculate best legend placement using continuous grid sampling
1081
- let legend_placement = $derived.by(() => {
1082
- const should_show = show_legend !== undefined ? show_legend : series.length > 1
1083
- if (!should_show || !width || !height) return null
1084
-
1085
- // Use measured size if available, otherwise estimate
1086
- const legend_size = legend_element
1087
- ? { width: legend_element.offsetWidth, height: legend_element.offsetHeight }
1088
- : { width: 120, height: 60 }
1089
-
1090
- const result = compute_element_placement({
1091
- plot_bounds: { x: pad.l, y: pad.t, width: chart_width, height: chart_height },
1092
- element_size: legend_size,
1093
- axis_clearance: legend?.axis_clearance,
1094
- exclude_rects: [],
1095
- points: bar_points_for_placement,
1096
- })
1097
-
1098
- return result
1099
- })
1100
-
1101
- // Tweened legend coordinates for smooth animation - create once, update target via effect
1102
- // untrack() explicitly captures initial tween config (intentional - config set once at mount)
1103
- const tweened_legend_coords = new Tween(
1104
- { x: 0, y: 0 },
1105
- untrack(() => ({ duration: 400, ...(legend?.tween ?? {}) })),
1106
- )
1107
-
1108
- // Update legend position with stability checks
1109
- $effect(() => {
1110
- if (!width || !height || !legend_placement) return
1111
-
1112
- // Track dimensions for resize detection
1113
- const dims_changed = dim_tracker.has_changed(width, height)
1114
- if (dims_changed) dim_tracker.update(width, height)
1115
-
1116
- const is_responsive = legend?.responsive ?? false
1117
- // Only update if: resize occurred, OR (not hover-locked AND (responsive OR not yet initially placed))
1118
- const should_update = dims_changed || (!legend_hover.is_locked.current &&
1119
- (is_responsive || !has_initial_legend_placement))
1120
-
1121
- if (should_update) {
1122
- tweened_legend_coords.set(
1123
- { x: legend_placement.x, y: legend_placement.y },
1124
- // Skip animation on initial placement to avoid jump from (0, 0)
1125
- has_initial_legend_placement ? undefined : { duration: 0 },
1126
- )
1127
- // Only lock position after we have actual measured size
1128
- if (legend_element) {
1129
- has_initial_legend_placement = true
1130
- }
1131
- }
1132
- })
1133
-
1134
- // Tooltip state
1135
- let hover_info = $state<BarHandlerProps<Metadata> | null>(null)
1136
- let tooltip_el = $state<HTMLDivElement | undefined>()
1137
-
1138
- function get_bar_data(
1139
- series_idx: number,
1140
- bar_idx: number,
1141
- color: string,
1142
- ): BarHandlerProps<Metadata> {
1143
- const srs = internal_series[series_idx]
1144
- const [x, y] = [srs.x[bar_idx], srs.y[bar_idx]]
1145
- const [orient_x, orient_y] = orientation === `horizontal` ? [y, x] : [x, y]
1146
- const metadata = Array.isArray(srs.metadata)
1147
- ? srs.metadata[bar_idx]
1148
- : srs.metadata
1149
- const label = srs.labels?.[bar_idx] ?? null
1150
- const active_y_axis = srs.y_axis ?? `y1`
1151
- const active_x_axis = srs.x_axis ?? `x1`
1152
- const category_label = category_list[x]
1153
- const coords = {
1154
- x,
1155
- y,
1156
- orient_x,
1157
- orient_y,
1158
- x_axis: active_x_axis === `x2` ? x2_axis : x_axis,
1159
- x2_axis,
1160
- y_axis: active_y_axis === `y2` ? y2_axis : y_axis,
1161
- y2_axis,
1162
- }
1163
- return {
1164
- ...coords,
1165
- metadata,
1166
- color,
1167
- label,
1168
- series_idx,
1169
- bar_idx,
1170
- active_y_axis,
1171
- active_x_axis,
1172
- category_label,
1173
- }
1174
- }
1175
-
1176
- // Find the point closest to the cursor on a polyline overlay (O(n) scan).
1177
- function find_closest_point(
1178
- evt: MouseEvent,
1179
- points: LineSeriesPoint[],
1180
- ): LineSeriesPoint | null {
1181
- const svg_el = (evt.target as Element).closest(`svg`)
1182
- if (!svg_el) return null
1183
- const rect = svg_el.getBoundingClientRect()
1184
- const mx = evt.clientX - rect.left
1185
- const my = evt.clientY - rect.top
1186
- let best: LineSeriesPoint | null = null
1187
- let best_dist = Infinity
1188
- for (const pt of points) {
1189
- const dist = (pt.x - mx) ** 2 + (pt.y - my) ** 2
1190
- if (dist < best_dist) {
1191
- best_dist = dist
1192
- best = pt
1193
- }
1194
- }
1195
- return best
1196
- }
1197
-
1198
- const line_point_fill = (pt: LineSeriesPoint, series_color: string): string =>
1199
- pt.color_value != null
1200
- ? color_scale_fn(pt.color_value)
1201
- : pt.point_style?.fill ?? series_color
1202
-
1203
- const handle_bar_hover =
1204
- (series_idx: number, bar_idx: number, color: string) => (event: MouseEvent) => {
1205
- hovered = true
1206
- hover_info = get_bar_data(series_idx, bar_idx, color)
1207
- change(hover_info)
1208
- on_bar_hover?.({ ...hover_info, event })
1209
- }
1210
-
1211
- // Stack offsets (only for bar series in stacked mode, grouped by y-axis)
1212
- let stacked_offsets = $derived.by(() => {
1213
- if (mode !== `stacked`) return [] as number[][]
1214
- const max_len = Math.max(
1215
- 0,
1216
- ...internal_series.map((srs) => srs.y.length),
1217
- )
1218
- const offsets = internal_series.map(() =>
1219
- Array.from({ length: max_len }, () => 0)
1220
- )
1221
-
1222
- // Separate accumulators for y1 and y2 axes
1223
- const y1_pos_acc = Array.from({ length: max_len }, () => 0)
1224
- const y1_neg_acc = Array.from({ length: max_len }, () => 0)
1225
- const y2_pos_acc = Array.from({ length: max_len }, () => 0)
1226
- const y2_neg_acc = Array.from({ length: max_len }, () => 0)
1227
-
1228
- internal_series.forEach((srs, series_idx) => {
1229
- if (!(srs?.visible ?? true) || srs.render_mode === `line`) return
1230
-
1231
- const use_y2 = srs.y_axis === `y2`
1232
- const pos_acc = use_y2 ? y2_pos_acc : y1_pos_acc
1233
- const neg_acc = use_y2 ? y2_neg_acc : y1_neg_acc
1234
-
1235
- for (let bar_idx = 0; bar_idx < max_len; bar_idx++) {
1236
- const y_val = srs.y[bar_idx] ?? 0
1237
- const acc = y_val >= 0 ? pos_acc : neg_acc
1238
- offsets[series_idx][bar_idx] = acc[bar_idx]
1239
- acc[bar_idx] += y_val
1240
- }
1241
- })
1242
- return offsets
1243
- })
1244
-
1245
- // Calculate group positions for grouped mode (side-by-side bars)
1246
- let group_info = $derived.by(() => {
1247
- if (mode !== `grouped`) return { bar_series_count: 0, bar_series_indices: [] }
1248
- const bar_series_indices = internal_series
1249
- .map((srs, idx) =>
1250
- (srs?.visible ?? true) && srs.render_mode !== `line` ? idx : -1
1251
- )
1252
- .filter((idx) => idx >= 0)
1253
- return { bar_series_count: bar_series_indices.length, bar_series_indices }
1254
- })
1255
-
1256
- // Set theme-aware background when entering fullscreen
1257
- $effect(() => {
1258
- set_fullscreen_bg(wrapper, fullscreen, `--barplot-fullscreen-bg`)
1259
- })
1260
-
1261
- // State accessors for shared axis change handler
1262
- const axis_state: AxisChangeState<BarSeries<Metadata>> = {
1263
- get_axis: (axis) => {
1264
- if (axis === `x`) return x_axis
1265
- if (axis === `x2`) return x2_axis
1266
- if (axis === `y`) return y_axis
1267
- return y2_axis
1268
- },
1269
- set_axis: (axis, config) => {
1270
- // Spread into existing state to preserve merged type structure
1271
- if (axis === `x`) x_axis = { ...x_axis, ...config }
1272
- else if (axis === `x2`) x2_axis = { ...x2_axis, ...config }
1273
- else if (axis === `y`) y_axis = { ...y_axis, ...config }
1274
- else y2_axis = { ...y2_axis, ...config }
1275
- },
1276
- get_series: () => series,
1277
- set_series: (new_series) => (series = new_series),
1278
- get_loading: () => axis_loading,
1279
- set_loading: (axis) => (axis_loading = axis),
1280
- }
1281
-
1282
- // Create shared handler bound to this component's state
1283
- // Using $derived so handler updates when callback props change
1284
- const handle_axis_change = $derived(create_axis_change_handler(
1285
- axis_state,
1286
- data_loader,
1287
- on_axis_change,
1288
- on_error,
1289
- ))
1290
-
1291
- let auto_load_attempted = false // prevent infinite retries on failure
1292
-
1293
- // Auto-load data if series is empty but options exist (runs once)
1294
- $effect(() => {
1295
- if (series.length === 0 && data_loader && !auto_load_attempted) {
1296
- // Check x-axis first, then y-axis
1297
- if (x_axis.options?.length) {
1298
- auto_load_attempted = true
1299
- const first_key = x_axis.selected_key ?? x_axis.options[0].key
1300
- handle_axis_change(`x`, first_key).catch(() => {})
1301
- } else if (y_axis.options?.length) {
1302
- auto_load_attempted = true
1303
- const first_key = y_axis.selected_key ?? y_axis.options[0].key
1304
- handle_axis_change(`y`, first_key).catch(() => {})
1305
- }
1306
- }
1307
- })
1308
- </script>
1309
-
1310
- {#snippet ref_lines_layer(lines: IndexedRefLine[])}
1311
- {#each lines as line (line.id ?? line.idx)}
1312
- <ReferenceLine
1313
- ref_line={line}
1314
- line_idx={line.idx}
1315
- x_min={line.x_axis === `x2` ? ranges.current.x2[0] : ranges.current.x[0]}
1316
- x_max={line.x_axis === `x2` ? ranges.current.x2[1] : ranges.current.x[1]}
1317
- y_min={line.y_axis === `y2` ? ranges.current.y2[0] : ranges.current.y[0]}
1318
- y_max={line.y_axis === `y2` ? ranges.current.y2[1] : ranges.current.y[1]}
1319
- x_scale={scales.x}
1320
- x2_scale={scales.x2}
1321
- y_scale={scales.y}
1322
- y2_scale={scales.y2}
1323
- {clip_path_id}
1324
- hovered_line_idx={hovered_ref_line_idx}
1325
- on_click={(event: RefLineEvent) => {
1326
- line.on_click?.(event)
1327
- on_ref_line_click?.(event)
1328
- }}
1329
- on_hover={(event: RefLineEvent | null) => {
1330
- hovered_ref_line_idx = event?.line_idx ?? null
1331
- line.on_hover?.(event)
1332
- on_ref_line_hover?.(event)
1333
- }}
1334
- />
1335
- {/each}
1336
- {/snippet}
1337
-
1338
- <svelte:window
1339
- onkeydown={(evt) => {
1340
- if (evt.key === `Escape` && fullscreen) {
1341
- evt.preventDefault()
1342
- fullscreen = false
1343
- }
1344
- if (evt.key === `Shift`) shift_held = true
1345
- }}
1346
- onkeyup={(evt) => {
1347
- if (evt.key === `Shift`) shift_held = false
1348
- }}
1349
- />
1350
-
1351
- <div
1352
- bind:this={wrapper}
1353
- bind:clientWidth={width}
1354
- bind:clientHeight={height}
1355
- {...rest}
1356
- class="bar-plot {rest.class ?? ``}"
1357
- class:fullscreen
1358
- >
1359
- {#if width && height}
1360
- <div class="header-controls">
1361
- {@render header_controls?.({ height, width, fullscreen })}
1362
- {#if fullscreen_toggle}
1363
- <FullscreenToggle bind:fullscreen />
1364
- {/if}
1365
- </div>
1366
- <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
1367
- <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
1368
- <svg
1369
- bind:this={svg_element}
1370
- role="application"
1371
- aria-label={rest[`aria-label`] ??
1372
- ([x_axis.label, y_axis.label].filter(Boolean).join(` vs `) || `Bar chart`)}
1373
- tabindex="0"
1374
- onfocusin={() => (is_focused = true)}
1375
- onfocusout={() => (is_focused = false)}
1376
- onmousedown={handle_mouse_down}
1377
- ondblclick={() => {
1378
- // Reset zoom to initial ranges (undo any pan/zoom)
1379
- ranges.current.x = [...ranges.initial.x] as [number, number]
1380
- ranges.current.x2 = [...ranges.initial.x2] as [number, number]
1381
- ranges.current.y = [...ranges.initial.y] as [number, number]
1382
- ranges.current.y2 = [...ranges.initial.y2] as [number, number]
1383
- // Also reset axis props so future data changes recalculate auto ranges
1384
- x_axis = { ...x_axis, range: [null, null] }
1385
- x2_axis = { ...x2_axis, range: [null, null] }
1386
- y_axis = { ...y_axis, range: [null, null] }
1387
- y2_axis = { ...y2_axis, range: [null, null] }
1388
- }}
1389
- onmouseleave={() => {
1390
- hovered = false
1391
- hover_info = null
1392
- change(null)
1393
- on_bar_hover?.(null)
1394
- }}
1395
- onwheel={handle_wheel}
1396
- ontouchstart={handle_touch_start}
1397
- ontouchmove={handle_touch_move}
1398
- ontouchend={handle_touch_end}
1399
- style:cursor={pan_drag_state
1400
- ? `grabbing`
1401
- : shift_held && pan?.enabled !== false
1402
- ? `grab`
1403
- : `crosshair`}
1404
- >
1405
- <ZoomRect start={drag_state.start} current={drag_state.current} />
1406
-
1407
- <!-- User content (custom overlays, reference lines, etc.) -->
1408
- {@render user_content?.({
1409
- height,
1410
- width,
1411
- x_scale_fn: scales.x,
1412
- x2_scale_fn: scales.x2,
1413
- y_scale_fn: scales.y,
1414
- y2_scale_fn: scales.y2,
1415
- pad,
1416
- x_range: ranges.current.x,
1417
- x2_range: ranges.current.x2,
1418
- y_range: ranges.current.y,
1419
- y2_range: ranges.current.y2,
1420
- fullscreen,
1421
- })}
1422
-
1423
- <!-- Reference lines: below grid (rendered before axes which contain grid lines) -->
1424
- {@render ref_lines_layer(ref_lines_by_z.below_grid)}
1425
-
1426
- <!-- X-axis -->
1427
- <g class="x-axis">
1428
- <line
1429
- x1={pad.l}
1430
- x2={width - pad.r}
1431
- y1={height - pad.b}
1432
- y2={height - pad.b}
1433
- stroke={x_axis.color || `var(--border-color, gray)`}
1434
- stroke-width="1"
1435
- />
1436
- {#each ticks.x as tick (tick)}
1437
- {@const tick_x = scales.x(tick as number)}
1438
- {#if isFinite(tick_x)}
1439
- {@const rotation = x_axis.tick?.label?.rotation ?? 0}
1440
- {@const shift_x = x_axis.tick?.label?.shift?.x ?? 0}
1441
- {@const shift_y = x_axis.tick?.label?.shift?.y ?? 0}
1442
- {@const inside = x_axis.tick?.label?.inside ?? false}
1443
- {@const base_y = inside ? -8 : (rotation !== 0 ? 8 : 18)}
1444
- {@const text_y = base_y + shift_y}
1445
- {@const text_anchor = rotation !== 0 ? (inside ? `end` : `start`) : `middle`}
1446
- {@const dominant_baseline = inside ? `auto` : `hanging`}
1447
- <g class="tick" transform="translate({tick_x}, {height - pad.b})">
1448
- {#if display.x_grid}
1449
- <line
1450
- y1={-(height - pad.b - pad.t)}
1451
- y2="0"
1452
- {...DEFAULT_GRID_STYLE}
1453
- {...(x_axis.grid_style ?? {})}
1454
- />
1455
- {/if}
1456
- <line
1457
- y1="0"
1458
- y2={inside ? -5 : 5}
1459
- stroke={x_axis.color || `var(--border-color, gray)`}
1460
- stroke-width="1"
1461
- />
1462
- <text
1463
- x={shift_x}
1464
- y={text_y}
1465
- text-anchor={text_anchor}
1466
- dominant-baseline={dominant_baseline}
1467
- fill={x_axis.color || `var(--text-color)`}
1468
- transform={rotation !== 0
1469
- ? `rotate(${rotation}, ${shift_x}, ${text_y})`
1470
- : undefined}
1471
- >
1472
- {
1473
- get_tick_label(
1474
- tick as number,
1475
- cat_axis === `x` ? effective_cat_ticks : x_axis.ticks,
1476
- ) ??
1477
- format_value(tick, x_axis.format)
1478
- }
1479
- </text>
1480
- </g>
1481
- {/if}
1482
- {/each}
1483
- {#if x_axis.label || x_axis.options?.length}
1484
- {@const { label_shift, label = ``, options, selected_key, color } = x_axis}
1485
- <AxisLabel
1486
- x={pad.l + chart_width / 2 + (label_shift?.x ?? 0)}
1487
- y={height - (pad.b / 3) + (label_shift?.y ?? 0)}
1488
- {label}
1489
- {options}
1490
- {selected_key}
1491
- loading={axis_loading === `x`}
1492
- axis_type="x"
1493
- {color}
1494
- on_select={(key) => handle_axis_change(`x`, key)}
1495
- />
1496
- {/if}
1497
- </g>
1498
-
1499
- <!-- X2-axis (Top) -->
1500
- <!-- Note: x2 axis is only supported for vertical orientation -->
1501
- {#if x2_series.length > 0 && orientation === `vertical`}
1502
- <g class="x2-axis">
1503
- <line
1504
- x1={pad.l}
1505
- x2={width - pad.r}
1506
- y1={pad.t}
1507
- y2={pad.t}
1508
- stroke={x2_axis.color || `var(--border-color, gray)`}
1509
- stroke-width="1"
1510
- />
1511
- {#each ticks.x2 as tick (tick)}
1512
- {@const tick_x = scales.x2(tick as number)}
1513
- {#if isFinite(tick_x)}
1514
- {@const rotation = x2_axis.tick?.label?.rotation ?? 0}
1515
- {@const shift_x = x2_axis.tick?.label?.shift?.x ?? 0}
1516
- {@const shift_y = x2_axis.tick?.label?.shift?.y ?? 0}
1517
- {@const inside = x2_axis.tick?.label?.inside ?? false}
1518
- {@const base_y = inside ? 8 : (rotation !== 0 ? -8 : -18)}
1519
- {@const text_y = base_y + shift_y}
1520
- {@const text_anchor = rotation !== 0 ? (inside ? `start` : `end`) : `middle`}
1521
- {@const dominant_baseline = inside ? `hanging` : `auto`}
1522
- <g class="tick" transform="translate({tick_x}, {pad.t})">
1523
- {#if display.x2_grid}
1524
- <line
1525
- y1="0"
1526
- y2={height - pad.b - pad.t}
1527
- {...DEFAULT_GRID_STYLE}
1528
- {...(x2_axis.grid_style ?? {})}
1529
- />
1530
- {/if}
1531
- <line
1532
- y1={inside ? 5 : 0}
1533
- y2={inside ? 0 : -5}
1534
- stroke={x2_axis.color || `var(--border-color, gray)`}
1535
- stroke-width="1"
1536
- />
1537
- <text
1538
- x={shift_x}
1539
- y={text_y}
1540
- text-anchor={text_anchor}
1541
- dominant-baseline={dominant_baseline}
1542
- fill={x2_axis.color || `var(--text-color)`}
1543
- transform={rotation !== 0
1544
- ? `rotate(${rotation}, ${shift_x}, ${text_y})`
1545
- : undefined}
1546
- >
1547
- {
1548
- get_tick_label(tick as number, x2_axis.ticks) ??
1549
- format_value(tick, x2_axis.format)
1550
- }
1551
- </text>
1552
- </g>
1553
- {/if}
1554
- {/each}
1555
- {#if x2_axis.label || x2_axis.options?.length}
1556
- {@const { label_shift, label = ``, options, selected_key, color } = x2_axis}
1557
- <AxisLabel
1558
- x={pad.l + chart_width / 2 + (label_shift?.x ?? 0)}
1559
- y={Math.max(12, pad.t - (label_shift?.y ?? 40))}
1560
- {label}
1561
- {options}
1562
- {selected_key}
1563
- loading={axis_loading === `x2`}
1564
- axis_type="x2"
1565
- {color}
1566
- on_select={(key) => handle_axis_change(`x2`, key)}
1567
- />
1568
- {/if}
1569
- </g>
1570
- {/if}
1571
-
1572
- <!-- Y-axis -->
1573
- <g class="y-axis">
1574
- <line
1575
- x1={pad.l}
1576
- x2={pad.l}
1577
- y1={pad.t}
1578
- y2={height - pad.b}
1579
- stroke={y_axis.color || `var(--border-color, gray)`}
1580
- stroke-width="1"
1581
- />
1582
- {#each ticks.y as tick (tick)}
1583
- {@const tick_y = scales.y(tick as number)}
1584
- {#if isFinite(tick_y)}
1585
- {@const rotation = y_axis.tick?.label?.rotation ?? 0}
1586
- {@const shift_x = y_axis.tick?.label?.shift?.x ?? 0}
1587
- {@const shift_y = y_axis.tick?.label?.shift?.y ?? 0}
1588
- {@const inside = y_axis.tick?.label?.inside ?? false}
1589
- {@const base_x = inside ? 8 : -10}
1590
- {@const text_x = base_x + shift_x}
1591
- {@const text_anchor = inside ? `start` : `end`}
1592
- <g class="tick" transform="translate({pad.l}, {tick_y})">
1593
- {#if display.y_grid}
1594
- <line
1595
- x1="0"
1596
- x2={width - pad.l - pad.r}
1597
- {...DEFAULT_GRID_STYLE}
1598
- {...(y_axis.grid_style ?? {})}
1599
- />
1600
- {/if}
1601
- <line
1602
- x1={inside ? 0 : -5}
1603
- x2={inside ? 5 : 0}
1604
- stroke={y_axis.color || `var(--border-color, gray)`}
1605
- stroke-width="1"
1606
- />
1607
- <text
1608
- x={text_x}
1609
- y={shift_y}
1610
- text-anchor={text_anchor}
1611
- dominant-baseline="central"
1612
- fill={y_axis.color || `var(--text-color)`}
1613
- transform={rotation !== 0
1614
- ? `rotate(${rotation}, ${text_x}, ${shift_y})`
1615
- : undefined}
1616
- >
1617
- {
1618
- get_tick_label(
1619
- tick as number,
1620
- cat_axis === `y` ? effective_cat_ticks : y_axis.ticks,
1621
- ) ??
1622
- format_value(tick, y_axis.format)
1623
- }
1624
- </text>
1625
- </g>
1626
- {/if}
1627
- {/each}
1628
- {#if y_axis.label || y_axis.options?.length}
1629
- {@const { label_shift, label = ``, options, selected_key, color, tick } = y_axis}
1630
- {@const y_inside = tick?.label?.inside ?? false}
1631
- <AxisLabel
1632
- x={Math.max(
1633
- 12,
1634
- pad.l - (y_inside ? 0 : tick_label_widths.y_max) - LABEL_GAP_DEFAULT,
1635
- ) +
1636
- (label_shift?.x ?? 0)}
1637
- y={pad.t + chart_height / 2 + (label_shift?.y ?? 0)}
1638
- rotate
1639
- {label}
1640
- {options}
1641
- {selected_key}
1642
- loading={axis_loading === `y`}
1643
- axis_type="y"
1644
- {color}
1645
- on_select={(key) => handle_axis_change(`y`, key)}
1646
- />
1647
- {/if}
1648
- </g>
1649
-
1650
- <!-- Y2-axis (Right) -->
1651
- <!-- Note: y2 axis is only supported for vertical orientation. Implementing x2 for horizontal mode requires additional complexity. -->
1652
- {#if y2_series.length > 0 && orientation === `vertical`}
1653
- <g class="y2-axis">
1654
- <line
1655
- x1={width - pad.r}
1656
- x2={width - pad.r}
1657
- y1={pad.t}
1658
- y2={height - pad.b}
1659
- stroke={y2_axis.color || `var(--border-color, gray)`}
1660
- stroke-width="1"
1661
- />
1662
- {#each ticks.y2 as tick (tick)}
1663
- {@const tick_y = scales.y2(tick as number)}
1664
- {#if isFinite(tick_y)}
1665
- {@const rotation = y2_axis.tick?.label?.rotation ?? 0}
1666
- {@const inside = y2_axis.tick?.label?.inside ?? false}
1667
- {@const base_x = inside ? -8 : 8}
1668
- {@const shift_x = (y2_axis.tick?.label?.shift?.x ?? 0) + base_x}
1669
- {@const shift_y = y2_axis.tick?.label?.shift?.y ?? 0}
1670
- {@const text_anchor = inside ? `end` : `start`}
1671
- <g class="tick" transform="translate({width - pad.r}, {tick_y})">
1672
- {#if display.y2_grid}
1673
- <line
1674
- x1={-(width - pad.l - pad.r)}
1675
- x2="0"
1676
- {...DEFAULT_GRID_STYLE}
1677
- {...(y2_axis.grid_style ?? {})}
1678
- />
1679
- {/if}
1680
- <line
1681
- x1={inside ? -5 : 0}
1682
- x2={inside ? 0 : 5}
1683
- stroke={y2_axis.color || `var(--border-color, gray)`}
1684
- stroke-width="1"
1685
- />
1686
- <text
1687
- x={shift_x}
1688
- y={shift_y}
1689
- text-anchor={text_anchor}
1690
- dominant-baseline="central"
1691
- fill={y2_axis.color || `var(--text-color)`}
1692
- transform={rotation !== 0
1693
- ? `rotate(${rotation}, ${shift_x}, ${shift_y})`
1694
- : undefined}
1695
- >
1696
- {
1697
- get_tick_label(tick as number, y2_axis.ticks) ??
1698
- format_value(tick, y2_axis.format)
1699
- }
1700
- </text>
1701
- </g>
1702
- {/if}
1703
- {/each}
1704
- {#if y2_axis.label || y2_axis.options?.length}
1705
- {@const { label_shift, label = ``, options, selected_key, color, tick } =
1706
- y2_axis}
1707
- {@const inside = tick?.label?.inside ?? false}
1708
- {@const tick_shift = inside ? 0 : (tick?.label?.shift?.x ?? 0) + 8}
1709
- {@const tick_width_contribution = inside ? 0 : tick_label_widths.y2_max}
1710
- <AxisLabel
1711
- x={width - pad.r + tick_shift + tick_width_contribution +
1712
- LABEL_GAP_DEFAULT + (label_shift?.x ?? 0)}
1713
- y={pad.t + chart_height / 2 + (label_shift?.y ?? 0)}
1714
- rotate
1715
- {label}
1716
- {options}
1717
- {selected_key}
1718
- loading={axis_loading === `y2`}
1719
- axis_type="y2"
1720
- {color}
1721
- on_select={(key) => handle_axis_change(`y2`, key)}
1722
- />
1723
- {/if}
1724
- </g>
1725
- {/if}
1726
-
1727
- <!-- Define clip path for chart area -->
1728
- <defs>
1729
- <clipPath id={clip_path_id}>
1730
- <rect x={pad.l} y={pad.t} width={chart_width} height={chart_height} />
1731
- </clipPath>
1732
- </defs>
1733
-
1734
- <!-- Clipped content: zero lines, bars, and lines -->
1735
- <g clip-path="url(#{clip_path_id})">
1736
- <ZeroLines
1737
- {display}
1738
- x_scale_fn={scales.x}
1739
- x2_scale_fn={scales.x2}
1740
- y_scale_fn={scales.y}
1741
- y2_scale_fn={scales.y2}
1742
- x_range={ranges.current.x}
1743
- x2_range={ranges.current.x2}
1744
- y_range={ranges.current.y}
1745
- y2_range={ranges.current.y2}
1746
- x_scale_type={x_axis.scale_type}
1747
- x2_scale_type={x2_axis.scale_type}
1748
- y_scale_type={y_axis.scale_type}
1749
- y2_scale_type={y2_axis.scale_type}
1750
- x_is_time={x_axis.format?.startsWith(`%`) ?? false}
1751
- x2_is_time={x2_axis.format?.startsWith(`%`) ?? false}
1752
- has_x2={x2_series.length > 0}
1753
- has_y2={y2_series.length > 0}
1754
- {width}
1755
- {height}
1756
- {pad}
1757
- />
1758
-
1759
- <!-- Reference lines: below lines -->
1760
- {@render ref_lines_layer(ref_lines_by_z.below_lines)}
1761
-
1762
- <!-- Bars and Lines -->
1763
- {#each internal_series as srs, series_idx (srs?.id ?? series_idx)}
1764
- {#if srs?.visible ?? true}
1765
- {@const is_line = srs.render_mode === `line`}
1766
- <g
1767
- class={is_line ? `line-series` : `bar-series`}
1768
- data-series-idx={series_idx}
1769
- >
1770
- {#if is_line}
1771
- <!-- Render as line -->
1772
- {@const color = srs.color ?? line_state.color ?? `steelblue`}
1773
- {@const stroke_width = srs.line_style?.stroke_width ?? line_state.width ?? 2}
1774
- {@const line_dash = srs.line_style?.line_dash ?? `none`}
1775
- {@const use_y2 = srs.y_axis === `y2`}
1776
- {@const y_scale = use_y2 ? scales.y2 : scales.y}
1777
- {@const use_x2 = srs.x_axis === `x2`}
1778
- {@const x_scale = use_x2 ? scales.x2 : scales.x}
1779
- {@const series_markers = srs.markers ?? DEFAULT_MARKERS}
1780
- {@const show_line = series_markers === `line` ||
1781
- series_markers === `line+points`}
1782
- {@const show_points = series_markers === `points` ||
1783
- series_markers === `line+points`}
1784
- {@const points = srs.x.map((x_val, idx) => {
1785
- const y_val = srs.y[idx]
1786
- // Lines don't stack - they show absolute values (useful for totals/trends)
1787
- const plot_x = orientation === `vertical`
1788
- ? x_scale(x_val)
1789
- : x_scale(y_val)
1790
- const plot_y = orientation === `vertical`
1791
- ? y_scale(y_val)
1792
- : scales.y(x_val)
1793
- // Create internal point with all needed data
1794
- const color_value = srs.color_values?.[idx] ?? null
1795
- const size_value = srs.size_values?.[idx] ?? null
1796
- const point_style = process_prop(srs.point_style, idx)
1797
- const point_hover = process_prop(srs.point_hover, idx)
1798
- const point_label = process_prop(srs.point_label, idx)
1799
- const point_offset = process_prop(srs.point_offset, idx)
1800
- const metadata = Array.isArray(srs.metadata)
1801
- ? srs.metadata[idx]
1802
- : srs.metadata
1803
- return {
1804
- x: plot_x,
1805
- y: plot_y,
1806
- data_x: x_val,
1807
- data_y: y_val,
1808
- idx,
1809
- color_value,
1810
- size_value,
1811
- point_style,
1812
- point_hover,
1813
- point_label,
1814
- point_offset,
1815
- metadata,
1816
- series_idx,
1817
- point_idx: idx,
1818
- } as LineSeriesPoint
1819
- }).filter((pt) => isFinite(pt.x) && isFinite(pt.y))}
1820
- {@const polyline_str = show_line && points.length > 1
1821
- ? points.map((pt) => `${pt.x},${pt.y}`).join(` `)
1822
- : ``}
1823
- {#if polyline_str}
1824
- <polyline
1825
- points={polyline_str}
1826
- fill="none"
1827
- stroke={color}
1828
- stroke-width={stroke_width}
1829
- stroke-dasharray={line_dash}
1830
- stroke-linejoin="round"
1831
- stroke-linecap="round"
1832
- />
1833
- {/if}
1834
- {#if polyline_str && !show_points && (on_bar_hover || on_bar_click)}
1835
- <!-- svelte-ignore a11y_no_static_element_interactions -->
1836
- <!-- svelte-ignore a11y_click_events_have_key_events -->
1837
- <polyline
1838
- points={polyline_str}
1839
- fill="none"
1840
- stroke="transparent"
1841
- stroke-width={Math.max(10, stroke_width * 3)}
1842
- stroke-linejoin="round"
1843
- stroke-linecap="round"
1844
- style:cursor={on_bar_click ? `pointer` : undefined}
1845
- onmousemove={(evt) => {
1846
- const pt = find_closest_point(evt, points)
1847
- if (!pt) return
1848
- hovered = true
1849
- const fill = line_point_fill(pt, color)
1850
- hover_info = get_bar_data(series_idx, pt.idx, fill)
1851
- change(hover_info)
1852
- on_bar_hover?.({ ...hover_info!, event: evt })
1853
- }}
1854
- onmouseleave={() => {
1855
- change(null)
1856
- hover_info = null
1857
- on_bar_hover?.(null)
1858
- }}
1859
- onclick={(evt) => {
1860
- const pt = find_closest_point(evt, points)
1861
- if (!pt) return
1862
- const fill = line_point_fill(pt, color)
1863
- const bar_data = get_bar_data(series_idx, pt.idx, fill)
1864
- on_bar_click?.({ ...bar_data, event: evt })
1865
- }}
1866
- />
1867
- {/if}
1868
- {#if show_points}
1869
- {@const clickable = on_bar_click || on_point_click}
1870
- {@const get_pt = (evt: Event) => {
1871
- const attr = evt.target instanceof Element
1872
- ? evt.target.closest(`[data-bar-idx]`)?.getAttribute(
1873
- `data-bar-idx`,
1874
- )
1875
- : null
1876
- return points.find((pt) => pt.idx === parseInt(attr ?? ``, 10))
1877
- }}
1878
- {@const set_hover = (
1879
- pt: LineSeriesPoint | null,
1880
- evt: MouseEvent | FocusEvent,
1881
- ) => {
1882
- if (pt) {
1883
- hovered = true
1884
- const fill = line_point_fill(pt, color)
1885
- hover_info = get_bar_data(series_idx, pt.idx, fill)
1886
- change(hover_info)
1887
- } else {
1888
- change(null)
1889
- hover_info = null
1890
- }
1891
- on_bar_hover?.(pt ? { ...hover_info!, event: evt } : null)
1892
- on_point_hover?.(
1893
- pt ? { ...hover_info!, event: evt, point: pt } : null,
1894
- )
1895
- }}
1896
- {@const do_click = (
1897
- pt: LineSeriesPoint,
1898
- evt: MouseEvent | KeyboardEvent,
1899
- ) => {
1900
- const fill = line_point_fill(pt, color)
1901
- const bar_data = get_bar_data(series_idx, pt.idx, fill)
1902
- on_bar_click?.({ ...bar_data, event: evt })
1903
- on_point_click?.({ ...bar_data, event: evt, point: pt })
1904
- }}
1905
- {@const leaving = (evt: MouseEvent | FocusEvent) =>
1906
- (evt.relatedTarget instanceof Element
1907
- ? evt.relatedTarget.closest(`.line-points`)
1908
- : null) !== evt.currentTarget}
1909
- <!-- svelte-ignore a11y_no_noninteractive_element_interactions, a11y_mouse_events_have_key_events -->
1910
- <g
1911
- class="line-points"
1912
- role="group"
1913
- onmouseover={(evt) => {
1914
- const pt = get_pt(evt)
1915
- if (pt) set_hover(pt, evt)
1916
- }}
1917
- onfocusin={(evt) => {
1918
- const pt = get_pt(evt)
1919
- if (pt) set_hover(pt, evt)
1920
- }}
1921
- onmouseout={(evt) => {
1922
- if (leaving(evt)) set_hover(null, evt)
1923
- }}
1924
- onfocusout={(evt) => {
1925
- if (leaving(evt)) set_hover(null, evt)
1926
- }}
1927
- onclick={(evt) => {
1928
- const pt = get_pt(evt)
1929
- if (pt && clickable) do_click(pt, evt)
1930
- }}
1931
- onkeydown={(evt) => {
1932
- const pt = get_pt(evt)
1933
- if (pt && clickable && (evt.key === `Enter` || evt.key === ` `)) {
1934
- evt.preventDefault()
1935
- do_click(pt, evt)
1936
- }
1937
- }}
1938
- >
1939
- {#each points as pt (pt.idx)}
1940
- {@const sty = pt.point_style}
1941
- {@const fl = line_point_fill(pt, color)}
1942
- {@const rad = pt.size_value != null
1943
- ? size_scale_fn(pt.size_value)
1944
- : sty?.radius ?? 4}
1945
- {@const hov = hover_info?.series_idx === series_idx &&
1946
- hover_info?.bar_idx === pt.idx}
1947
- <ScatterPoint
1948
- x={pt.x}
1949
- y={pt.y}
1950
- is_hovered={hov}
1951
- {point_tween}
1952
- style={{
1953
- ...sty,
1954
- radius: rad,
1955
- fill: fl,
1956
- stroke: sty?.stroke ?? `transparent`,
1957
- stroke_width: sty?.stroke_width ?? 1,
1958
- fill_opacity: sty?.fill_opacity ?? 1,
1959
- stroke_opacity: sty?.stroke_opacity ?? 1,
1960
- cursor: clickable ? `pointer` : undefined,
1961
- }}
1962
- hover={pt.point_hover ?? {}}
1963
- label={pt.point_label ?? {}}
1964
- offset={pt.point_offset ?? { x: 0, y: 0 }}
1965
- origin={{ x: plot_center_x, y: plot_center_y }}
1966
- --point-fill-color={fl}
1967
- data-bar-idx={pt.idx}
1968
- tabindex={clickable ? (hov ? 0 : -1) : undefined}
1969
- />
1970
- {/each}
1971
- </g>
1972
- {/if}
1973
- {:else}
1974
- <!-- Render as bars -->
1975
- {#each srs.x as x_val, bar_idx (bar_idx)}
1976
- {@const y_val = srs.y[bar_idx]}
1977
- {@const base = mode === `stacked`
1978
- ? (stacked_offsets[series_idx]?.[bar_idx] ?? 0)
1979
- : 0}
1980
- {@const color = srs.color ?? bar_state.color ?? `steelblue`}
1981
- {@const bar_width_val = Array.isArray(srs.bar_width)
1982
- ? (srs.bar_width[bar_idx] ?? 0.5)
1983
- : (srs.bar_width ?? 0.5)}
1984
- {@const half = mode === `grouped` && group_info.bar_series_count > 1
1985
- ? bar_width_val / (2 * group_info.bar_series_count)
1986
- : bar_width_val / 2}
1987
- {@const calculate_group_offset = (idx: number) => {
1988
- const position = group_info.bar_series_indices.indexOf(idx)
1989
- const offset = position - (group_info.bar_series_count - 1) / 2
1990
- return offset * (bar_width_val / group_info.bar_series_count)
1991
- }}
1992
- {@const group_offset = mode === `grouped` && group_info.bar_series_count > 1
1993
- ? calculate_group_offset(series_idx)
1994
- : 0}
1995
- {@const is_vertical = orientation === `vertical`}
1996
- {@const cat_val = x_val}
1997
- {@const val = y_val}
1998
- {@const use_y2 = srs.y_axis === `y2`}
1999
- {@const y_scale = use_y2 ? scales.y2 : scales.y}
2000
- {@const use_x2_bar = srs.x_axis === `x2`}
2001
- {@const x_scale_bar = use_x2_bar ? scales.x2 : scales.x}
2002
- {@const [cat_scale, val_scale] = is_vertical
2003
- ? [x_scale_bar, y_scale]
2004
- : [scales.y, x_scale_bar]}
2005
- {@const c0 = cat_scale(cat_val + group_offset - half)}
2006
- {@const c1 = cat_scale(cat_val + group_offset + half)}
2007
- {@const v0 = val_scale(base)}
2008
- {@const v1 = val_scale(base + val)}
2009
- {@const [rect_x, rect_y] = is_vertical
2010
- ? [Math.min(c0, c1), Math.min(v0, v1)]
2011
- : [Math.min(v0, v1), Math.min(c0, c1)]}
2012
- {@const [rect_w, rect_h] = is_vertical
2013
- ? [Math.max(1, Math.abs(c1 - c0)), Math.max(0, Math.abs(v1 - v0))]
2014
- : [Math.max(1, Math.abs(v1 - v0)), Math.max(0, Math.abs(c1 - c0))]}
2015
- {#if (is_vertical ? rect_h : rect_w) > 0}
2016
- <path
2017
- d={bar_path(
2018
- rect_x,
2019
- rect_y,
2020
- rect_w,
2021
- rect_h,
2022
- Math.min(bar_state.border_radius ?? 0, rect_w / 2, rect_h / 2),
2023
- is_vertical,
2024
- )}
2025
- fill={color}
2026
- opacity={mode === `overlay` ? bar_state.opacity : 1}
2027
- stroke={bar_state.stroke_color}
2028
- stroke-opacity={bar_state.stroke_opacity}
2029
- stroke-width={bar_state.stroke_width}
2030
- role="button"
2031
- tabindex="0"
2032
- aria-label={`bar ${bar_idx + 1} of ${srs.label ?? `series`}`}
2033
- style:cursor={on_bar_click ? `pointer` : undefined}
2034
- onmousemove={handle_bar_hover(series_idx, bar_idx, color)}
2035
- onmouseleave={() => {
2036
- hover_info = null
2037
- change(null)
2038
- on_bar_hover?.(null)
2039
- }}
2040
- onclick={(evt) =>
2041
- on_bar_click?.({
2042
- ...get_bar_data(series_idx, bar_idx, color),
2043
- event: evt,
2044
- })}
2045
- onkeydown={(evt) => {
2046
- if (evt.key === `Enter` || evt.key === ` `) {
2047
- evt.preventDefault()
2048
- on_bar_click?.({
2049
- ...get_bar_data(series_idx, bar_idx, color),
2050
- event: evt,
2051
- })
2052
- }
2053
- }}
2054
- />
2055
- {#if srs.labels?.[bar_idx]}
2056
- <text
2057
- x={is_vertical ? (c0 + c1) / 2 : Math.max(v0, v1) + 4}
2058
- y={is_vertical ? Math.max(0, Math.min(v0, v1) - 6) : (c0 + c1) / 2}
2059
- text-anchor={is_vertical ? `middle` : undefined}
2060
- dominant-baseline={is_vertical ? undefined : `central`}
2061
- class="bar-label"
2062
- >
2063
- {srs.labels[bar_idx]}
2064
- </text>
2065
- {/if}
2066
- {/if}
2067
- {/each}
2068
- {/if}
2069
- </g>
2070
- {/if}
2071
- {/each}
2072
-
2073
- <!-- Reference lines: below points -->
2074
- {@render ref_lines_layer(ref_lines_by_z.below_points)}
2075
-
2076
- <!-- Reference lines: above all -->
2077
- {@render ref_lines_layer(ref_lines_by_z.above_all)}
2078
- </g>
2079
- </svg>
2080
-
2081
- <!-- Legend -->
2082
- {#if legend && series.length > 1}
2083
- <PlotLegend
2084
- bind:root_element={legend_element}
2085
- {...legend}
2086
- series_data={legend_data}
2087
- on_toggle={legend?.on_toggle || toggle_series_visibility}
2088
- on_group_toggle={legend?.on_group_toggle || toggle_group_visibility}
2089
- on_hover_change={legend_hover.set_locked}
2090
- style={`
2091
- position: absolute;
2092
- left: ${legend_placement ? tweened_legend_coords.current.x : pad.l + 10}px;
2093
- top: ${legend_placement ? tweened_legend_coords.current.y : pad.t + 10}px;
2094
- pointer-events: auto;
2095
- ${legend?.style || ``}
2096
- `}
2097
- />
2098
- {/if}
2099
-
2100
- {#if hover_info && hovered}
2101
- {@const cx = (hover_info.active_x_axis === `x2` ? scales.x2 : scales.x)(
2102
- hover_info.orient_x,
2103
- )}
2104
- {@const cy = (hover_info.active_y_axis === `y2` ? scales.y2 : scales.y)(
2105
- hover_info.orient_y,
2106
- )}
2107
- {@const tooltip_pos = constrain_tooltip_position(
2108
- cx,
2109
- cy,
2110
- tooltip_el?.offsetWidth ?? 140,
2111
- tooltip_el?.offsetHeight ?? 50,
2112
- width,
2113
- height,
2114
- { offset_x: 10, offset_y: 5 },
2115
- )}
2116
- <PlotTooltip
2117
- x={tooltip_pos.x}
2118
- y={tooltip_pos.y}
2119
- offset={{ x: 0, y: 0 }}
2120
- bg_color={hover_info.color}
2121
- bind:wrapper={tooltip_el}
2122
- >
2123
- {#if tooltip}
2124
- {@render tooltip({ ...hover_info, fullscreen })}
2125
- {:else}
2126
- {@const series_label = series[hover_info.series_idx]?.label}
2127
- {#if series.length > 1 && series_label}
2128
- <div><strong>{series_label}</strong></div>
2129
- {/if}
2130
- <div>
2131
- {@html sanitize_html(hover_info.x_axis.label || `x`)}: {
2132
- (cat_axis === `x` ? hover_info.category_label : undefined) ??
2133
- format_value(hover_info.orient_x, hover_info.x_axis.format || `.3~s`)
2134
- }
2135
- </div>
2136
- <div>
2137
- {@html sanitize_html(hover_info.y_axis.label || `y`)}: {
2138
- (cat_axis === `y` ? hover_info.category_label : undefined) ??
2139
- format_value(hover_info.orient_y, hover_info.y_axis.format || `.3~s`)
2140
- }
2141
- </div>
2142
- {/if}
2143
- </PlotTooltip>
2144
- {/if}
2145
-
2146
- {#if show_controls}
2147
- <BarPlotControls
2148
- toggle_props={{
2149
- ...controls_toggle_props,
2150
- style: `--ctrl-btn-right: var(--fullscreen-btn-offset, 30px); ${
2151
- controls_toggle_props?.style ?? ``
2152
- }`,
2153
- }}
2154
- pane_props={controls_pane_props}
2155
- bind:show_controls
2156
- bind:controls_open
2157
- bind:orientation
2158
- bind:mode
2159
- bind:x_axis
2160
- bind:x2_axis
2161
- bind:y_axis
2162
- bind:y2_axis
2163
- bind:display
2164
- auto_x_range={auto_ranges.x as Vec2}
2165
- auto_x2_range={auto_ranges.x2 as Vec2}
2166
- auto_y_range={auto_ranges.y as Vec2}
2167
- auto_y2_range={auto_ranges.y2 as Vec2}
2168
- has_x2_points={x2_series.length > 0}
2169
- has_y2_points={y2_series.length > 0}
2170
- children={controls_extra}
2171
- />
2172
- {/if}
2173
- {/if}
2174
-
2175
- <!-- User-provided children (e.g. for custom absolutely-positioned overlays) -->
2176
- {@render children?.({ height, width, fullscreen })}
2177
- </div>
2178
-
2179
- <style>
2180
- .bar-plot {
2181
- position: relative;
2182
- width: 100%;
2183
- height: var(--barplot-height, auto);
2184
- min-height: var(--barplot-min-height, 300px);
2185
- container-type: size;
2186
- z-index: var(--barplot-z-index, auto);
2187
- border-radius: var(--barplot-border-radius, var(--border-radius, 3pt));
2188
- flex: var(--barplot-flex, 1);
2189
- display: var(--barplot-display, flex);
2190
- flex-direction: column;
2191
- background: var(--barplot-bg, var(--plot-bg));
2192
- }
2193
- .bar-plot.fullscreen {
2194
- position: fixed;
2195
- top: 0;
2196
- left: 0;
2197
- width: 100vw !important;
2198
- height: 100vh !important;
2199
- /* Must be higher than Structure.svelte's --struct-buttons-z-index (100000000) */
2200
- z-index: var(--barplot-fullscreen-z-index, 100000001);
2201
- margin: 0;
2202
- border-radius: 0;
2203
- background: var(--barplot-fullscreen-bg, var(--barplot-bg, var(--plot-bg)));
2204
- max-height: none !important;
2205
- overflow: hidden;
2206
- /* Add padding to prevent titles from being cropped at top */
2207
- padding-top: var(--plot-fullscreen-padding-top, 2em);
2208
- box-sizing: border-box;
2209
- }
2210
- .header-controls {
2211
- position: absolute;
2212
- top: var(--ctrl-btn-top, 5pt);
2213
- right: var(--fullscreen-btn-right, 4px);
2214
- z-index: var(--fullscreen-btn-z-index, 10);
2215
- display: flex;
2216
- align-items: center;
2217
- gap: 8px;
2218
- }
2219
- .header-controls :global(.fullscreen-toggle) {
2220
- position: static; /* Override absolute positioning since container handles it */
2221
- opacity: 1; /* Always visible when inside header-controls, container controls visibility */
2222
- }
2223
- /* Hide controls and fullscreen toggles by default, show on hover */
2224
- .bar-plot :global(.pane-toggle),
2225
- .bar-plot .header-controls {
2226
- opacity: 0;
2227
- transition: opacity 0.2s, background-color 0.2s;
2228
- }
2229
- .bar-plot:hover :global(.pane-toggle),
2230
- .bar-plot:hover .header-controls,
2231
- .bar-plot :global(.pane-toggle:focus-visible),
2232
- .bar-plot :global(.pane-toggle[aria-expanded='true']),
2233
- .bar-plot .header-controls:focus-within {
2234
- opacity: 1;
2235
- }
2236
- svg {
2237
- width: var(--barplot-svg-width, 100%);
2238
- height: var(--barplot-svg-height, 100%);
2239
- flex: var(--barplot-svg-flex, 1);
2240
- overflow: var(--barplot-svg-overflow, visible);
2241
- fill: var(--text-color);
2242
- font-weight: var(--scatter-font-weight);
2243
- font-size: var(--scatter-font-size);
2244
- }
2245
- .bar-plot.dragover {
2246
- border: var(--barplot-dragover-border, var(--dragover-border));
2247
- background-color: var(--barplot-dragover-bg, var(--dragover-bg));
2248
- }
2249
- g:is(.x-axis, .x2-axis, .y-axis, .y2-axis) .tick text {
2250
- font-size: var(--tick-font-size, 0.8em);
2251
- }
2252
- .bar-label {
2253
- fill: var(--text-color);
2254
- font-size: 11px;
2255
- }
2256
- </style>