matterviz 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EmptyState.svelte +10 -4
- package/dist/FilePicker.svelte +12 -14
- package/dist/Icon.svelte +7 -4
- package/dist/MillerIndexInput.svelte +2 -2
- package/dist/app.css +53 -0
- package/dist/brillouin/BrillouinZone.svelte +75 -85
- package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
- package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
- package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
- package/dist/brillouin/BrillouinZoneScene.svelte +26 -39
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +62 -74
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +511 -547
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/async-compute.svelte.js +1 -1
- package/dist/chempot-diagram/controls-state.svelte.js +1 -1
- package/dist/colors/index.d.ts +0 -4
- package/dist/colors/index.js +19 -20
- package/dist/composition/BarChart.svelte +37 -31
- package/dist/composition/BubbleChart.svelte +17 -17
- package/dist/composition/Composition.svelte +7 -11
- package/dist/composition/Formula.svelte +18 -25
- package/dist/composition/FormulaFilter.svelte +92 -95
- package/dist/composition/PieChart.svelte +55 -41
- package/dist/composition/format.js +1 -1
- package/dist/composition/index.d.ts +2 -0
- package/dist/composition/index.js +14 -0
- package/dist/composition/parse.d.ts +2 -2
- package/dist/composition/parse.js +11 -10
- package/dist/constants.js +11 -9
- package/dist/convex-hull/ConvexHull.svelte +12 -15
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +93 -92
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +109 -140
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +75 -94
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
- package/dist/convex-hull/ConvexHullControls.svelte +46 -48
- package/dist/convex-hull/ConvexHullStats.svelte +193 -195
- package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
- package/dist/convex-hull/GasPressureControls.svelte +5 -12
- package/dist/convex-hull/StructurePopup.svelte +17 -21
- package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
- package/dist/convex-hull/TemperatureSlider.svelte +4 -10
- package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
- package/dist/convex-hull/helpers.d.ts +8 -10
- package/dist/convex-hull/helpers.js +36 -36
- package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
- package/dist/convex-hull/thermodynamics.js +18 -17
- package/dist/coordination/CoordinationBarPlot.svelte +38 -33
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/coordination/calc-coordination.d.ts +1 -1
- package/dist/coordination/calc-coordination.js +28 -25
- package/dist/element/BohrAtom.svelte +5 -8
- package/dist/element/ElementHeading.svelte +4 -1
- package/dist/element/ElementPhoto.svelte +11 -9
- package/dist/element/ElementStats.svelte +12 -10
- package/dist/element/ElementTile.svelte +24 -29
- package/dist/element/Nucleus.svelte +4 -2
- package/dist/element/data.d.ts +1 -2
- package/dist/element/helpers.d.ts +4 -0
- package/dist/element/helpers.js +18 -0
- package/dist/element/index.d.ts +1 -4
- package/dist/element/index.js +3 -18
- package/dist/feedback/DragOverlay.svelte +5 -5
- package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
- package/dist/feedback/StatusMessage.svelte +7 -4
- package/dist/fermi-surface/FermiSlice.svelte +21 -18
- package/dist/fermi-surface/FermiSurface.svelte +14 -22
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -7
- package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +37 -64
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
- package/dist/fermi-surface/compute.js +3 -3
- package/dist/fermi-surface/parse.js +22 -24
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +109 -148
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
- package/dist/heatmap-matrix/index.d.ts +5 -0
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +4 -0
- package/dist/io/ExportPane.svelte +10 -6
- package/dist/io/decompress.d.ts +2 -1
- package/dist/io/decompress.js +22 -35
- package/dist/io/export.d.ts +4 -0
- package/dist/io/export.js +5 -1
- package/dist/io/fetch.d.ts +0 -3
- package/dist/io/fetch.js +0 -11
- package/dist/io/index.d.ts +0 -1
- package/dist/io/index.js +2 -9
- package/dist/io/is-binary.d.ts +9 -0
- package/dist/io/is-binary.js +45 -1
- package/dist/io/url-drop.js +13 -25
- package/dist/isosurface/Isosurface.svelte +17 -23
- package/dist/isosurface/IsosurfaceControls.svelte +37 -42
- package/dist/isosurface/parse-vaspwave.d.ts +3 -0
- package/dist/isosurface/parse-vaspwave.js +138 -0
- package/dist/isosurface/parse.js +6 -6
- package/dist/labels.d.ts +6 -2
- package/dist/labels.js +43 -13
- package/dist/layout/FullscreenButton.svelte +2 -1
- package/dist/layout/FullscreenToggle.svelte +10 -4
- package/dist/layout/InfoCard.svelte +7 -18
- package/dist/layout/InfoTag.svelte +1 -3
- package/dist/layout/NumberRangeInput.svelte +46 -0
- package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
- package/dist/layout/PropertyFilter.svelte +2 -6
- package/dist/layout/SettingsSection.svelte +21 -17
- package/dist/layout/SubpageGrid.svelte +3 -1
- package/dist/layout/ViewerChrome.svelte +9 -10
- package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
- package/dist/layout/fullscreen.js +3 -5
- package/dist/layout/fullscreen.svelte.js +1 -2
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/layout/json-tree/JsonNode.svelte +8 -11
- package/dist/layout/json-tree/JsonTree.svelte +53 -77
- package/dist/layout/json-tree/JsonValue.svelte +7 -15
- package/dist/layout/json-tree/utils.js +14 -23
- package/dist/math.d.ts +2 -0
- package/dist/math.js +19 -0
- package/dist/overlays/ContextMenu.svelte +4 -2
- package/dist/overlays/CopyButton.svelte +11 -5
- package/dist/overlays/DragControlTab.svelte +6 -1
- package/dist/overlays/DraggablePane.svelte +81 -26
- package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
- package/dist/overlays/GlassChip.svelte +30 -0
- package/dist/overlays/GlassChip.svelte.d.ts +8 -0
- package/dist/overlays/InfoPaneCards.svelte +11 -23
- package/dist/overlays/index.d.ts +7 -0
- package/dist/overlays/index.js +26 -0
- package/dist/overlays/portal.d.ts +2 -0
- package/dist/overlays/portal.js +14 -0
- package/dist/periodic-table/PeriodicTable.svelte +113 -145
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
- package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
- package/dist/periodic-table/TableInset.svelte +9 -4
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
- package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
- package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
- package/dist/phase-diagram/build-diagram.js +3 -3
- package/dist/phase-diagram/diagram-input.d.ts +1 -2
- package/dist/phase-diagram/parse.js +15 -15
- package/dist/phase-diagram/svg-to-diagram.js +21 -15
- package/dist/phase-diagram/utils.js +2 -3
- package/dist/plot/bar/BarPlot.svelte +430 -391
- package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
- package/dist/plot/bar/BarPlotControls.svelte +1 -3
- package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
- package/dist/plot/bar/SpacegroupBarPlot.svelte +29 -36
- package/dist/plot/bar/data.d.ts +5 -4
- package/dist/plot/bar/data.js +2 -1
- package/dist/plot/box/BoxPlot.svelte +301 -209
- package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
- package/dist/plot/box/Violin.svelte.d.ts +1 -0
- package/dist/plot/box/box-plot.js +1 -1
- package/dist/plot/core/auto-place.js +1 -1
- package/dist/plot/core/axis-utils.d.ts +12 -7
- package/dist/plot/core/axis-utils.js +48 -48
- package/dist/plot/core/components/AxisLabel.svelte +82 -20
- package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
- package/dist/plot/core/components/ColorBar.svelte +101 -106
- package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
- package/dist/plot/core/components/FillArea.svelte +10 -17
- package/dist/plot/core/components/HierarchyControls.svelte +249 -0
- package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
- package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
- package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/core/components/Line.svelte +18 -9
- package/dist/plot/core/components/Line.svelte.d.ts +2 -0
- package/dist/plot/core/components/PlotAxis.svelte +40 -17
- package/dist/plot/core/components/PlotControls.svelte +65 -41
- package/dist/plot/core/components/PlotLegend.svelte +31 -35
- package/dist/plot/core/components/PlotMarginals.svelte +616 -0
- package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
- package/dist/plot/core/components/PlotTooltip.svelte +1 -1
- package/dist/plot/core/components/PortalSelect.svelte +4 -8
- package/dist/plot/core/components/ReferenceLine.svelte +27 -24
- package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
- package/dist/plot/core/components/ReferencePlane.svelte +7 -8
- package/dist/plot/core/components/ZeroLines.svelte +4 -8
- package/dist/plot/core/components/ZoomRect.svelte +1 -2
- package/dist/plot/core/components/index.d.ts +1 -0
- package/dist/plot/core/components/index.js +1 -0
- package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
- package/dist/plot/core/data-cleaning-signal.js +467 -0
- package/dist/plot/core/data-cleaning.d.ts +2 -42
- package/dist/plot/core/data-cleaning.js +27 -474
- package/dist/plot/core/data-transform.js +9 -5
- package/dist/plot/core/fill-utils.d.ts +3 -1
- package/dist/plot/core/fill-utils.js +28 -6
- package/dist/plot/core/index.d.ts +1 -0
- package/dist/plot/core/index.js +1 -0
- package/dist/plot/core/interactions.js +0 -2
- package/dist/plot/core/layout.d.ts +3 -1
- package/dist/plot/core/layout.js +22 -13
- package/dist/plot/core/marginals.d.ts +170 -0
- package/dist/plot/core/marginals.js +436 -0
- package/dist/plot/core/reference-line.js +1 -1
- package/dist/plot/core/scales.d.ts +23 -0
- package/dist/plot/core/scales.js +39 -13
- package/dist/plot/core/types/fills.d.ts +101 -0
- package/dist/plot/core/types/fills.js +15 -0
- package/dist/plot/core/types/plot-3d.d.ts +87 -0
- package/dist/plot/core/types/plot-3d.js +4 -0
- package/dist/plot/core/types/reference-lines.d.ts +140 -0
- package/dist/plot/core/types/reference-lines.js +9 -0
- package/dist/plot/core/types.d.ts +29 -324
- package/dist/plot/core/types.js +23 -20
- package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
- package/dist/plot/core/utils/hierarchy-chart.js +179 -0
- package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
- package/dist/plot/core/utils/hierarchy-labels.js +99 -0
- package/dist/plot/core/utils/label-placement.js +2 -2
- package/dist/plot/histogram/Histogram.svelte +304 -325
- package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
- package/dist/plot/histogram/HistogramControls.svelte +30 -28
- package/dist/plot/histogram/histogram.d.ts +31 -0
- package/dist/plot/histogram/histogram.js +70 -0
- package/dist/plot/histogram/index.d.ts +1 -0
- package/dist/plot/histogram/index.js +1 -0
- package/dist/plot/index.d.ts +1 -0
- package/dist/plot/index.js +1 -0
- package/dist/plot/sankey/Sankey.svelte +78 -69
- package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
- package/dist/plot/sankey/SankeyControls.svelte +22 -16
- package/dist/plot/scatter/BinnedScatterPlot.svelte +263 -109
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
- package/dist/plot/scatter/ElementScatter.svelte +4 -1
- package/dist/plot/scatter/ScatterPlot.svelte +477 -385
- package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
- package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
- package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/scatter/ScatterPoint.svelte +16 -9
- package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
- package/dist/plot/scatter/binned-scatter-types.js +6 -1
- package/dist/plot/scatter/scatter-data.d.ts +1 -1
- package/dist/plot/scatter/scatter-data.js +8 -7
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
- package/dist/plot/sunburst/Sunburst.svelte +251 -329
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
- package/dist/plot/sunburst/index.d.ts +1 -1
- package/dist/plot/sunburst/index.js +2 -1
- package/dist/plot/sunburst/render.d.ts +2 -2
- package/dist/plot/sunburst/render.js +47 -22
- package/dist/plot/sunburst/sunburst.d.ts +5 -1
- package/dist/plot/sunburst/sunburst.js +10 -3
- package/dist/plot/treemap/Treemap.svelte +907 -0
- package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
- package/dist/plot/treemap/index.d.ts +3 -0
- package/dist/plot/treemap/index.js +4 -0
- package/dist/plot/treemap/treemap.d.ts +26 -0
- package/dist/plot/treemap/treemap.js +99 -0
- package/dist/rdf/RdfPlot.svelte +22 -26
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/calc-rdf.js +4 -8
- package/dist/sanitize.js +1 -1
- package/dist/scene/bind-renderer.svelte.js +14 -6
- package/dist/settings.d.ts +19 -9
- package/dist/settings.js +77 -50
- package/dist/spectral/Bands.svelte +223 -230
- package/dist/spectral/BandsAndDos.svelte +11 -9
- package/dist/spectral/BrillouinBandsDos.svelte +19 -27
- package/dist/spectral/Dos.svelte +70 -73
- package/dist/spectral/helpers.d.ts +3 -3
- package/dist/spectral/helpers.js +25 -35
- package/dist/state.svelte.js +5 -18
- package/dist/structure/Arrow.svelte +5 -18
- package/dist/structure/ArrowInstances.svelte +160 -0
- package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
- package/dist/structure/AtomLegend.svelte +115 -75
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/Bond.svelte +31 -23
- package/dist/structure/CanvasTooltip.svelte +15 -3
- package/dist/structure/CellSelect.svelte +11 -26
- package/dist/structure/Cylinder.svelte +24 -40
- package/dist/structure/InstancedAtoms.svelte +114 -0
- package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
- package/dist/structure/Lattice.svelte +85 -149
- package/dist/structure/SiteLabels.svelte +122 -0
- package/dist/structure/SiteLabels.svelte.d.ts +18 -0
- package/dist/structure/Structure.svelte +473 -419
- package/dist/structure/Structure.svelte.d.ts +4 -2
- package/dist/structure/StructureCarousel.svelte +630 -0
- package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
- package/dist/structure/StructureControls.svelte +157 -399
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureExportPane.svelte +17 -21
- package/dist/structure/StructureInfoPane.svelte +72 -66
- package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
- package/dist/structure/StructureScene.svelte +467 -476
- package/dist/structure/StructureScene.svelte.d.ts +3 -1
- package/dist/structure/StructureViewport.svelte +386 -0
- package/dist/structure/StructureViewport.svelte.d.ts +63 -0
- package/dist/structure/atom-label-placement.d.ts +16 -12
- package/dist/structure/atom-label-placement.js +70 -37
- package/dist/structure/atom-properties.d.ts +2 -0
- package/dist/structure/atom-properties.js +104 -38
- package/dist/structure/bonding.d.ts +10 -3
- package/dist/structure/bonding.js +84 -28
- package/dist/structure/edit-history.d.ts +6 -0
- package/dist/structure/edit-history.js +27 -0
- package/dist/structure/export.d.ts +1 -0
- package/dist/structure/export.js +39 -31
- package/dist/structure/format-detect.d.ts +1 -0
- package/dist/structure/format-detect.js +22 -0
- package/dist/structure/geometry.d.ts +9 -0
- package/dist/structure/geometry.js +27 -0
- package/dist/structure/index.d.ts +16 -1
- package/dist/structure/index.js +13 -2
- package/dist/structure/measure.d.ts +1 -1
- package/dist/structure/measure.js +6 -12
- package/dist/structure/parse.d.ts +2 -1
- package/dist/structure/parse.js +243 -222
- package/dist/structure/partial-occupancy.js +4 -2
- package/dist/structure/pbc.js +78 -98
- package/dist/structure/polyhedra.d.ts +0 -1
- package/dist/structure/polyhedra.js +3 -18
- package/dist/structure/supercell.d.ts +1 -2
- package/dist/structure/supercell.js +7 -13
- package/dist/symmetry/SymmetryElements.svelte +11 -15
- package/dist/symmetry/SymmetryStats.svelte +56 -68
- package/dist/symmetry/WyckoffTable.svelte +5 -24
- package/dist/symmetry/cell-transform.js +1 -0
- package/dist/symmetry/index.d.ts +1 -0
- package/dist/symmetry/index.js +8 -2
- package/dist/symmetry/spacegroups.js +3 -2
- package/dist/table/HeatmapTable.svelte +1102 -365
- package/dist/table/HeatmapTable.svelte.d.ts +12 -2
- package/dist/table/ToggleMenu.svelte +5 -12
- package/dist/table/index.d.ts +21 -6
- package/dist/table/index.js +34 -21
- package/dist/theme/ThemeControl.svelte +16 -8
- package/dist/theme/index.d.ts +1 -5
- package/dist/theme/index.js +4 -10
- package/dist/theme/themes.mjs +14 -7
- package/dist/tooltip/KCoords.svelte +4 -1
- package/dist/tooltip/TooltipContent.svelte +2 -5
- package/dist/trajectory/Trajectory.svelte +515 -308
- package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
- package/dist/trajectory/TrajectoryError.svelte +11 -8
- package/dist/trajectory/TrajectoryExportPane.svelte +14 -31
- package/dist/trajectory/TrajectoryInfoPane.svelte +85 -97
- package/dist/trajectory/extract.js +56 -34
- package/dist/trajectory/format-detect.js +11 -9
- package/dist/trajectory/frame-reader.d.ts +2 -0
- package/dist/trajectory/frame-reader.js +33 -29
- package/dist/trajectory/helpers.d.ts +2 -0
- package/dist/trajectory/helpers.js +18 -7
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +3 -0
- package/dist/trajectory/parse/h5-utils.d.ts +13 -0
- package/dist/trajectory/parse/h5-utils.js +109 -0
- package/dist/trajectory/parse/hdf5.d.ts +1 -1
- package/dist/trajectory/parse/hdf5.js +116 -106
- package/dist/trajectory/parse/index.d.ts +2 -3
- package/dist/trajectory/parse/index.js +17 -20
- package/dist/trajectory/parse/lammps.js +8 -12
- package/dist/trajectory/parse/vasp.js +10 -7
- package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
- package/dist/trajectory/parse/vaspout-electronic.js +207 -0
- package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
- package/dist/trajectory/parse/vaspout-h5.js +284 -0
- package/dist/trajectory/parse/xyz.js +11 -7
- package/dist/trajectory/plotting.d.ts +8 -9
- package/dist/trajectory/plotting.js +99 -27
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +7 -0
- package/dist/xrd/XrdPlot.svelte +47 -61
- package/dist/xrd/broadening.js +2 -1
- package/dist/xrd/calc-xrd.js +2 -4
- package/dist/xrd/parse.d.ts +0 -1
- package/dist/xrd/parse.js +56 -73
- package/package.json +61 -33
- package/dist/api/mp.d.ts +0 -6
- package/dist/api/mp.js +0 -22
- package/dist/plot/sunburst/SunburstControls.svelte +0 -200
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
generics="Metadata extends Record<string, unknown> = Record<string, unknown>"
|
|
4
4
|
>
|
|
5
5
|
import type { D3InterpolateName } from '../../colors'
|
|
6
|
-
import { format_value } from '../../labels'
|
|
6
|
+
import { format_value, format_value_or_num } from '../../labels'
|
|
7
7
|
import { sanitize_html } from '../../sanitize'
|
|
8
8
|
import { FullscreenToggle, set_fullscreen_bg } from '../../layout'
|
|
9
9
|
import type { Point2D, Vec2 } from '../../math'
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
Line,
|
|
41
41
|
PlotAxis,
|
|
42
42
|
PlotLegend,
|
|
43
|
+
PlotMarginals,
|
|
43
44
|
PlotTooltip,
|
|
44
45
|
ReferenceLine,
|
|
45
46
|
ScatterPlotControls,
|
|
@@ -47,20 +48,33 @@
|
|
|
47
48
|
ZeroLines,
|
|
48
49
|
ZoomRect,
|
|
49
50
|
} from '..'
|
|
51
|
+
import type { MarginalSeriesInput, MarginalsProp } from '../core/marginals'
|
|
52
|
+
import {
|
|
53
|
+
add_sides,
|
|
54
|
+
marginal_axis,
|
|
55
|
+
marginal_axis_presence,
|
|
56
|
+
normalize_marginals,
|
|
57
|
+
reserve_marginal_pad,
|
|
58
|
+
} from '../core/marginals'
|
|
50
59
|
import {
|
|
51
60
|
build_obstacles_norm,
|
|
52
61
|
has_explicit_position,
|
|
53
62
|
measured_footprint,
|
|
54
63
|
place_decorations,
|
|
55
64
|
} from '../core/auto-place'
|
|
56
|
-
import
|
|
57
|
-
|
|
65
|
+
import {
|
|
66
|
+
AXIS_DEFAULTS,
|
|
67
|
+
type AxisChangeState,
|
|
68
|
+
create_axis_loader,
|
|
69
|
+
} from '../core/axis-utils'
|
|
58
70
|
import { get_series_color, get_series_symbol } from '../core/data-transform'
|
|
59
71
|
import { create_placed_tween } from '../core/placed-tween.svelte'
|
|
60
72
|
import {
|
|
73
|
+
COLOR_BAR_DEFAULTS,
|
|
61
74
|
DEFAULT_MARKERS,
|
|
62
75
|
get_scale_type_name,
|
|
63
76
|
is_time_scale,
|
|
77
|
+
SCALE_DEFAULTS,
|
|
64
78
|
} from '../core/types'
|
|
65
79
|
import { compute_label_positions } from '../core/utils/label-placement'
|
|
66
80
|
import { create_legend_visibility } from '../core/utils/series-visibility'
|
|
@@ -88,6 +102,7 @@
|
|
|
88
102
|
import { create_pan_zoom } from '../core/pan-zoom.svelte'
|
|
89
103
|
import type { Rect, Sides } from '../core/layout'
|
|
90
104
|
import {
|
|
105
|
+
AXIS_TITLE_OFFSET,
|
|
91
106
|
calc_auto_padding,
|
|
92
107
|
filter_padding,
|
|
93
108
|
LABEL_GAP_DEFAULT,
|
|
@@ -106,11 +121,10 @@
|
|
|
106
121
|
get_nice_data_range,
|
|
107
122
|
} from '../core/scales'
|
|
108
123
|
import { resolve_line_tween, unique_id } from '../core/utils'
|
|
109
|
-
import {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
} from './scatter-data'
|
|
124
|
+
import { build_legend_data, filter_series_to_ranges, pick_tooltip_bg } from './scatter-data'
|
|
125
|
+
|
|
126
|
+
// Plots with at least this many visible markers get smaller default point radii
|
|
127
|
+
const DENSE_MARKER_COUNT = 100
|
|
114
128
|
|
|
115
129
|
let {
|
|
116
130
|
series = $bindable([]),
|
|
@@ -122,7 +136,7 @@
|
|
|
122
136
|
styles: styles_init = {},
|
|
123
137
|
controls: controls_init = {},
|
|
124
138
|
padding = {},
|
|
125
|
-
range_padding = 0
|
|
139
|
+
range_padding = 0,
|
|
126
140
|
current_x_value = null,
|
|
127
141
|
tooltip_point = $bindable(null),
|
|
128
142
|
selected_point = null,
|
|
@@ -130,13 +144,9 @@
|
|
|
130
144
|
tooltip,
|
|
131
145
|
user_content,
|
|
132
146
|
change = () => {},
|
|
133
|
-
color_scale =
|
|
134
|
-
type: `linear`,
|
|
135
|
-
scheme: `interpolateViridis`,
|
|
136
|
-
value_range: undefined,
|
|
137
|
-
},
|
|
147
|
+
color_scale = SCALE_DEFAULTS.color,
|
|
138
148
|
color_bar = {},
|
|
139
|
-
size_scale =
|
|
149
|
+
size_scale = SCALE_DEFAULTS.size,
|
|
140
150
|
label_placement_config = {},
|
|
141
151
|
hover_config = {},
|
|
142
152
|
legend = {},
|
|
@@ -163,100 +173,95 @@
|
|
|
163
173
|
on_axis_change,
|
|
164
174
|
on_error,
|
|
165
175
|
pan = {},
|
|
176
|
+
marginals = false,
|
|
166
177
|
...rest
|
|
167
|
-
}: HTMLAttributes<HTMLDivElement> &
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
[
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
) => void
|
|
225
|
-
on_error?: (error: AxisLoadError) => void
|
|
226
|
-
pan?: PanConfig
|
|
227
|
-
} = $props()
|
|
178
|
+
}: HTMLAttributes<HTMLDivElement> &
|
|
179
|
+
Omit<BasePlotProps, `change`> &
|
|
180
|
+
PlotConfig & {
|
|
181
|
+
series?: DataSeries<Metadata>[]
|
|
182
|
+
styles?: StyleOverrides
|
|
183
|
+
controls?: ControlsConfig
|
|
184
|
+
current_x_value?: number | null
|
|
185
|
+
tooltip_point?: InternalPoint<Metadata> | null
|
|
186
|
+
selected_point?: { series_idx: number; point_idx: number } | null
|
|
187
|
+
tooltip?: Snippet<[ScatterHandlerProps<Metadata>]>
|
|
188
|
+
user_content?: Snippet<[UserContentProps]>
|
|
189
|
+
header_controls?: Snippet<[{ height: number; width: number; fullscreen: boolean }]>
|
|
190
|
+
controls_extra?: Snippet<
|
|
191
|
+
[{ styles: StyleOverrides; selected_series_idx: number } & Required<PlotConfig>]
|
|
192
|
+
>
|
|
193
|
+
change?: (data: (Point<Metadata> & { series: DataSeries<Metadata> }) | null) => void
|
|
194
|
+
color_scale?: ColorScaleConfig | D3InterpolateName
|
|
195
|
+
size_scale?: SizeScaleConfig
|
|
196
|
+
color_bar?:
|
|
197
|
+
| (ComponentProps<typeof ColorBar> & {
|
|
198
|
+
margin?: number | Sides
|
|
199
|
+
tween?: TweenOptions<Point2D>
|
|
200
|
+
responsive?: boolean // Allow colorbar to reposition if density changes (default: false)
|
|
201
|
+
axis_clearance?: number // Min distance kept from plot edges/axes (default: 15)
|
|
202
|
+
})
|
|
203
|
+
| null
|
|
204
|
+
label_placement_config?: Partial<LabelPlacementConfig>
|
|
205
|
+
hover_config?: Partial<HoverConfig>
|
|
206
|
+
legend?: LegendConfig | null
|
|
207
|
+
point_tween?: TweenOptions<Point2D>
|
|
208
|
+
line_tween?: TweenOptions<string>
|
|
209
|
+
point_events?: Record<
|
|
210
|
+
string,
|
|
211
|
+
(payload: { point: InternalPoint<Metadata>; event: Event }) => void
|
|
212
|
+
>
|
|
213
|
+
on_point_click?: (data: ScatterHandlerEvent<Metadata>) => void
|
|
214
|
+
on_point_hover?: (data: ScatterHandlerEvent<Metadata> | null) => void
|
|
215
|
+
fill_regions?: FillRegion[] // Bindable for legend toggle support
|
|
216
|
+
error_bands?: ErrorBand[]
|
|
217
|
+
on_fill_click?: (event: FillHandlerEvent) => void
|
|
218
|
+
on_fill_hover?: (event: FillHandlerEvent | null) => void
|
|
219
|
+
ref_lines?: RefLine[] // Bindable for legend toggle support
|
|
220
|
+
on_ref_line_click?: (event: RefLineEvent) => void
|
|
221
|
+
on_ref_line_hover?: (event: RefLineEvent | null) => void
|
|
222
|
+
selected_series_idx?: number
|
|
223
|
+
wrapper?: HTMLDivElement
|
|
224
|
+
// Interactive axis props
|
|
225
|
+
data_loader?: DataLoaderFn<Metadata>
|
|
226
|
+
on_axis_change?: (
|
|
227
|
+
axis: `x` | `x2` | `y` | `y2`,
|
|
228
|
+
key: string,
|
|
229
|
+
new_series: DataSeries<Metadata>[],
|
|
230
|
+
) => void
|
|
231
|
+
on_error?: (error: AxisLoadError) => void
|
|
232
|
+
pan?: PanConfig
|
|
233
|
+
marginals?: MarginalsProp
|
|
234
|
+
} = $props()
|
|
228
235
|
|
|
229
236
|
// Merged axis/display values with defaults (use $derived to avoid breaking $bindable)
|
|
230
237
|
const final_x_axis = $derived({
|
|
231
238
|
...AXIS_DEFAULTS,
|
|
232
|
-
label_shift: { x: 0, y:
|
|
239
|
+
label_shift: { x: 0, y: 0 },
|
|
233
240
|
...x_axis,
|
|
234
241
|
})
|
|
235
242
|
const final_y_axis = $derived({ ...AXIS_DEFAULTS, ...y_axis })
|
|
236
243
|
const final_x2_axis = $derived({
|
|
237
244
|
...AXIS_DEFAULTS,
|
|
238
|
-
label_shift: { x: 0, y:
|
|
245
|
+
label_shift: { x: 0, y: AXIS_TITLE_OFFSET }, // x2-axis label above top edge
|
|
239
246
|
...x2_axis,
|
|
240
247
|
})
|
|
241
248
|
const final_y2_axis = $derived({ ...AXIS_DEFAULTS, ...y2_axis })
|
|
242
249
|
// Cache time-axis check — used in ~10 places for scale/tick/tooltip logic
|
|
243
|
-
let is_time_x = $derived(
|
|
244
|
-
|
|
245
|
-
)
|
|
246
|
-
let is_time_x2 = $derived(
|
|
247
|
-
is_time_scale(final_x2_axis.scale_type, final_x2_axis.format),
|
|
248
|
-
)
|
|
250
|
+
let is_time_x = $derived(is_time_scale(final_x_axis.scale_type, final_x_axis.format))
|
|
251
|
+
let is_time_x2 = $derived(is_time_scale(final_x2_axis.scale_type, final_x2_axis.format))
|
|
249
252
|
const final_display = $derived({ ...DEFAULTS.scatter.display, ...display })
|
|
250
253
|
// Local state for styles (initialized from prop, owned by this component for controls)
|
|
251
254
|
// Using $state because styles has bindings in ScatterPlotControls
|
|
252
255
|
// untrack() explicitly captures initial prop value (intentional - props provide initial config)
|
|
253
|
-
let styles = $state(
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
256
|
+
let styles = $state(
|
|
257
|
+
untrack(() => ({
|
|
258
|
+
show_points: DEFAULTS.scatter.show_points,
|
|
259
|
+
show_lines: DEFAULTS.scatter.show_lines,
|
|
260
|
+
point: { ...DEFAULTS.scatter.point, ...styles_init?.point },
|
|
261
|
+
line: { ...DEFAULTS.scatter.line, ...styles_init?.line },
|
|
262
|
+
...styles_init,
|
|
263
|
+
})),
|
|
264
|
+
)
|
|
260
265
|
let controls = $derived({ show: true, open: false, ...controls_init })
|
|
261
266
|
|
|
262
267
|
let [width, height] = $state([0, 0])
|
|
@@ -287,7 +292,10 @@
|
|
|
287
292
|
initial: { x: [0, 1], x2: [0, 1], y: [0, 1], y2: [0, 1] },
|
|
288
293
|
current: { x: [0, 1], x2: [0, 1], y: [0, 1], y2: [0, 1] },
|
|
289
294
|
})
|
|
290
|
-
const legend_vis = create_legend_visibility(
|
|
295
|
+
const legend_vis = create_legend_visibility(
|
|
296
|
+
() => series,
|
|
297
|
+
(next) => (series = next),
|
|
298
|
+
)
|
|
291
299
|
|
|
292
300
|
// Y2 axis sync configuration
|
|
293
301
|
let y2_sync_config = $derived(normalize_y2_sync(y2_axis?.sync))
|
|
@@ -350,8 +358,13 @@
|
|
|
350
358
|
|
|
351
359
|
for (const srs of series_with_ids) {
|
|
352
360
|
if (!srs) continue
|
|
353
|
-
const {
|
|
354
|
-
|
|
361
|
+
const {
|
|
362
|
+
x: xs,
|
|
363
|
+
y: ys,
|
|
364
|
+
visible = true,
|
|
365
|
+
y_axis: series_y_axis = `y1`,
|
|
366
|
+
x_axis: x_ax = `x1`,
|
|
367
|
+
} = srs as DataSeries
|
|
355
368
|
for (let idx = 0; idx < xs.length; idx++) {
|
|
356
369
|
const point = { x: xs[idx], y: ys[idx] }
|
|
357
370
|
all.push(point)
|
|
@@ -376,37 +389,44 @@
|
|
|
376
389
|
|
|
377
390
|
// Update padding when format or ticks change
|
|
378
391
|
$effect(() => {
|
|
379
|
-
const new_pad =
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
392
|
+
const new_pad =
|
|
393
|
+
width &&
|
|
394
|
+
height &&
|
|
395
|
+
(y_tick_values.length > 0 || y2_tick_values.length > 0 || x2_tick_values.length > 0)
|
|
396
|
+
? calc_auto_padding({
|
|
397
|
+
padding,
|
|
398
|
+
default_padding,
|
|
399
|
+
x2_axis: { ...final_x2_axis, tick_values: x2_tick_values },
|
|
400
|
+
y_axis: { ...final_y_axis, tick_values: y_tick_values },
|
|
401
|
+
y2_axis: { ...final_y2_axis, tick_values: y2_tick_values },
|
|
402
|
+
})
|
|
403
|
+
: filter_padding(padding, default_padding)
|
|
389
404
|
|
|
390
405
|
if (
|
|
391
406
|
base_pad.t !== new_pad.t ||
|
|
392
407
|
base_pad.b !== new_pad.b ||
|
|
393
408
|
base_pad.l !== new_pad.l ||
|
|
394
409
|
base_pad.r !== new_pad.r
|
|
395
|
-
)
|
|
410
|
+
)
|
|
411
|
+
base_pad = new_pad
|
|
396
412
|
})
|
|
397
413
|
|
|
398
414
|
// === Auto-move legend/colorbar outside the plot when interior overlap is unavoidable ===
|
|
399
415
|
// (shared logic lives in auto-place.ts so every 2D plot reuses it)
|
|
400
416
|
// ColorBar's orientation prop defaults to horizontal, so treat unset as horizontal too
|
|
401
|
-
const colorbar_is_horizontal = $derived(
|
|
417
|
+
const colorbar_is_horizontal = $derived(
|
|
418
|
+
(color_bar?.orientation ?? `horizontal`) === `horizontal`,
|
|
419
|
+
)
|
|
402
420
|
const colorbar_footprint = $derived(
|
|
403
421
|
colorbar_element?.offsetWidth && colorbar_element?.offsetHeight
|
|
404
422
|
? measure_full_footprint(colorbar_element)
|
|
405
423
|
: colorbar_is_horizontal
|
|
406
|
-
|
|
407
|
-
|
|
424
|
+
? COLOR_BAR_DEFAULTS.horizontal_footprint
|
|
425
|
+
: COLOR_BAR_DEFAULTS.vertical_footprint,
|
|
426
|
+
)
|
|
427
|
+
const legend_footprint = $derived(
|
|
428
|
+
measured_footprint(legend_element, { width: 120, height: 80 }),
|
|
408
429
|
)
|
|
409
|
-
const legend_footprint = $derived(measured_footprint(legend_element, { width: 120, height: 80 }))
|
|
410
430
|
const legend_has_explicit_pos = $derived(has_explicit_position(legend?.style))
|
|
411
431
|
|
|
412
432
|
// Plot-specific obstacle field: series points/lines normalized to [0,1] (y=0 at top)
|
|
@@ -416,7 +436,9 @@
|
|
|
416
436
|
const base_h = height - base_pad.t - base_pad.b
|
|
417
437
|
if (base_w <= 0 || base_h <= 0) return []
|
|
418
438
|
const norm_x = is_time_x
|
|
419
|
-
? scaleTime()
|
|
439
|
+
? scaleTime()
|
|
440
|
+
.domain([new Date(x_min), new Date(x_max)])
|
|
441
|
+
.range([0, 1])
|
|
420
442
|
: create_scale(final_x_axis.scale_type ?? `linear`, [x_min, x_max], [0, 1])
|
|
421
443
|
const norm_y = create_scale(final_y_axis.scale_type ?? `linear`, [y_min, y_max], [0, 1])
|
|
422
444
|
return build_obstacles_norm(
|
|
@@ -442,23 +464,58 @@
|
|
|
442
464
|
obstacles_norm,
|
|
443
465
|
// gate on legend_element (the actual render signal) not legend_data, whose fill entries read
|
|
444
466
|
// computed_fills -> pad and would make this derived reference itself
|
|
445
|
-
legend:
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
467
|
+
legend:
|
|
468
|
+
legend != null &&
|
|
469
|
+
legend_element != null &&
|
|
470
|
+
!legend_has_explicit_pos &&
|
|
471
|
+
!legend_is_dragging &&
|
|
472
|
+
!legend_manual_position
|
|
473
|
+
? { footprint: legend_footprint, clearance: legend?.axis_clearance }
|
|
474
|
+
: null,
|
|
449
475
|
// gate on a measured colorbar: its outside style stretches it to full width, so deciding from
|
|
450
476
|
// the (wide) pre-measure fallback would flip-flop placement between interior and outside
|
|
451
|
-
colorbar:
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
477
|
+
colorbar:
|
|
478
|
+
Boolean(color_bar) &&
|
|
479
|
+
all_color_values.length > 0 &&
|
|
480
|
+
!color_bar?.wrapper_style &&
|
|
481
|
+
(colorbar_element?.offsetWidth ?? 0) > 0 &&
|
|
482
|
+
(colorbar_element?.offsetHeight ?? 0) > 0
|
|
483
|
+
? {
|
|
484
|
+
footprint: colorbar_footprint,
|
|
485
|
+
horizontal: colorbar_is_horizontal,
|
|
486
|
+
clearance: color_bar?.axis_clearance,
|
|
487
|
+
}
|
|
488
|
+
: null,
|
|
489
|
+
}),
|
|
490
|
+
)
|
|
491
|
+
// Resolve marginals and reserve outer-band padding so the plot shrinks to make room
|
|
492
|
+
const resolved_marginals = $derived(
|
|
493
|
+
normalize_marginals(marginals, { top: true, right: true }),
|
|
494
|
+
)
|
|
495
|
+
const pad = $derived(add_sides(decor.pad, reserve_marginal_pad(resolved_marginals)))
|
|
496
|
+
// Map series to the generic marginal input, reusing the line/legend color fallback
|
|
497
|
+
const marginal_series = $derived<MarginalSeriesInput[]>(
|
|
498
|
+
series_with_ids.map((srs, idx) => {
|
|
499
|
+
const point_fill = Array.isArray(srs?.point_style)
|
|
500
|
+
? srs.point_style[0]?.fill
|
|
501
|
+
: srs?.point_style?.fill
|
|
502
|
+
return {
|
|
503
|
+
x: srs?.x ?? [],
|
|
504
|
+
y: srs?.y ?? [],
|
|
505
|
+
color:
|
|
506
|
+
srs?.line_style?.stroke ??
|
|
507
|
+
point_fill ??
|
|
508
|
+
get_series_color(srs?.orig_series_idx ?? idx),
|
|
509
|
+
label: srs?.label,
|
|
510
|
+
visible: srs?.visible ?? true,
|
|
511
|
+
x_axis: srs?.x_axis,
|
|
512
|
+
y_axis: srs?.y_axis,
|
|
513
|
+
}
|
|
514
|
+
}),
|
|
515
|
+
)
|
|
516
|
+
const marginal_has_axis = $derived(
|
|
517
|
+
marginal_axis_presence(x2_points.length > 0, y2_points.length > 0),
|
|
460
518
|
)
|
|
461
|
-
const pad = $derived(decor.pad)
|
|
462
519
|
const legend_auto_outside = $derived(decor.legend_outside)
|
|
463
520
|
const legend_outside_x = $derived(decor.legend_pos.x)
|
|
464
521
|
const legend_outside_y = $derived(decor.legend_pos.y)
|
|
@@ -471,9 +528,7 @@
|
|
|
471
528
|
x: pad.l || 0,
|
|
472
529
|
y: pad.t || 0,
|
|
473
530
|
width: isFinite(width - pad.l - pad.r) ? Math.max(1, width - pad.l - pad.r) : 1,
|
|
474
|
-
height: isFinite(height - pad.t - pad.b)
|
|
475
|
-
? Math.max(1, height - pad.t - pad.b)
|
|
476
|
-
: 1,
|
|
531
|
+
height: isFinite(height - pad.t - pad.b) ? Math.max(1, height - pad.t - pad.b) : 1,
|
|
477
532
|
})
|
|
478
533
|
|
|
479
534
|
// Calculate plot area center coordinates
|
|
@@ -487,8 +542,12 @@
|
|
|
487
542
|
for (const srs of series_with_ids) {
|
|
488
543
|
if (!srs) continue
|
|
489
544
|
const { color_values: cvs, size_values: svs } = srs as DataSeries
|
|
490
|
-
if (cvs) {
|
|
491
|
-
|
|
545
|
+
if (cvs) {
|
|
546
|
+
for (const val of cvs) if (val != null) color_values.push(val)
|
|
547
|
+
}
|
|
548
|
+
if (svs) {
|
|
549
|
+
for (const val of svs) if (val != null) size_values.push(val)
|
|
550
|
+
}
|
|
492
551
|
}
|
|
493
552
|
return { color_values, size_values }
|
|
494
553
|
})
|
|
@@ -567,7 +626,10 @@
|
|
|
567
626
|
if (explicit) {
|
|
568
627
|
ranges.current[axis] = range
|
|
569
628
|
} else {
|
|
570
|
-
const result = expand_range_if_needed(
|
|
629
|
+
const result = expand_range_if_needed(
|
|
630
|
+
untrack(() => ranges.initial[axis]),
|
|
631
|
+
range,
|
|
632
|
+
)
|
|
571
633
|
if (result.changed) {
|
|
572
634
|
ranges.initial[axis] = result.range
|
|
573
635
|
ranges.current[axis] = result.range
|
|
@@ -579,7 +641,10 @@
|
|
|
579
641
|
if (resolved.y2.explicit) {
|
|
580
642
|
ranges.current.y2 = resolved.y2.range
|
|
581
643
|
} else {
|
|
582
|
-
const result = expand_range_if_needed(
|
|
644
|
+
const result = expand_range_if_needed(
|
|
645
|
+
untrack(() => ranges.initial.y2),
|
|
646
|
+
resolved.y2.range,
|
|
647
|
+
)
|
|
583
648
|
if (result.changed) ranges.initial.y2 = result.range
|
|
584
649
|
// Apply sync if enabled, otherwise use expanded range (or keep current if unchanged)
|
|
585
650
|
if (y2_sync_config.mode !== `none`) {
|
|
@@ -605,10 +670,10 @@
|
|
|
605
670
|
// Ensure we only calculate extent on actual numbers, filtering out nulls/undefined
|
|
606
671
|
all_color_values.length > 0
|
|
607
672
|
? extent(
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
673
|
+
all_color_values.filter(
|
|
674
|
+
(color_val: number | null): color_val is number => typeof color_val === `number`,
|
|
675
|
+
),
|
|
676
|
+
)
|
|
612
677
|
: [0, 1],
|
|
613
678
|
) as Vec2
|
|
614
679
|
|
|
@@ -617,37 +682,37 @@
|
|
|
617
682
|
let x_scale_fn = $derived(
|
|
618
683
|
is_time_x
|
|
619
684
|
? scaleTime()
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
: create_scale(
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
685
|
+
.domain([new Date(x_min), new Date(x_max)])
|
|
686
|
+
.range([pad.l, width - pad.r])
|
|
687
|
+
: create_scale(
|
|
688
|
+
final_x_axis.scale_type ?? `linear`,
|
|
689
|
+
[x_min, x_max],
|
|
690
|
+
[pad.l, width - pad.r],
|
|
691
|
+
),
|
|
626
692
|
)
|
|
627
693
|
|
|
628
694
|
let x2_scale_fn = $derived(
|
|
629
695
|
is_time_x2
|
|
630
696
|
? scaleTime()
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
: create_scale(
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
697
|
+
.domain([new Date(x2_min), new Date(x2_max)])
|
|
698
|
+
.range([pad.l, width - pad.r])
|
|
699
|
+
: create_scale(
|
|
700
|
+
final_x2_axis.scale_type ?? `linear`,
|
|
701
|
+
[x2_min, x2_max],
|
|
702
|
+
[pad.l, width - pad.r],
|
|
703
|
+
),
|
|
637
704
|
)
|
|
638
705
|
|
|
639
706
|
let y_scale_fn = $derived(
|
|
640
|
-
create_scale(final_y_axis.scale_type ?? `linear`, [y_min, y_max], [
|
|
641
|
-
height - pad.b,
|
|
642
|
-
pad.t,
|
|
643
|
-
]),
|
|
707
|
+
create_scale(final_y_axis.scale_type ?? `linear`, [y_min, y_max], [height - pad.b, pad.t]),
|
|
644
708
|
)
|
|
645
709
|
|
|
646
710
|
let y2_scale_fn = $derived(
|
|
647
|
-
create_scale(
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
711
|
+
create_scale(
|
|
712
|
+
final_y2_axis.scale_type ?? `linear`,
|
|
713
|
+
[y2_min, y2_max],
|
|
714
|
+
[height - pad.b, pad.t],
|
|
715
|
+
),
|
|
651
716
|
)
|
|
652
717
|
|
|
653
718
|
// All size values from series (for size scale) - extracted in series_value_arrays
|
|
@@ -684,6 +749,22 @@
|
|
|
684
749
|
})
|
|
685
750
|
let effective_line_tween = $derived(resolve_line_tween(line_tween, line_tween_load))
|
|
686
751
|
|
|
752
|
+
let visible_marker_count = $derived.by(() => {
|
|
753
|
+
if (!styles.show_points) return 0
|
|
754
|
+
let count = 0
|
|
755
|
+
for (const series_data of filtered_series ?? []) {
|
|
756
|
+
if ((series_data.markers ?? DEFAULT_MARKERS).includes(`points`)) {
|
|
757
|
+
count += series_data.filtered_data.length
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
return count
|
|
761
|
+
})
|
|
762
|
+
|
|
763
|
+
const default_point_radius = (markers: string): number => {
|
|
764
|
+
const [sparse_radius, dense_radius] = markers.includes(`line`) ? [2.5, 2] : [3, 2.5]
|
|
765
|
+
return visible_marker_count >= DENSE_MARKER_COUNT ? dense_radius : sparse_radius
|
|
766
|
+
}
|
|
767
|
+
|
|
687
768
|
// Obstacle field for legend/colorbar auto-placement. Sampling only data points lets the
|
|
688
769
|
// legend land on top of a steep connecting line whose markers are sparse (e.g. y=x^2), so
|
|
689
770
|
// sample_series_obstacle_points also walks each drawn segment at a fixed pixel cadence.
|
|
@@ -699,14 +780,16 @@
|
|
|
699
780
|
const active_x_scale = use_x2_scale ? x2_scale_fn : x_scale_fn
|
|
700
781
|
const active_is_time_x = use_x2_scale ? is_time_x2 : is_time_x
|
|
701
782
|
const active_y_scale = series_data.y_axis === `y2` ? y2_scale_fn : y_scale_fn
|
|
702
|
-
const draws_line =
|
|
703
|
-
(series_data.markers ?? DEFAULT_MARKERS).includes(`line`)
|
|
783
|
+
const draws_line =
|
|
784
|
+
styles.show_lines && (series_data.markers ?? DEFAULT_MARKERS).includes(`line`)
|
|
704
785
|
|
|
705
786
|
const pixel_points = series_data.filtered_data.map((point) => ({
|
|
706
787
|
x: active_is_time_x ? active_x_scale(new Date(point.x)) : active_x_scale(point.x),
|
|
707
788
|
y: active_y_scale(point.y),
|
|
708
789
|
}))
|
|
709
|
-
points.push(
|
|
790
|
+
points.push(
|
|
791
|
+
...sample_series_obstacle_points(pixel_points, draws_line, SEGMENT_SAMPLE_STEP),
|
|
792
|
+
)
|
|
710
793
|
}
|
|
711
794
|
return points
|
|
712
795
|
})
|
|
@@ -791,14 +874,16 @@
|
|
|
791
874
|
}
|
|
792
875
|
|
|
793
876
|
return all_regions
|
|
794
|
-
.filter(
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
877
|
+
.filter(
|
|
878
|
+
(
|
|
879
|
+
entry,
|
|
880
|
+
): entry is {
|
|
881
|
+
region: FillRegion
|
|
882
|
+
source_type: `fill_region` | `error_band`
|
|
883
|
+
source_idx: number
|
|
884
|
+
hover_key: string
|
|
885
|
+
} => entry.region !== null,
|
|
886
|
+
)
|
|
802
887
|
.map(({ region, source_type, source_idx, hover_key }, idx) => {
|
|
803
888
|
// Hidden fills keep their entry (with empty path_segments -> nothing renders) so the
|
|
804
889
|
// legend item persists greyed-out and can be toggled back on.
|
|
@@ -806,15 +891,15 @@
|
|
|
806
891
|
const path_segments = hidden
|
|
807
892
|
? []
|
|
808
893
|
: compute_fill_segments(region, series_with_ids, domains)
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
894
|
+
.map((seg) =>
|
|
895
|
+
generate_fill_path(
|
|
896
|
+
seg.upper.map(to_px),
|
|
897
|
+
seg.lower.map(to_px),
|
|
898
|
+
seg.upper_curve,
|
|
899
|
+
seg.lower_curve,
|
|
900
|
+
),
|
|
815
901
|
)
|
|
816
|
-
|
|
817
|
-
.filter((path) => path.length > 0)
|
|
902
|
+
.filter((path) => path.length > 0)
|
|
818
903
|
|
|
819
904
|
// Drop only visible fills with no geometry; keep hidden ones for the legend
|
|
820
905
|
if (!hidden && path_segments.length === 0) return null
|
|
@@ -848,13 +933,12 @@
|
|
|
848
933
|
})
|
|
849
934
|
|
|
850
935
|
// Compute ref_lines with index and group by z-index (using shared utilities)
|
|
851
|
-
let
|
|
852
|
-
let ref_lines_by_z = $derived(group_ref_lines_by_z(indexed_ref_lines))
|
|
936
|
+
let ref_lines_by_z = $derived(group_ref_lines_by_z(index_ref_lines(ref_lines)))
|
|
853
937
|
|
|
854
938
|
// Calculate best legend placement using continuous grid sampling
|
|
855
939
|
let legend_placement = $derived.by(() => {
|
|
856
|
-
const should_place =
|
|
857
|
-
(legend_data.length > 1 || Object.keys(legend ?? {}).length > 0)
|
|
940
|
+
const should_place =
|
|
941
|
+
legend != null && (legend_data.length > 1 || Object.keys(legend ?? {}).length > 0)
|
|
858
942
|
|
|
859
943
|
if (!should_place || !width || !height) return null
|
|
860
944
|
|
|
@@ -882,10 +966,9 @@
|
|
|
882
966
|
|
|
883
967
|
// Fallback estimate (with room for tick labels) used before the colorbar first
|
|
884
968
|
// renders; compute_element_placement measures the real footprint once it's laid out
|
|
885
|
-
const
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
: { width: 56, height: 100 }
|
|
969
|
+
const colorbar_size = colorbar_is_horizontal
|
|
970
|
+
? COLOR_BAR_DEFAULTS.horizontal_footprint
|
|
971
|
+
: COLOR_BAR_DEFAULTS.vertical_footprint
|
|
889
972
|
|
|
890
973
|
// Build exclusion rects (avoid legend if it's placed)
|
|
891
974
|
const exclude_rects: Rect[] = []
|
|
@@ -910,20 +993,10 @@
|
|
|
910
993
|
})
|
|
911
994
|
})
|
|
912
995
|
|
|
913
|
-
// Active legend placement (null if user set explicit position)
|
|
914
|
-
let active_legend_placement = $derived
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
// Skip auto-placement if user set explicit position in style
|
|
918
|
-
const legend_style = legend?.style ?? ``
|
|
919
|
-
if (
|
|
920
|
-
/(^|[;{]\s*)(top|bottom|left|right)\s*:|position\s*:\s*absolute/.test(
|
|
921
|
-
legend_style,
|
|
922
|
-
)
|
|
923
|
-
) return null
|
|
924
|
-
|
|
925
|
-
return legend_placement
|
|
926
|
-
})
|
|
996
|
+
// Active legend placement (null if user set explicit position in style)
|
|
997
|
+
let active_legend_placement = $derived(
|
|
998
|
+
legend_placement && !legend_has_explicit_pos ? legend_placement : null,
|
|
999
|
+
)
|
|
927
1000
|
|
|
928
1001
|
// Tweened colorbar/legend coordinates with shared placement stability gating
|
|
929
1002
|
const colorbar_tween = create_placed_tween({
|
|
@@ -966,15 +1039,16 @@
|
|
|
966
1039
|
x_scale_for_ticks,
|
|
967
1040
|
{ format: final_x_axis.format },
|
|
968
1041
|
),
|
|
969
|
-
x2:
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
1042
|
+
x2:
|
|
1043
|
+
x2_points.length > 0
|
|
1044
|
+
? generate_ticks(
|
|
1045
|
+
[x2_min, x2_max],
|
|
1046
|
+
final_x2_axis.scale_type ?? `linear`,
|
|
1047
|
+
final_x2_axis.ticks,
|
|
1048
|
+
x2_scale_for_ticks,
|
|
1049
|
+
{ format: final_x2_axis.format },
|
|
1050
|
+
)
|
|
1051
|
+
: [],
|
|
978
1052
|
y: generate_ticks(
|
|
979
1053
|
[y_min, y_max],
|
|
980
1054
|
final_y_axis.scale_type ?? `linear`,
|
|
@@ -982,15 +1056,16 @@
|
|
|
982
1056
|
y_scale_fn,
|
|
983
1057
|
{ default_count: 5 },
|
|
984
1058
|
),
|
|
985
|
-
y2:
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1059
|
+
y2:
|
|
1060
|
+
y2_points.length > 0
|
|
1061
|
+
? generate_ticks(
|
|
1062
|
+
[y2_min, y2_max],
|
|
1063
|
+
final_y2_axis.scale_type ?? `linear`,
|
|
1064
|
+
final_y2_axis.ticks,
|
|
1065
|
+
y2_scale_fn,
|
|
1066
|
+
{ default_count: 5 },
|
|
1067
|
+
)
|
|
1068
|
+
: [],
|
|
994
1069
|
}
|
|
995
1070
|
})
|
|
996
1071
|
|
|
@@ -1036,16 +1111,16 @@
|
|
|
1036
1111
|
y_axis = { ...y_axis, range: next_y }
|
|
1037
1112
|
|
|
1038
1113
|
// X2 axis: invert screen coords using x2 scale
|
|
1039
|
-
const next_x2 =
|
|
1040
|
-
? invert_rect_range(x2_scale_fn, start.x, current.x)
|
|
1041
|
-
: null
|
|
1114
|
+
const next_x2 =
|
|
1115
|
+
x2_points.length > 0 ? invert_rect_range(x2_scale_fn, start.x, current.x) : null
|
|
1042
1116
|
if (next_x2) x2_axis = { ...x2_axis, range: next_x2 }
|
|
1043
1117
|
|
|
1044
1118
|
// Y2 axis: when sync is enabled the y_axis effect derives y2; with sync 'none'
|
|
1045
1119
|
// y2 must zoom from the rect directly (parity with BarPlot/Histogram/BoxPlot)
|
|
1046
|
-
const next_y2 =
|
|
1047
|
-
|
|
1048
|
-
|
|
1120
|
+
const next_y2 =
|
|
1121
|
+
y2_points.length > 0 && y2_sync_config.mode === `none`
|
|
1122
|
+
? invert_rect_range(y2_scale_fn, start.y, current.y)
|
|
1123
|
+
: null
|
|
1049
1124
|
if (next_y2) y2_axis = { ...y2_axis, range: next_y2 }
|
|
1050
1125
|
},
|
|
1051
1126
|
on_reset: () => {
|
|
@@ -1100,9 +1175,7 @@
|
|
|
1100
1175
|
const point_cx = tooltip_is_time_x
|
|
1101
1176
|
? tooltip_x_scale(new Date(point.x))
|
|
1102
1177
|
: tooltip_x_scale(point.x)
|
|
1103
|
-
const point_cy = (series_data.y_axis === `y2` ? y2_scale_fn : y_scale_fn)(
|
|
1104
|
-
point.y,
|
|
1105
|
-
)
|
|
1178
|
+
const point_cy = (series_data.y_axis === `y2` ? y2_scale_fn : y_scale_fn)(point.y)
|
|
1106
1179
|
|
|
1107
1180
|
// Calculate squared screen distance between mouse and point
|
|
1108
1181
|
const screen_dx = x_rel - point_cx
|
|
@@ -1119,11 +1192,7 @@
|
|
|
1119
1192
|
}
|
|
1120
1193
|
|
|
1121
1194
|
// Check if the closest point is within the hover threshold
|
|
1122
|
-
if (
|
|
1123
|
-
closest_point &&
|
|
1124
|
-
closest_series &&
|
|
1125
|
-
min_screen_dist_sq <= hover_threshold_px_sq
|
|
1126
|
-
) {
|
|
1195
|
+
if (closest_point && closest_series && min_screen_dist_sq <= hover_threshold_px_sq) {
|
|
1127
1196
|
// Construct handler props synchronously to avoid stale derived reads
|
|
1128
1197
|
const props = construct_handler_props(closest_point)
|
|
1129
1198
|
tooltip_point = closest_point
|
|
@@ -1198,8 +1267,8 @@
|
|
|
1198
1267
|
const new_y = event.clientY - svg_rect.top - legend_drag_offset.y
|
|
1199
1268
|
|
|
1200
1269
|
// Get actual legend dimensions for accurate bounds checking using the bound element reference
|
|
1201
|
-
const { width: legend_width, height: legend_height } =
|
|
1202
|
-
.getBoundingClientRect()
|
|
1270
|
+
const { width: legend_width, height: legend_height } =
|
|
1271
|
+
legend_element.getBoundingClientRect()
|
|
1203
1272
|
|
|
1204
1273
|
// Constrain to plot bounds using measured legend size
|
|
1205
1274
|
const constrained_x = Math.max(0, Math.min(width - legend_width, new_x))
|
|
@@ -1245,9 +1314,7 @@
|
|
|
1245
1314
|
const cx = handler_is_time_x ? handler_x_scale(new Date(x)) : handler_x_scale(x)
|
|
1246
1315
|
const cy = (hovered_series.y_axis === `y2` ? y2_scale_fn : y_scale_fn)(y)
|
|
1247
1316
|
const active_x_config = handler_use_x2 ? final_x2_axis : final_x_axis
|
|
1248
|
-
const active_y_config = hovered_series.y_axis === `y2`
|
|
1249
|
-
? final_y2_axis
|
|
1250
|
-
: final_y_axis
|
|
1317
|
+
const active_y_config = hovered_series.y_axis === `y2` ? final_y2_axis : final_y_axis
|
|
1251
1318
|
const coords = {
|
|
1252
1319
|
x,
|
|
1253
1320
|
y,
|
|
@@ -1264,8 +1331,8 @@
|
|
|
1264
1331
|
metadata,
|
|
1265
1332
|
label: hovered_series.label ?? null,
|
|
1266
1333
|
series_idx,
|
|
1267
|
-
x_formatted:
|
|
1268
|
-
y_formatted:
|
|
1334
|
+
x_formatted: format_value_or_num(x, active_x_config.format),
|
|
1335
|
+
y_formatted: format_value_or_num(y, active_y_config.format),
|
|
1269
1336
|
color_value: color_value ?? null,
|
|
1270
1337
|
colorbar: {
|
|
1271
1338
|
value: color_value ?? null,
|
|
@@ -1287,9 +1354,7 @@
|
|
|
1287
1354
|
// Precompute non-click event names from point_events so we don't rebuild
|
|
1288
1355
|
// the entries array on every point render.
|
|
1289
1356
|
let point_event_names = $derived(
|
|
1290
|
-
point_events
|
|
1291
|
-
? Object.keys(point_events).filter((name) => name !== `onclick`)
|
|
1292
|
-
: [],
|
|
1357
|
+
point_events ? Object.keys(point_events).filter((name) => name !== `onclick`) : [],
|
|
1293
1358
|
)
|
|
1294
1359
|
|
|
1295
1360
|
// Set theme-aware background when entering fullscreen
|
|
@@ -1298,41 +1363,30 @@
|
|
|
1298
1363
|
})
|
|
1299
1364
|
|
|
1300
1365
|
// State accessors for shared axis change handler
|
|
1366
|
+
// Spread into existing state in each setter to preserve merged type structure
|
|
1301
1367
|
const axis_state: AxisChangeState<DataSeries<Metadata>> = {
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1368
|
+
axes: {
|
|
1369
|
+
x: { get: () => x_axis, set: (config) => (x_axis = { ...x_axis, ...config }) },
|
|
1370
|
+
x2: { get: () => x2_axis, set: (config) => (x2_axis = { ...x2_axis, ...config }) },
|
|
1371
|
+
y: { get: () => y_axis, set: (config) => (y_axis = { ...y_axis, ...config }) },
|
|
1372
|
+
y2: { get: () => y2_axis, set: (config) => (y2_axis = { ...y2_axis, ...config }) },
|
|
1307
1373
|
},
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
if (axis === `x`) x_axis = { ...x_axis, ...config }
|
|
1311
|
-
else if (axis === `x2`) x2_axis = { ...x2_axis, ...config }
|
|
1312
|
-
else if (axis === `y`) y_axis = { ...y_axis, ...config }
|
|
1313
|
-
else y2_axis = { ...y2_axis, ...config }
|
|
1314
|
-
},
|
|
1315
|
-
get_series: () => series,
|
|
1316
|
-
set_series: (new_series) => (series = new_series),
|
|
1317
|
-
get_loading: () => axis_loading,
|
|
1318
|
-
set_loading: (axis) => (axis_loading = axis),
|
|
1374
|
+
series: { get: () => series, set: (next) => (series = next) },
|
|
1375
|
+
loading: { get: () => axis_loading, set: (axis) => (axis_loading = axis) },
|
|
1319
1376
|
}
|
|
1320
1377
|
|
|
1321
1378
|
// Shared handler + one-shot auto-load bound to this component's state
|
|
1322
|
-
const { handle_axis_change, try_auto_load } = create_axis_loader(
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1379
|
+
const { handle_axis_change, try_auto_load } = create_axis_loader(axis_state, () => ({
|
|
1380
|
+
data_loader,
|
|
1381
|
+
on_axis_change,
|
|
1382
|
+
on_error,
|
|
1383
|
+
}))
|
|
1326
1384
|
$effect(try_auto_load)
|
|
1327
1385
|
</script>
|
|
1328
1386
|
|
|
1329
1387
|
{#snippet fill_regions_layer(fills: typeof computed_fills)}
|
|
1330
1388
|
{#each fills as fill (fill.hover_key)}
|
|
1331
|
-
{#each fill.path_segments as
|
|
1332
|
-
path_d,
|
|
1333
|
-
segment_idx
|
|
1334
|
-
(`${fill.id ?? fill.idx}-${segment_idx}`)
|
|
1335
|
-
}
|
|
1389
|
+
{#each fill.path_segments as path_d, segment_idx (`${fill.id ?? fill.idx}-${segment_idx}`)}
|
|
1336
1390
|
<FillArea
|
|
1337
1391
|
region={fill}
|
|
1338
1392
|
region_idx={fill.idx}
|
|
@@ -1399,7 +1453,7 @@
|
|
|
1399
1453
|
bind:clientWidth={width}
|
|
1400
1454
|
bind:clientHeight={height}
|
|
1401
1455
|
{...rest}
|
|
1402
|
-
class=
|
|
1456
|
+
class={[`scatter`, rest.class]}
|
|
1403
1457
|
class:fullscreen
|
|
1404
1458
|
>
|
|
1405
1459
|
{#if width && height}
|
|
@@ -1415,8 +1469,8 @@
|
|
|
1415
1469
|
bind:this={svg_element}
|
|
1416
1470
|
role="application"
|
|
1417
1471
|
aria-label={rest[`aria-label`] ??
|
|
1418
|
-
|
|
1419
|
-
|
|
1472
|
+
([final_x_axis.label, final_y_axis.label].filter(Boolean).join(` vs `) ||
|
|
1473
|
+
`Scatter plot`)}
|
|
1420
1474
|
tabindex="0"
|
|
1421
1475
|
onfocusin={() => pan_zoom.set_focused(true)}
|
|
1422
1476
|
onfocusout={() => pan_zoom.set_focused(false)}
|
|
@@ -1473,7 +1527,7 @@
|
|
|
1473
1527
|
domain={[x_min, x_max]}
|
|
1474
1528
|
tick_label={(tick) => get_tick_label(tick, final_x_axis.ticks)}
|
|
1475
1529
|
label_x={width / 2 + (final_x_axis.label_shift?.x ?? 0)}
|
|
1476
|
-
label_y={height - pad.b
|
|
1530
|
+
label_y={height - pad.b + AXIS_TITLE_OFFSET + (final_x_axis.label_shift?.y ?? 0)}
|
|
1477
1531
|
axis_loading={axis_loading === `x`}
|
|
1478
1532
|
on_axis_change={(key) => handle_axis_change(`x`, key)}
|
|
1479
1533
|
/>
|
|
@@ -1481,8 +1535,8 @@
|
|
|
1481
1535
|
<!-- Current frame indicator -->
|
|
1482
1536
|
{#if current_x_value != null}
|
|
1483
1537
|
{@const current_pos_raw = is_time_x
|
|
1484
|
-
|
|
1485
|
-
|
|
1538
|
+
? x_scale_fn(new Date(current_x_value))
|
|
1539
|
+
: x_scale_fn(current_x_value)}
|
|
1486
1540
|
{#if isFinite(current_pos_raw)}
|
|
1487
1541
|
{@const current_pos = current_pos_raw}
|
|
1488
1542
|
{#if current_pos >= pad.l && current_pos <= width - pad.r}
|
|
@@ -1516,7 +1570,8 @@
|
|
|
1516
1570
|
tick_label={(tick) => get_tick_label(tick, final_y_axis.ticks)}
|
|
1517
1571
|
label_x={Math.max(
|
|
1518
1572
|
12,
|
|
1519
|
-
pad.l -
|
|
1573
|
+
pad.l -
|
|
1574
|
+
(final_y_axis.tick?.label?.inside ? 0 : tick_label_widths.y_max) -
|
|
1520
1575
|
LABEL_GAP_DEFAULT,
|
|
1521
1576
|
) + (final_y_axis.label_shift?.x ?? 0)}
|
|
1522
1577
|
label_y={pad.t + (height - pad.t - pad.b) / 2 + (final_y_axis.label_shift?.y ?? 0)}
|
|
@@ -1561,7 +1616,7 @@
|
|
|
1561
1616
|
domain={[x2_min, x2_max]}
|
|
1562
1617
|
tick_label={(tick) => get_tick_label(tick, final_x2_axis.ticks)}
|
|
1563
1618
|
label_x={width / 2 + (final_x2_axis.label_shift?.x ?? 0)}
|
|
1564
|
-
label_y={Math.max(12, pad.t - (final_x2_axis.label_shift?.y ??
|
|
1619
|
+
label_y={Math.max(12, pad.t - (final_x2_axis.label_shift?.y ?? AXIS_TITLE_OFFSET))}
|
|
1565
1620
|
axis_loading={axis_loading === `x2`}
|
|
1566
1621
|
on_axis_change={(key) => handle_axis_change(`x2`, key)}
|
|
1567
1622
|
/>
|
|
@@ -1619,30 +1674,32 @@
|
|
|
1619
1674
|
data-series-id={series_data._id}
|
|
1620
1675
|
clip-path="url(#{clip_path_id})"
|
|
1621
1676
|
opacity={hovered_legend_series_idx !== null &&
|
|
1622
|
-
|
|
1677
|
+
hovered_legend_series_idx !== series_data.orig_series_idx
|
|
1623
1678
|
? 0.25
|
|
1624
1679
|
: 1}
|
|
1625
1680
|
>
|
|
1626
|
-
{#if series_markers
|
|
1681
|
+
{#if series_markers.includes(`line`)}
|
|
1627
1682
|
{@const all_line_points = series_data.x.map((x, idx) => ({
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1683
|
+
x,
|
|
1684
|
+
y: series_data.y[idx],
|
|
1685
|
+
}))}
|
|
1631
1686
|
{@const finite_screen_points = all_line_points
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
{@const apply_line_controls =
|
|
1635
|
-
|
|
1636
|
-
|
|
1687
|
+
.map((point) => get_screen_coords(point, series_data))
|
|
1688
|
+
.filter(([sx, sy]) => isFinite(sx) && isFinite(sy))}
|
|
1689
|
+
{@const apply_line_controls =
|
|
1690
|
+
controls.show &&
|
|
1691
|
+
(!has_multiple_series ||
|
|
1692
|
+
series_data._id === series_with_ids[selected_series_idx]?._id)}
|
|
1637
1693
|
{@const ls = series_data.line_style}
|
|
1638
1694
|
{@const tc = (key: string) => apply_line_controls && touched.has(key)}
|
|
1639
|
-
{@const color_fallback =
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1695
|
+
{@const color_fallback =
|
|
1696
|
+
ls?.stroke ??
|
|
1697
|
+
(Array.isArray(series_data.point_style)
|
|
1698
|
+
? series_data.point_style[0]?.fill
|
|
1699
|
+
: series_data.point_style?.fill) ??
|
|
1700
|
+
(series_data.color_values?.[0] != null
|
|
1701
|
+
? color_scale_fn(series_data.color_values[0])
|
|
1702
|
+
: series_default_color)}
|
|
1646
1703
|
<Line
|
|
1647
1704
|
points={finite_screen_points}
|
|
1648
1705
|
origin={[
|
|
@@ -1650,8 +1707,11 @@
|
|
|
1650
1707
|
series_data.y_axis === `y2` ? y2_scale_fn(y2_min) : y_scale_fn(y_min),
|
|
1651
1708
|
]}
|
|
1652
1709
|
line_color={(tc(`line.color`) ? styles.line?.color : null) ?? color_fallback}
|
|
1653
|
-
line_width={(tc(`line.width`) ? styles.line?.width : null) ??
|
|
1710
|
+
line_width={(tc(`line.width`) ? styles.line?.width : null) ??
|
|
1711
|
+
ls?.stroke_width ??
|
|
1712
|
+
2}
|
|
1654
1713
|
line_dash={(tc(`line.dash`) ? styles.line?.dash : null) ?? ls?.line_dash}
|
|
1714
|
+
curve={ls?.curve}
|
|
1655
1715
|
area_color="transparent"
|
|
1656
1716
|
line_tween={effective_line_tween}
|
|
1657
1717
|
/>
|
|
@@ -1672,53 +1732,60 @@
|
|
|
1672
1732
|
{@const series_default_color = get_series_color(series_data.orig_series_idx ?? 0)}
|
|
1673
1733
|
{@const series_default_symbol = get_series_symbol(series_data.orig_series_idx ?? 0)}
|
|
1674
1734
|
<g data-series-id={series_data._id}>
|
|
1675
|
-
{#if series_markers
|
|
1676
|
-
{#each series_data.filtered_data as
|
|
1677
|
-
point
|
|
1678
|
-
(`${point.series_idx}-${point.point_idx}`)
|
|
1679
|
-
}
|
|
1735
|
+
{#if series_markers.includes(`points`)}
|
|
1736
|
+
{#each series_data.filtered_data as point (`${point.series_idx}-${point.point_idx}`)}
|
|
1680
1737
|
{@const label_id = `${point.series_idx}-${point.point_idx}`}
|
|
1681
1738
|
{@const calculated_label_pos = label_positions[label_id]}
|
|
1682
1739
|
{@const point_label = point.point_label ?? {}}
|
|
1683
|
-
{@const label_style =
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1740
|
+
{@const label_style =
|
|
1741
|
+
point_label.auto_placement &&
|
|
1742
|
+
actual_label_config.max_neighbors &&
|
|
1743
|
+
!calculated_label_pos
|
|
1744
|
+
? {}
|
|
1745
|
+
: point_label}
|
|
1688
1746
|
{@const final_label = calculated_label_pos
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1747
|
+
? {
|
|
1748
|
+
...label_style,
|
|
1749
|
+
offset: {
|
|
1750
|
+
x:
|
|
1751
|
+
calculated_label_pos.x -
|
|
1752
|
+
(is_time_x ? x_scale_fn(new Date(point.x)) : x_scale_fn(point.x)),
|
|
1753
|
+
y:
|
|
1754
|
+
calculated_label_pos.y -
|
|
1755
|
+
(series_data.y_axis === `y2`
|
|
1756
|
+
? y2_scale_fn(point.y)
|
|
1757
|
+
: y_scale_fn(point.y)),
|
|
1758
|
+
},
|
|
1759
|
+
}
|
|
1760
|
+
: label_style}
|
|
1700
1761
|
{@const [raw_screen_x, raw_screen_y] = get_screen_coords(point, series_data)}
|
|
1701
|
-
{@const screen_x = isFinite(raw_screen_x)
|
|
1762
|
+
{@const screen_x = isFinite(raw_screen_x)
|
|
1763
|
+
? raw_screen_x
|
|
1764
|
+
: x_scale_fn.range()[0]}
|
|
1702
1765
|
{@const screen_y = isFinite(raw_screen_y)
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
{@const apply_controls =
|
|
1706
|
-
|
|
1707
|
-
|
|
1766
|
+
? raw_screen_y
|
|
1767
|
+
: (series_data.y_axis === `y2` ? y2_scale_fn : y_scale_fn).range()[0]}
|
|
1768
|
+
{@const apply_controls =
|
|
1769
|
+
controls.show &&
|
|
1770
|
+
(!has_multiple_series ||
|
|
1771
|
+
series_data._id === series_with_ids[selected_series_idx]?._id)}
|
|
1708
1772
|
{@const pt = point.point_style}
|
|
1709
1773
|
{@const tc = (key: string) => apply_controls && touched.has(key)}
|
|
1710
|
-
{@const computed_radius =
|
|
1711
|
-
|
|
1712
|
-
|
|
1774
|
+
{@const computed_radius =
|
|
1775
|
+
point.size_value != null
|
|
1776
|
+
? size_scale_fn(point.size_value)
|
|
1777
|
+
: ((tc(`point.size`) ? styles.point?.size : null) ??
|
|
1778
|
+
pt?.radius ??
|
|
1779
|
+
default_point_radius(series_markers))}
|
|
1713
1780
|
<ScatterPoint
|
|
1714
1781
|
x={screen_x}
|
|
1715
1782
|
y={screen_y}
|
|
1716
1783
|
is_dimmed={hovered_legend_series_idx !== null &&
|
|
1717
1784
|
hovered_legend_series_idx !== point.series_idx}
|
|
1718
1785
|
is_hovered={tooltip_point?.series_idx === point.series_idx &&
|
|
1719
|
-
|
|
1786
|
+
tooltip_point?.point_idx === point.point_idx}
|
|
1720
1787
|
is_selected={selected_point?.series_idx === point.series_idx &&
|
|
1721
|
-
|
|
1788
|
+
selected_point?.point_idx === point.point_idx}
|
|
1722
1789
|
leader_line_threshold={actual_label_config.leader_line_threshold}
|
|
1723
1790
|
style={{
|
|
1724
1791
|
symbol_type: pt?.symbol_type ?? series_default_symbol,
|
|
@@ -1726,18 +1793,21 @@
|
|
|
1726
1793
|
radius: computed_radius,
|
|
1727
1794
|
stroke_width:
|
|
1728
1795
|
(tc(`point.stroke_width`) ? styles.point?.stroke_width : null) ??
|
|
1729
|
-
|
|
1796
|
+
pt?.stroke_width ??
|
|
1797
|
+
1,
|
|
1730
1798
|
stroke:
|
|
1731
1799
|
(tc(`point.stroke_color`) ? styles.point?.stroke_color : null) ??
|
|
1732
|
-
|
|
1800
|
+
pt?.stroke ??
|
|
1801
|
+
`#000`,
|
|
1733
1802
|
stroke_opacity:
|
|
1734
1803
|
(tc(`point.stroke_opacity`) ? styles.point?.stroke_opacity : null) ??
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1804
|
+
pt?.stroke_opacity ??
|
|
1805
|
+
1,
|
|
1806
|
+
fill_opacity:
|
|
1807
|
+
(tc(`point.opacity`) ? styles.point?.opacity : null) ??
|
|
1808
|
+
pt?.fill_opacity ??
|
|
1809
|
+
1,
|
|
1810
|
+
cursor: on_point_click || point_events?.onclick ? `pointer` : undefined,
|
|
1741
1811
|
}}
|
|
1742
1812
|
hover={point.point_hover ?? {}}
|
|
1743
1813
|
label={final_label}
|
|
@@ -1745,15 +1815,17 @@
|
|
|
1745
1815
|
{point_tween}
|
|
1746
1816
|
origin={{ x: plot_center_x, y: plot_center_y }}
|
|
1747
1817
|
--point-fill-color={point.color_value != null
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1818
|
+
? color_scale_fn(point.color_value)
|
|
1819
|
+
: ((tc(`point.color`) ? styles.point?.color : null) ??
|
|
1820
|
+
pt?.fill ??
|
|
1821
|
+
series_default_color)}
|
|
1751
1822
|
{...point_events &&
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1823
|
+
Object.fromEntries(
|
|
1824
|
+
point_event_names.map((name) => [
|
|
1825
|
+
name,
|
|
1826
|
+
(event: Event) => point_events?.[name]?.({ point, event }),
|
|
1827
|
+
]),
|
|
1828
|
+
)}
|
|
1757
1829
|
onclick={(event: MouseEvent) => {
|
|
1758
1830
|
// Call user-provided onclick handler first if it exists
|
|
1759
1831
|
point_events?.onclick?.({ point, event })
|
|
@@ -1773,16 +1845,33 @@
|
|
|
1773
1845
|
{@render fill_regions_layer(fills_by_z.above_all)}
|
|
1774
1846
|
<!-- Reference lines: above all -->
|
|
1775
1847
|
{@render ref_lines_layer(ref_lines_by_z.above_all)}
|
|
1848
|
+
|
|
1849
|
+
<!-- Marginal distribution strips -->
|
|
1850
|
+
<PlotMarginals
|
|
1851
|
+
marginals={resolved_marginals}
|
|
1852
|
+
series={marginal_series}
|
|
1853
|
+
{width}
|
|
1854
|
+
{height}
|
|
1855
|
+
{pad}
|
|
1856
|
+
has_axis={marginal_has_axis}
|
|
1857
|
+
axes={{
|
|
1858
|
+
x1: marginal_axis(x_scale_fn, [x_min, x_max], final_x_axis),
|
|
1859
|
+
x2: marginal_axis(x2_scale_fn, [x2_min, x2_max], final_x2_axis),
|
|
1860
|
+
y1: marginal_axis(y_scale_fn, [y_min, y_max], final_y_axis),
|
|
1861
|
+
y2: marginal_axis(y2_scale_fn, [y2_min, y2_max], final_y2_axis),
|
|
1862
|
+
}}
|
|
1863
|
+
id={component_id}
|
|
1864
|
+
/>
|
|
1776
1865
|
</svg>
|
|
1777
1866
|
|
|
1778
1867
|
<!-- Tooltip overlay above all plot overlays (legend, colorbar) -->
|
|
1779
1868
|
{#if handler_props && hovered && tooltip_point}
|
|
1780
1869
|
{@const { point_label, series_idx } = tooltip_point}
|
|
1781
1870
|
{@const tooltip_bg_color = pick_tooltip_bg(
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1871
|
+
tooltip_point,
|
|
1872
|
+
series_with_ids[series_idx],
|
|
1873
|
+
color_scale_fn,
|
|
1874
|
+
)}
|
|
1786
1875
|
<PlotTooltip
|
|
1787
1876
|
x={handler_props.cx}
|
|
1788
1877
|
y={handler_props.cy}
|
|
@@ -1800,9 +1889,10 @@
|
|
|
1800
1889
|
{@html sanitize_html(hp.x_axis.label || `x`)}: {hp.x_formatted}<br />
|
|
1801
1890
|
{@html sanitize_html(hp.y_axis.label || `y`)}: {hp.y_formatted}
|
|
1802
1891
|
{#if hp.colorbar?.value != null}
|
|
1803
|
-
<br />{@html sanitize_html(hp.colorbar.title || `Color`)}: {
|
|
1804
|
-
|
|
1805
|
-
|
|
1892
|
+
<br />{@html sanitize_html(hp.colorbar.title || `Color`)}: {format_value(
|
|
1893
|
+
hp.colorbar.value,
|
|
1894
|
+
hp.colorbar.tick_format || `.3~g`,
|
|
1895
|
+
)}
|
|
1806
1896
|
{/if}
|
|
1807
1897
|
{/if}
|
|
1808
1898
|
</PlotTooltip>
|
|
@@ -1813,10 +1903,9 @@
|
|
|
1813
1903
|
<ScatterPlotControls
|
|
1814
1904
|
toggle_props={{
|
|
1815
1905
|
...controls.toggle_props,
|
|
1816
|
-
style:
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
}`,
|
|
1906
|
+
style: `--ctrl-btn-right: var(--fullscreen-btn-offset, 30px); top: var(--ctrl-btn-top, 5pt); ${
|
|
1907
|
+
controls.toggle_props?.style ?? ``
|
|
1908
|
+
}`,
|
|
1820
1909
|
}}
|
|
1821
1910
|
pane_props={controls.pane_props}
|
|
1822
1911
|
bind:x_axis
|
|
@@ -1841,11 +1930,11 @@
|
|
|
1841
1930
|
<!-- Color Bar -->
|
|
1842
1931
|
{#if color_bar && all_color_values.length > 0 && color_bar_placement}
|
|
1843
1932
|
{@const color_domain = [
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1933
|
+
(typeof color_scale === `string` ? undefined : color_scale.value_range)?.[0] ??
|
|
1934
|
+
auto_color_range[0],
|
|
1935
|
+
(typeof color_scale === `string` ? undefined : color_scale.value_range)?.[1] ??
|
|
1936
|
+
auto_color_range[1],
|
|
1937
|
+
] as Vec2}
|
|
1849
1938
|
<div
|
|
1850
1939
|
bind:this={colorbar_element}
|
|
1851
1940
|
onmouseenter={() => colorbar_tween.set_locked(true)}
|
|
@@ -1854,9 +1943,10 @@
|
|
|
1854
1943
|
role="img"
|
|
1855
1944
|
aria-label="Color scale legend"
|
|
1856
1945
|
style={`${
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
`position: absolute; left: ${colorbar_tween.coords.current.x}px; top: ${colorbar_tween.coords.current.y}px`
|
|
1946
|
+
// explicit wrapper_style or auto-outside places the colorbar; else auto-placement coords
|
|
1947
|
+
effective_cbar_wrapper_style ??
|
|
1948
|
+
`position: absolute; left: ${colorbar_tween.coords.current.x}px; top: ${colorbar_tween.coords.current.y}px`
|
|
1949
|
+
}; pointer-events: auto;`}
|
|
1860
1950
|
>
|
|
1861
1951
|
<ColorBar
|
|
1862
1952
|
tick_labels={4}
|
|
@@ -1865,7 +1955,8 @@
|
|
|
1865
1955
|
color_scale_domain={color_domain}
|
|
1866
1956
|
scale_type={typeof color_scale === `string` ? undefined : color_scale.type}
|
|
1867
1957
|
range={color_domain?.every((val) => val != null) ? color_domain : undefined}
|
|
1868
|
-
bar_style="width:
|
|
1958
|
+
bar_style="width: {COLOR_BAR_DEFAULTS.width}px; height: {COLOR_BAR_DEFAULTS.horizontal_bar_height}px; {color_bar?.style ??
|
|
1959
|
+
``}"
|
|
1869
1960
|
{...color_bar}
|
|
1870
1961
|
wrapper_style={effective_cbar_wrapper_style ? `height: 100%; width: 100%;` : ``}
|
|
1871
1962
|
/>
|
|
@@ -1874,24 +1965,25 @@
|
|
|
1874
1965
|
|
|
1875
1966
|
<!-- Legend -->
|
|
1876
1967
|
<!-- Only render if multiple series or if legend prop was explicitly provided by user (even if empty object) -->
|
|
1877
|
-
{#if legend != null && legend_data.length > 0 &&
|
|
1878
|
-
(legend_data.length > 1 || Object.keys(legend ?? {}).length > 0)}
|
|
1968
|
+
{#if legend != null && legend_data.length > 0 && (legend_data.length > 1 || Object.keys(legend ?? {}).length > 0)}
|
|
1879
1969
|
{@const default_x = pad.l + 10}
|
|
1880
1970
|
{@const default_y = pad.t + 10}
|
|
1881
|
-
{@const current_x =
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1971
|
+
{@const current_x =
|
|
1972
|
+
legend_is_dragging && legend_manual_position
|
|
1973
|
+
? legend_manual_position.x
|
|
1974
|
+
: legend_auto_outside
|
|
1975
|
+
? legend_outside_x
|
|
1976
|
+
: legend_placement
|
|
1977
|
+
? legend_tween.coords.current.x
|
|
1978
|
+
: default_x}
|
|
1979
|
+
{@const current_y =
|
|
1980
|
+
legend_is_dragging && legend_manual_position
|
|
1981
|
+
? legend_manual_position.y
|
|
1982
|
+
: legend_auto_outside
|
|
1983
|
+
? legend_outside_y
|
|
1984
|
+
: legend_placement
|
|
1985
|
+
? legend_tween.coords.current.y
|
|
1986
|
+
: default_y}
|
|
1895
1987
|
<PlotLegend
|
|
1896
1988
|
bind:root_element={legend_element}
|
|
1897
1989
|
series_data={legend_data}
|
|
@@ -1907,15 +1999,14 @@
|
|
|
1907
1999
|
hovered_fill_key = fill && fill.visible !== false ? fill.hover_key : null
|
|
1908
2000
|
hovered_legend_series_idx = null
|
|
1909
2001
|
} else {
|
|
1910
|
-
hovered_legend_series_idx =
|
|
1911
|
-
? item.series_idx
|
|
1912
|
-
: null
|
|
2002
|
+
hovered_legend_series_idx =
|
|
2003
|
+
item != null && item.series_idx >= 0 ? item.series_idx : null
|
|
1913
2004
|
hovered_fill_key = null
|
|
1914
2005
|
}
|
|
1915
2006
|
}}
|
|
1916
2007
|
active_series_idx={tooltip_point?.series_idx ?? hovered_legend_series_idx}
|
|
1917
|
-
active_fill_idx={computed_fills.find((fill) => fill.hover_key === hovered_fill_key)
|
|
1918
|
-
null}
|
|
2008
|
+
active_fill_idx={computed_fills.find((fill) => fill.hover_key === hovered_fill_key)
|
|
2009
|
+
?.idx ?? null}
|
|
1919
2010
|
draggable={legend?.draggable ?? true}
|
|
1920
2011
|
{...legend}
|
|
1921
2012
|
on_toggle={legend?.on_toggle ?? legend_vis.on_toggle}
|
|
@@ -1927,7 +2018,7 @@
|
|
|
1927
2018
|
fill_regions = fill_regions.map((region, idx) =>
|
|
1928
2019
|
idx === source_idx
|
|
1929
2020
|
? { ...region, visible: !(region.visible !== false) }
|
|
1930
|
-
: region
|
|
2021
|
+
: region,
|
|
1931
2022
|
)
|
|
1932
2023
|
}
|
|
1933
2024
|
}}
|
|
@@ -1938,7 +2029,9 @@
|
|
|
1938
2029
|
// Only fill_regions can be toggled (error_bands are not bindable)
|
|
1939
2030
|
if (source_type !== `fill_region`) return
|
|
1940
2031
|
// Toggle: if only this fill is visible, show all; otherwise show only this one
|
|
1941
|
-
const visible_count = fill_regions.filter(
|
|
2032
|
+
const visible_count = fill_regions.filter(
|
|
2033
|
+
(region) => region.visible !== false,
|
|
2034
|
+
).length
|
|
1942
2035
|
const this_visible = fill_regions[source_idx]?.visible !== false
|
|
1943
2036
|
if (visible_count === 1 && this_visible) {
|
|
1944
2037
|
// Show all fills
|
|
@@ -2024,7 +2117,9 @@
|
|
|
2024
2117
|
div.scatter :global(.pane-toggle),
|
|
2025
2118
|
div.scatter .header-controls {
|
|
2026
2119
|
opacity: 0;
|
|
2027
|
-
transition:
|
|
2120
|
+
transition:
|
|
2121
|
+
opacity 0.2s,
|
|
2122
|
+
background-color 0.2s;
|
|
2028
2123
|
}
|
|
2029
2124
|
div.scatter:hover :global(.pane-toggle),
|
|
2030
2125
|
div.scatter:hover .header-controls,
|
|
@@ -2051,10 +2146,7 @@
|
|
|
2051
2146
|
color: var(--text-color);
|
|
2052
2147
|
white-space: nowrap;
|
|
2053
2148
|
/* Use line-height to center text vertically without flexbox */
|
|
2054
|
-
line-height: var(
|
|
2055
|
-
--scatter-axis-label-line-height,
|
|
2056
|
-
20px
|
|
2057
|
-
); /* Match foreignObject height */
|
|
2149
|
+
line-height: var(--scatter-axis-label-line-height, 20px); /* Match foreignObject height */
|
|
2058
2150
|
display: block;
|
|
2059
2151
|
}
|
|
2060
2152
|
.current-frame-indicator {
|