matterviz 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. package/dist/EmptyState.svelte +10 -2
  2. package/dist/FilePicker.svelte +154 -96
  3. package/dist/Icon.svelte +20 -14
  4. package/dist/MillerIndexInput.svelte +27 -21
  5. package/dist/api/optimade.js +6 -6
  6. package/dist/app.css +216 -178
  7. package/dist/brillouin/BrillouinZone.svelte +299 -198
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +74 -55
  11. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte +277 -165
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  15. package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
  16. package/dist/brillouin/compute.js +11 -6
  17. package/dist/chempot-diagram/ChemPotDiagram.svelte +327 -0
  18. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
  19. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +847 -0
  20. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
  21. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +3194 -0
  22. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
  23. package/dist/chempot-diagram/ChemPotScene3D.svelte +11 -0
  24. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
  25. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  26. package/dist/chempot-diagram/async-compute.svelte.js +77 -0
  27. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  28. package/dist/chempot-diagram/chempot-worker.js +11 -0
  29. package/dist/chempot-diagram/color.d.ts +10 -0
  30. package/dist/chempot-diagram/color.js +32 -0
  31. package/dist/chempot-diagram/compute.d.ts +48 -0
  32. package/dist/chempot-diagram/compute.js +812 -0
  33. package/dist/chempot-diagram/index.d.ts +6 -0
  34. package/dist/chempot-diagram/index.js +6 -0
  35. package/dist/chempot-diagram/pointer.d.ts +16 -0
  36. package/dist/chempot-diagram/pointer.js +40 -0
  37. package/dist/chempot-diagram/temperature.d.ts +15 -0
  38. package/dist/chempot-diagram/temperature.js +36 -0
  39. package/dist/chempot-diagram/types.d.ts +86 -0
  40. package/dist/chempot-diagram/types.js +28 -0
  41. package/dist/colors/index.d.ts +3 -1
  42. package/dist/colors/index.js +9 -3
  43. package/dist/composition/BarChart.svelte +141 -77
  44. package/dist/composition/BubbleChart.svelte +107 -52
  45. package/dist/composition/Composition.svelte +100 -79
  46. package/dist/composition/Formula.svelte +108 -62
  47. package/dist/composition/FormulaFilter.svelte +973 -353
  48. package/dist/composition/FormulaFilter.svelte.d.ts +35 -1
  49. package/dist/composition/PieChart.svelte +199 -99
  50. package/dist/composition/PieChart.svelte.d.ts +1 -1
  51. package/dist/composition/format.d.ts +5 -0
  52. package/dist/composition/format.js +20 -3
  53. package/dist/composition/parse.js +14 -9
  54. package/dist/convex-hull/ConvexHull.svelte +93 -38
  55. package/dist/convex-hull/ConvexHull2D.svelte +551 -393
  56. package/dist/convex-hull/ConvexHull3D.svelte +1303 -825
  57. package/dist/convex-hull/ConvexHull4D.svelte +1012 -686
  58. package/dist/convex-hull/ConvexHullControls.svelte +115 -28
  59. package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
  60. package/dist/convex-hull/ConvexHullStats.svelte +821 -249
  61. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
  62. package/dist/convex-hull/ConvexHullTooltip.svelte +41 -16
  63. package/dist/convex-hull/GasPressureControls.svelte +104 -61
  64. package/dist/convex-hull/StructurePopup.svelte +25 -4
  65. package/dist/convex-hull/TemperatureSlider.svelte +45 -25
  66. package/dist/convex-hull/barycentric-coords.js +13 -7
  67. package/dist/convex-hull/demo-temperature.d.ts +6 -0
  68. package/dist/convex-hull/demo-temperature.js +40 -0
  69. package/dist/convex-hull/gas-thermodynamics.js +17 -12
  70. package/dist/convex-hull/helpers.d.ts +10 -1
  71. package/dist/convex-hull/helpers.js +79 -38
  72. package/dist/convex-hull/index.d.ts +1 -0
  73. package/dist/convex-hull/index.js +1 -0
  74. package/dist/convex-hull/thermodynamics.d.ts +8 -21
  75. package/dist/convex-hull/thermodynamics.js +163 -69
  76. package/dist/convex-hull/types.d.ts +12 -12
  77. package/dist/convex-hull/types.js +0 -12
  78. package/dist/coordination/CoordinationBarPlot.svelte +232 -176
  79. package/dist/element/BohrAtom.svelte +56 -13
  80. package/dist/element/ElementHeading.svelte +7 -2
  81. package/dist/element/ElementPhoto.svelte +15 -9
  82. package/dist/element/ElementStats.svelte +10 -4
  83. package/dist/element/ElementTile.svelte +137 -73
  84. package/dist/element/Nucleus.svelte +39 -11
  85. package/dist/element/data.js +2 -14
  86. package/dist/element/data.json.gz +0 -0
  87. package/dist/element/types.d.ts +1 -0
  88. package/dist/feedback/ClickFeedback.svelte +16 -5
  89. package/dist/feedback/DragOverlay.svelte +10 -2
  90. package/dist/feedback/Spinner.svelte +4 -2
  91. package/dist/feedback/StatusMessage.svelte +8 -2
  92. package/dist/fermi-surface/FermiSlice.svelte +118 -88
  93. package/dist/fermi-surface/FermiSurface.svelte +336 -239
  94. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  95. package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
  96. package/dist/fermi-surface/FermiSurfaceScene.svelte +536 -343
  97. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  98. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
  99. package/dist/fermi-surface/compute.js +16 -20
  100. package/dist/fermi-surface/parse.js +37 -33
  101. package/dist/fermi-surface/symmetry.js +2 -7
  102. package/dist/fermi-surface/types.d.ts +3 -5
  103. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1527 -0
  104. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
  105. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
  106. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +30 -0
  107. package/dist/heatmap-matrix/index.d.ts +53 -0
  108. package/dist/heatmap-matrix/index.js +100 -0
  109. package/dist/heatmap-matrix/shared.d.ts +2 -0
  110. package/dist/heatmap-matrix/shared.js +4 -0
  111. package/dist/icons.d.ts +111 -0
  112. package/dist/icons.js +158 -0
  113. package/dist/index.d.ts +5 -2
  114. package/dist/index.js +5 -2
  115. package/dist/io/decompress.js +1 -1
  116. package/dist/io/export.d.ts +3 -0
  117. package/dist/io/export.js +138 -140
  118. package/dist/io/file-drop.d.ts +7 -0
  119. package/dist/io/file-drop.js +43 -0
  120. package/dist/io/index.d.ts +2 -2
  121. package/dist/io/index.js +2 -112
  122. package/dist/io/is-binary.js +2 -3
  123. package/dist/io/types.d.ts +1 -0
  124. package/dist/io/url-drop.d.ts +2 -0
  125. package/dist/io/url-drop.js +117 -0
  126. package/dist/isosurface/Isosurface.svelte +220 -110
  127. package/dist/isosurface/IsosurfaceControls.svelte +65 -28
  128. package/dist/isosurface/parse.js +104 -56
  129. package/dist/isosurface/slice.d.ts +2 -1
  130. package/dist/isosurface/slice.js +8 -13
  131. package/dist/isosurface/types.d.ts +14 -1
  132. package/dist/isosurface/types.js +152 -5
  133. package/dist/labels.d.ts +2 -1
  134. package/dist/labels.js +12 -8
  135. package/dist/layout/FullscreenToggle.svelte +11 -2
  136. package/dist/layout/InfoCard.svelte +38 -6
  137. package/dist/layout/InfoTag.svelte +125 -94
  138. package/dist/layout/PropertyFilter.svelte +82 -37
  139. package/dist/layout/SettingsSection.svelte +85 -55
  140. package/dist/layout/SubpageGrid.svelte +82 -0
  141. package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
  142. package/dist/layout/index.d.ts +1 -0
  143. package/dist/layout/index.js +1 -0
  144. package/dist/layout/json-tree/JsonNode.svelte +266 -223
  145. package/dist/layout/json-tree/JsonTree.svelte +516 -429
  146. package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
  147. package/dist/layout/json-tree/JsonValue.svelte +281 -173
  148. package/dist/layout/json-tree/types.d.ts +10 -2
  149. package/dist/layout/json-tree/utils.d.ts +2 -0
  150. package/dist/layout/json-tree/utils.js +37 -2
  151. package/dist/marching-cubes.js +25 -2
  152. package/dist/math.d.ts +20 -17
  153. package/dist/math.js +474 -57
  154. package/dist/overlays/ContextMenu.svelte +66 -40
  155. package/dist/overlays/DraggablePane.svelte +331 -154
  156. package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
  157. package/dist/periodic-table/PeriodicTable.svelte +278 -145
  158. package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
  159. package/dist/periodic-table/PropertySelect.svelte +25 -7
  160. package/dist/periodic-table/TableInset.svelte +8 -3
  161. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +559 -267
  162. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
  163. package/dist/phase-diagram/PhaseDiagramControls.svelte +131 -51
  164. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
  165. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
  166. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
  167. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +160 -110
  168. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +8 -1
  169. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +217 -86
  170. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
  171. package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
  172. package/dist/phase-diagram/build-diagram.js +9 -9
  173. package/dist/phase-diagram/colors.js +1 -3
  174. package/dist/phase-diagram/index.d.ts +2 -0
  175. package/dist/phase-diagram/index.js +2 -0
  176. package/dist/phase-diagram/parse.js +10 -9
  177. package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
  178. package/dist/phase-diagram/svg-to-diagram.js +869 -0
  179. package/dist/phase-diagram/types.d.ts +10 -0
  180. package/dist/phase-diagram/utils.d.ts +8 -4
  181. package/dist/phase-diagram/utils.js +219 -74
  182. package/dist/plot/AxisLabel.svelte +51 -0
  183. package/dist/plot/AxisLabel.svelte.d.ts +16 -0
  184. package/dist/plot/BarPlot.svelte +1461 -768
  185. package/dist/plot/BarPlot.svelte.d.ts +3 -3
  186. package/dist/plot/BarPlotControls.svelte +33 -6
  187. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  188. package/dist/plot/ColorBar.svelte +533 -383
  189. package/dist/plot/ColorBar.svelte.d.ts +1 -1
  190. package/dist/plot/ColorScaleSelect.svelte +28 -7
  191. package/dist/plot/ElementScatter.svelte +38 -16
  192. package/dist/plot/FillArea.svelte +152 -92
  193. package/dist/plot/Histogram.svelte +1162 -709
  194. package/dist/plot/Histogram.svelte.d.ts +1 -1
  195. package/dist/plot/HistogramControls.svelte +81 -18
  196. package/dist/plot/HistogramControls.svelte.d.ts +6 -2
  197. package/dist/plot/InteractiveAxisLabel.svelte +34 -11
  198. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  199. package/dist/plot/Line.svelte +63 -28
  200. package/dist/plot/PlotControls.svelte +221 -96
  201. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  202. package/dist/plot/PlotLegend.svelte +174 -91
  203. package/dist/plot/PlotTooltip.svelte +45 -6
  204. package/dist/plot/PortalSelect.svelte +175 -146
  205. package/dist/plot/ReferenceLine.svelte +77 -22
  206. package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
  207. package/dist/plot/ReferenceLine3D.svelte +132 -107
  208. package/dist/plot/ReferencePlane.svelte +146 -123
  209. package/dist/plot/ScatterPlot.svelte +1880 -1156
  210. package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
  211. package/dist/plot/ScatterPlot3D.svelte +256 -131
  212. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  213. package/dist/plot/ScatterPlot3DControls.svelte +300 -297
  214. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
  215. package/dist/plot/ScatterPlot3DScene.svelte +608 -406
  216. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  217. package/dist/plot/ScatterPlotControls.svelte +150 -70
  218. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  219. package/dist/plot/ScatterPoint.svelte +98 -26
  220. package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
  221. package/dist/plot/SpacegroupBarPlot.svelte +142 -85
  222. package/dist/plot/Surface3D.svelte +159 -108
  223. package/dist/plot/ZeroLines.svelte +96 -0
  224. package/dist/plot/ZeroLines.svelte.d.ts +32 -0
  225. package/dist/plot/ZoomRect.svelte +23 -0
  226. package/dist/plot/ZoomRect.svelte.d.ts +8 -0
  227. package/dist/plot/axis-utils.d.ts +1 -1
  228. package/dist/plot/axis-utils.js +1 -3
  229. package/dist/plot/data-cleaning.js +12 -28
  230. package/dist/plot/data-transform.js +2 -1
  231. package/dist/plot/fill-utils.js +2 -0
  232. package/dist/plot/index.d.ts +6 -2
  233. package/dist/plot/index.js +6 -2
  234. package/dist/plot/interactions.d.ts +8 -10
  235. package/dist/plot/interactions.js +2 -3
  236. package/dist/plot/layout.d.ts +11 -2
  237. package/dist/plot/layout.js +44 -17
  238. package/dist/plot/reference-line.d.ts +5 -22
  239. package/dist/plot/reference-line.js +12 -84
  240. package/dist/plot/scales.js +24 -36
  241. package/dist/plot/types.d.ts +53 -40
  242. package/dist/plot/types.js +12 -7
  243. package/dist/plot/utils/label-placement.d.ts +32 -15
  244. package/dist/plot/utils/label-placement.js +227 -63
  245. package/dist/plot/utils/series-visibility.js +2 -3
  246. package/dist/plot/utils.d.ts +1 -0
  247. package/dist/plot/utils.js +14 -0
  248. package/dist/rdf/RdfPlot.svelte +173 -132
  249. package/dist/rdf/calc-rdf.js +4 -5
  250. package/dist/sanitize.d.ts +4 -0
  251. package/dist/sanitize.js +107 -0
  252. package/dist/settings.d.ts +21 -6
  253. package/dist/settings.js +63 -19
  254. package/dist/spectral/Bands.svelte +963 -412
  255. package/dist/spectral/Bands.svelte.d.ts +22 -2
  256. package/dist/spectral/BandsAndDos.svelte +90 -49
  257. package/dist/spectral/BrillouinBandsDos.svelte +151 -93
  258. package/dist/spectral/Dos.svelte +389 -258
  259. package/dist/spectral/helpers.d.ts +23 -1
  260. package/dist/spectral/helpers.js +119 -51
  261. package/dist/spectral/types.d.ts +2 -0
  262. package/dist/state.svelte.d.ts +1 -1
  263. package/dist/state.svelte.js +3 -2
  264. package/dist/structure/Arrow.svelte +59 -20
  265. package/dist/structure/AtomLegend.svelte +231 -129
  266. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  267. package/dist/structure/Bond.svelte +73 -47
  268. package/dist/structure/CanvasTooltip.svelte +10 -2
  269. package/dist/structure/CellSelect.svelte +148 -51
  270. package/dist/structure/Cylinder.svelte +33 -17
  271. package/dist/structure/Lattice.svelte +88 -33
  272. package/dist/structure/Structure.svelte +1077 -821
  273. package/dist/structure/Structure.svelte.d.ts +1 -1
  274. package/dist/structure/StructureControls.svelte +373 -139
  275. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  276. package/dist/structure/StructureExportPane.svelte +124 -89
  277. package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
  278. package/dist/structure/StructureInfoPane.svelte +304 -231
  279. package/dist/structure/StructureScene.svelte +919 -445
  280. package/dist/structure/StructureScene.svelte.d.ts +16 -7
  281. package/dist/structure/atom-properties.d.ts +6 -2
  282. package/dist/structure/atom-properties.js +42 -29
  283. package/dist/structure/bonding.js +6 -7
  284. package/dist/structure/export.js +22 -34
  285. package/dist/structure/ferrox-wasm-types.d.ts +3 -2
  286. package/dist/structure/ferrox-wasm-types.js +0 -3
  287. package/dist/structure/ferrox-wasm.d.ts +3 -2
  288. package/dist/structure/ferrox-wasm.js +2 -3
  289. package/dist/structure/index.d.ts +16 -0
  290. package/dist/structure/index.js +88 -6
  291. package/dist/structure/measure.d.ts +2 -2
  292. package/dist/structure/measure.js +4 -44
  293. package/dist/structure/parse.js +130 -155
  294. package/dist/structure/partial-occupancy.d.ts +25 -0
  295. package/dist/structure/partial-occupancy.js +99 -0
  296. package/dist/structure/pbc.d.ts +1 -0
  297. package/dist/structure/pbc.js +16 -6
  298. package/dist/structure/supercell.d.ts +2 -2
  299. package/dist/structure/supercell.js +12 -22
  300. package/dist/structure/validation.js +5 -3
  301. package/dist/symmetry/SymmetryStats.svelte +94 -37
  302. package/dist/symmetry/WyckoffTable.svelte +42 -14
  303. package/dist/symmetry/cell-transform.js +5 -3
  304. package/dist/symmetry/index.d.ts +7 -4
  305. package/dist/symmetry/index.js +87 -21
  306. package/dist/symmetry/spacegroups.js +148 -148
  307. package/dist/table/HeatmapTable.svelte +1112 -516
  308. package/dist/table/HeatmapTable.svelte.d.ts +12 -1
  309. package/dist/table/ToggleMenu.svelte +125 -90
  310. package/dist/table/index.d.ts +2 -0
  311. package/dist/table/index.js +2 -4
  312. package/dist/theme/ThemeControl.svelte +21 -12
  313. package/dist/time.js +4 -1
  314. package/dist/tooltip/TooltipContent.svelte +33 -8
  315. package/dist/trajectory/Trajectory.svelte +889 -687
  316. package/dist/trajectory/TrajectoryError.svelte +14 -3
  317. package/dist/trajectory/TrajectoryExportPane.svelte +148 -90
  318. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
  319. package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
  320. package/dist/trajectory/constants.d.ts +6 -0
  321. package/dist/trajectory/constants.js +7 -0
  322. package/dist/trajectory/extract.js +13 -31
  323. package/dist/trajectory/format-detect.d.ts +9 -0
  324. package/dist/trajectory/format-detect.js +76 -0
  325. package/dist/trajectory/frame-reader.d.ts +17 -0
  326. package/dist/trajectory/frame-reader.js +332 -0
  327. package/dist/trajectory/helpers.d.ts +14 -0
  328. package/dist/trajectory/helpers.js +172 -0
  329. package/dist/trajectory/index.d.ts +1 -0
  330. package/dist/trajectory/index.js +23 -14
  331. package/dist/trajectory/parse/ase.d.ts +2 -0
  332. package/dist/trajectory/parse/ase.js +77 -0
  333. package/dist/trajectory/parse/hdf5.d.ts +2 -0
  334. package/dist/trajectory/parse/hdf5.js +129 -0
  335. package/dist/trajectory/parse/index.d.ts +12 -0
  336. package/dist/trajectory/parse/index.js +299 -0
  337. package/dist/trajectory/parse/lammps.d.ts +5 -0
  338. package/dist/trajectory/parse/lammps.js +179 -0
  339. package/dist/trajectory/parse/vasp.d.ts +2 -0
  340. package/dist/trajectory/parse/vasp.js +68 -0
  341. package/dist/trajectory/parse/xyz.d.ts +2 -0
  342. package/dist/trajectory/parse/xyz.js +110 -0
  343. package/dist/trajectory/plotting.js +13 -8
  344. package/dist/trajectory/types.d.ts +11 -0
  345. package/dist/trajectory/types.js +1 -0
  346. package/dist/utils.d.ts +3 -0
  347. package/dist/utils.js +17 -0
  348. package/dist/xrd/XrdPlot.svelte +337 -245
  349. package/dist/xrd/broadening.js +14 -9
  350. package/dist/xrd/calc-xrd.js +12 -19
  351. package/dist/xrd/parse.d.ts +1 -1
  352. package/dist/xrd/parse.js +17 -17
  353. package/package.json +103 -101
  354. package/readme.md +4 -4
  355. package/dist/trajectory/parse.d.ts +0 -42
  356. package/dist/trajectory/parse.js +0 -1267
  357. /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
  358. /package/dist/theme/{themes.js → themes.mjs} +0 -0
@@ -1,100 +1,183 @@
1
- <script lang="ts">import { onDestroy } from 'svelte';
2
- import { SvelteMap, SvelteSet } from 'svelte/reactivity';
3
- // Unique instance ID to prevent gradient ID collisions when multiple legends render on the same page
4
- const instance_id = crypto.randomUUID().slice(0, 8);
5
- let { series_data = [], layout = `vertical`, layout_tracks = 1, // Default to 1 column/row
6
- style = ``, item_style = ``, collapsed_groups = $bindable(new SvelteSet()), on_toggle = () => { }, on_double_click = () => { }, on_fill_toggle, on_fill_double_click, on_group_toggle, on_group_double_click, on_drag_start = () => { }, on_drag = () => { }, on_drag_end = () => { }, on_hover_change, draggable = true, root_element = $bindable(undefined), ...rest } = $props();
7
- let is_dragging = $state(false);
8
- let drag_start_coords = $state(null);
9
- let grouped_series = $derived.by(() => {
10
- const groups = [];
11
- const group_map = new SvelteMap();
1
+ <script lang="ts">
2
+ import type { LegendItem, Orientation } from './'
3
+ import { sanitize_html } from '../sanitize'
4
+ import { strip_html } from '../table'
5
+ import { onDestroy } from 'svelte'
6
+ import type { HTMLAttributes } from 'svelte/elements'
7
+ import { SvelteMap, SvelteSet } from 'svelte/reactivity'
8
+
9
+ // Unique instance ID to prevent gradient ID collisions when multiple legends render on the same page
10
+ const instance_id = crypto.randomUUID().slice(0, 8)
11
+
12
+ let {
13
+ series_data = [],
14
+ layout = `vertical`,
15
+ layout_tracks = 1, // Default to 1 column/row
16
+ style = ``,
17
+ item_style = ``,
18
+ collapsed_groups = $bindable(new SvelteSet<string>()),
19
+ on_toggle = () => {},
20
+ on_double_click = () => {},
21
+ on_fill_toggle,
22
+ on_fill_double_click,
23
+ on_group_toggle,
24
+ on_group_double_click,
25
+ on_drag_start = () => {},
26
+ on_drag = () => {},
27
+ on_drag_end = () => {},
28
+ on_hover_change,
29
+ draggable = true,
30
+ root_element = $bindable<HTMLDivElement | undefined>(undefined),
31
+ ...rest
32
+ }: Omit<HTMLAttributes<HTMLDivElement>, `style`> & {
33
+ series_data: LegendItem[]
34
+ layout?: Orientation
35
+ layout_tracks?: number // Number of columns for horizontal, rows for vertical
36
+ style?: string // Inline styles forwarded to wrapper div
37
+ item_style?: string
38
+ // Bindable set of collapsed group names (pass initial values to collapse groups by default)
39
+ collapsed_groups?: Set<string>
40
+ on_toggle?: (series_idx: number) => void
41
+ on_double_click?: (series_idx: number) => void
42
+ on_fill_toggle?: (
43
+ source_type: `fill_region` | `error_band`,
44
+ source_idx: number,
45
+ ) => void
46
+ on_fill_double_click?: (
47
+ source_type: `fill_region` | `error_band`,
48
+ source_idx: number,
49
+ ) => void
50
+ on_group_toggle?: (group_name: string, series_indices: number[]) => void
51
+ on_group_double_click?: (group_name: string, series_indices: number[]) => void
52
+ on_drag_start?: (event: MouseEvent) => void
53
+ on_drag?: (event: MouseEvent) => void
54
+ on_drag_end?: (event: MouseEvent) => void
55
+ // Callback when hover state changes (for placement stability)
56
+ on_hover_change?: (is_hovered: boolean) => void
57
+ draggable?: boolean
58
+ // Bindable reference to the root DOM element for size measurements
59
+ root_element?: HTMLDivElement
60
+ } = $props()
61
+
62
+ let is_dragging = $state(false)
63
+ let drag_start_coords = $state<{ x: number; y: number } | null>(null)
64
+
65
+ // Group series by legend_group, preserving order
66
+ type GroupedData = { group_name: string | null; items: LegendItem[] }
67
+ let grouped_series = $derived.by<GroupedData[]>(() => {
68
+ const groups: GroupedData[] = []
69
+ const group_map = new SvelteMap<string | null, LegendItem[]>()
70
+
12
71
  for (const item of series_data) {
13
- const group_key = item.legend_group ?? null;
14
- if (!group_map.has(group_key)) {
15
- group_map.set(group_key, []);
16
- groups.push({ group_name: group_key, items: group_map.get(group_key) });
17
- }
18
- group_map.get(group_key).push(item);
72
+ const group_key = item.legend_group ?? null
73
+ let group_items = group_map.get(group_key)
74
+ if (!group_items) {
75
+ group_items = []
76
+ group_map.set(group_key, group_items)
77
+ groups.push({ group_name: group_key, items: group_items })
78
+ }
79
+ group_items.push(item)
19
80
  }
20
- return groups;
21
- });
22
- // Check if any grouping is present
23
- let has_groups = $derived(grouped_series.some((group) => group.group_name !== null && group.items.length > 0));
24
- function toggle_group_collapse(group_name) {
81
+ return groups
82
+ })
83
+
84
+ // Check if any grouping is present
85
+ let has_groups = $derived(
86
+ grouped_series.some((group) =>
87
+ group.group_name !== null && group.items.length > 0
88
+ ),
89
+ )
90
+
91
+ function toggle_group_collapse(group_name: string) {
25
92
  // Normalize to SvelteSet if a plain Set was passed (ensures reactivity)
26
93
  if (!(collapsed_groups instanceof SvelteSet)) {
27
- collapsed_groups = new SvelteSet(collapsed_groups);
94
+ collapsed_groups = new SvelteSet(collapsed_groups)
28
95
  }
29
96
  // Set.delete returns true if element existed, so add if delete failed
30
- if (!collapsed_groups.delete(group_name))
31
- collapsed_groups.add(group_name);
32
- }
33
- const handle_group_click = (group_name, items) => on_group_toggle?.(group_name, items.map((item) => item.series_idx));
34
- function cleanup_drag_listeners() {
97
+ if (!collapsed_groups.delete(group_name)) collapsed_groups.add(group_name)
98
+ }
99
+
100
+ const handle_group_click = (group_name: string, items: LegendItem[]) =>
101
+ on_group_toggle?.(group_name, items.map((item) => item.series_idx))
102
+
103
+ function cleanup_drag_listeners() {
35
104
  if (is_dragging) {
36
- // Remove global event listeners
37
- window.removeEventListener(`mousemove`, handle_window_mouse_move);
38
- window.removeEventListener(`mouseup`, handle_window_mouse_up);
39
- // Reset cursor and text selection
40
- document.body.style.cursor = `default`;
41
- document.body.style.userSelect = `auto`;
105
+ // Remove global event listeners
106
+ window.removeEventListener(`mousemove`, handle_window_mouse_move)
107
+ window.removeEventListener(`mouseup`, handle_window_mouse_up)
108
+
109
+ // Reset cursor and text selection
110
+ document.body.style.cursor = `default`
111
+ document.body.style.userSelect = `auto`
42
112
  }
43
- }
44
- onDestroy(cleanup_drag_listeners);
45
- function handle_legend_mouse_down(event) {
46
- if (!draggable)
47
- return;
113
+ }
114
+ onDestroy(cleanup_drag_listeners)
115
+
116
+ function handle_legend_mouse_down(event: MouseEvent) {
117
+ if (!draggable) return
118
+
48
119
  // Only start drag if clicking on empty areas (not on legend items)
49
- const target = event.target;
50
- if (target.closest(`.legend-item`))
51
- return;
52
- event.preventDefault();
53
- event.stopPropagation();
54
- is_dragging = true;
55
- drag_start_coords = { x: event.clientX, y: event.clientY };
56
- on_drag_start(event);
120
+ const target = event.target
121
+ if (target instanceof Element && target.closest(`.legend-item`)) return
122
+
123
+ event.preventDefault()
124
+ event.stopPropagation()
125
+
126
+ is_dragging = true
127
+ drag_start_coords = { x: event.clientX, y: event.clientY }
128
+
129
+ on_drag_start(event)
130
+
57
131
  // Add global event listeners
58
- window.addEventListener(`mousemove`, handle_window_mouse_move);
59
- window.addEventListener(`mouseup`, handle_window_mouse_up);
60
- }
61
- function handle_window_mouse_move(event) {
62
- if (!is_dragging || !drag_start_coords)
63
- return;
64
- event.preventDefault();
65
- on_drag(event);
66
- }
67
- function handle_window_mouse_up(event) {
68
- if (!is_dragging)
69
- return;
70
- is_dragging = false;
71
- drag_start_coords = null;
72
- on_drag_end(event);
132
+ window.addEventListener(`mousemove`, handle_window_mouse_move)
133
+ window.addEventListener(`mouseup`, handle_window_mouse_up)
134
+ }
135
+
136
+ function handle_window_mouse_move(event: MouseEvent) {
137
+ if (!is_dragging || !drag_start_coords) return
138
+
139
+ event.preventDefault()
140
+ on_drag(event)
141
+ }
142
+
143
+ function handle_window_mouse_up(event: MouseEvent) {
144
+ if (!is_dragging) return
145
+
146
+ is_dragging = false
147
+ drag_start_coords = null
148
+
149
+ on_drag_end(event)
150
+
73
151
  // Remove global event listeners
74
- window.removeEventListener(`mousemove`, handle_window_mouse_move);
75
- window.removeEventListener(`mouseup`, handle_window_mouse_up);
76
- }
77
- let div_style = $derived({
78
- horizontal: `grid-template-columns: repeat(${layout_tracks}, auto);`,
79
- vertical: `grid-template-rows: repeat(${layout_tracks}, auto); grid-template-columns: auto;`,
80
- }[layout] + style);
81
- // Extracted toggle handlers to reduce duplication
82
- function toggle_item(item) {
83
- if (item.item_type === `fill` && on_fill_toggle && item.fill_source_type &&
84
- item.fill_source_idx !== undefined) {
85
- on_fill_toggle(item.fill_source_type, item.fill_source_idx);
86
- }
87
- else
88
- on_toggle(item.series_idx);
89
- }
90
- function double_click_item(item) {
91
- if (item.item_type === `fill` && on_fill_double_click && item.fill_source_type &&
92
- item.fill_source_idx !== undefined) {
93
- on_fill_double_click(item.fill_source_type, item.fill_source_idx);
94
- }
95
- else
96
- on_double_click(item.series_idx);
97
- }
152
+ window.removeEventListener(`mousemove`, handle_window_mouse_move)
153
+ window.removeEventListener(`mouseup`, handle_window_mouse_up)
154
+ }
155
+
156
+ let div_style = $derived(
157
+ {
158
+ horizontal: `grid-template-columns: repeat(${layout_tracks}, auto);`,
159
+ vertical:
160
+ `grid-template-rows: repeat(${layout_tracks}, auto); grid-template-columns: auto;`,
161
+ }[layout] + style,
162
+ )
163
+
164
+ // Extracted toggle handlers to reduce duplication
165
+ function toggle_item(item: LegendItem) {
166
+ if (
167
+ item.item_type === `fill` && on_fill_toggle && item.fill_source_type &&
168
+ item.fill_source_idx !== undefined
169
+ ) {
170
+ on_fill_toggle(item.fill_source_type, item.fill_source_idx)
171
+ } else on_toggle(item.series_idx)
172
+ }
173
+ function double_click_item(item: LegendItem) {
174
+ if (
175
+ item.item_type === `fill` && on_fill_double_click && item.fill_source_type &&
176
+ item.fill_source_idx !== undefined
177
+ ) {
178
+ on_fill_double_click(item.fill_source_type, item.fill_source_idx)
179
+ } else on_double_click(item.series_idx)
180
+ }
98
181
  </script>
99
182
 
100
183
  {#snippet legend_item(series: LegendItem, indent: boolean = false)}
@@ -124,7 +207,7 @@ function double_click_item(item) {
124
207
  role="button"
125
208
  tabindex="0"
126
209
  aria-pressed={series.visible}
127
- aria-label="Toggle visibility for {series.label}"
210
+ aria-label="Toggle visibility for {strip_html(series.label)}"
128
211
  >
129
212
  <span class="legend-marker">
130
213
  <!-- Fill region swatch -->
@@ -213,7 +296,7 @@ function double_click_item(item) {
213
296
  {/if}
214
297
  {/if}
215
298
  </span>
216
- <span class="legend-label">{@html series.label}</span>
299
+ <span class="legend-label">{@html sanitize_html(series.label)}</span>
217
300
  </div>
218
301
  {/snippet}
219
302
 
@@ -256,7 +339,7 @@ function double_click_item(item) {
256
339
  role="button"
257
340
  tabindex="0"
258
341
  aria-expanded={!is_collapsed}
259
- aria-label="Toggle group {group_name}"
342
+ aria-label="Toggle group {strip_html(group_name)}"
260
343
  >
261
344
  <span
262
345
  class="group-chevron"
@@ -275,11 +358,11 @@ function double_click_item(item) {
275
358
  }}
276
359
  role="button"
277
360
  tabindex="0"
278
- aria-label="{is_collapsed ? `Expand` : `Collapse`} group {group_name}"
361
+ aria-label="{is_collapsed ? `Expand` : `Collapse`} group {strip_html(group_name)}"
279
362
  >
280
363
 
281
364
  </span>
282
- <span class="group-label">{@html group_name}</span>
365
+ <span class="group-label">{@html sanitize_html(group_name)}</span>
283
366
  </div>
284
367
  <!-- Group items (collapsible) -->
285
368
  {#if !is_collapsed}
@@ -1,9 +1,48 @@
1
- <script lang="ts">import { luminance } from '../colors';
2
- let { x, y, bg_color, offset = { x: 6, y: 0 }, fixed = false, wrapper = $bindable(), children, ...rest } = $props();
3
- // Auto-compute contrasting text color based on background luminance only if bg_color is defined
4
- const text_color = $derived(bg_color != null ? (luminance(bg_color) > 0.5 ? `#000000` : `#ffffff`) : null);
5
- const style = $derived(`position: ${fixed ? `fixed` : `absolute`}; pointer-events: none;
6
- left: ${x + offset.x}px; top: ${y + offset.y}px; ${rest.style ?? ``}`);
1
+ <script lang="ts">
2
+ import { luminance } from '../colors'
3
+ import type { Snippet } from 'svelte'
4
+ import type { HTMLAttributes } from 'svelte/elements'
5
+
6
+ let {
7
+ x,
8
+ y,
9
+ bg_color,
10
+ offset = { x: 6, y: 0 },
11
+ fixed = false,
12
+ wrapper = $bindable(),
13
+ children,
14
+ ...rest
15
+ }: HTMLAttributes<HTMLDivElement> & {
16
+ x: number
17
+ y: number
18
+ bg_color?: string | null
19
+ offset?: { x: number; y: number }
20
+ fixed?: boolean // Use position: fixed (for viewport coords) vs absolute
21
+ wrapper?: HTMLDivElement // Bindable reference for measuring tooltip size
22
+ children: Snippet
23
+ } = $props()
24
+
25
+ // Auto-compute contrasting text color based on background luminance only if bg_color is defined
26
+ const text_color = $derived(
27
+ bg_color != null ? (luminance(bg_color) > 0.5 ? `#000000` : `#ffffff`) : null,
28
+ )
29
+
30
+ // For fixed positioning (viewport coords), flip to opposite side when near viewport edges
31
+ const pos = $derived.by(() => {
32
+ const raw_x = x + offset.x
33
+ const raw_y = y + offset.y
34
+ if (!fixed) return { x: raw_x, y: raw_y }
35
+ const tw = wrapper?.offsetWidth ?? 0
36
+ const th = wrapper?.offsetHeight ?? 0
37
+ const cx = raw_x + tw > globalThis.innerWidth ? x - Math.abs(offset.x) - tw : raw_x
38
+ const cy = raw_y + th > globalThis.innerHeight ? y - Math.abs(offset.y) - th : raw_y
39
+ return { x: Math.max(0, cx), y: Math.max(0, cy) }
40
+ })
41
+
42
+ const style = $derived(
43
+ `position: ${fixed ? `fixed` : `absolute`}; pointer-events: none;
44
+ left: ${pos.x}px; top: ${pos.y}px; ${rest.style ?? ``}`,
45
+ )
7
46
  </script>
8
47
 
9
48
  <div