matterviz 0.4.0 → 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 +132 -219
- package/dist/brillouin/BrillouinZone.svelte.d.ts +9 -20
- package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
- package/dist/brillouin/BrillouinZoneExportPane.svelte +47 -96
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +15 -42
- package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
- package/dist/brillouin/BrillouinZoneScene.svelte +63 -230
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +3 -23
- package/dist/brillouin/ReciprocalVectors.svelte +39 -0
- package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
- package/dist/brillouin/compute.d.ts +2 -0
- package/dist/brillouin/compute.js +80 -77
- package/dist/brillouin/geometry.d.ts +8 -0
- package/dist/brillouin/geometry.js +57 -0
- package/dist/brillouin/index.d.ts +2 -0
- package/dist/brillouin/index.js +2 -0
- package/dist/brillouin/types.d.ts +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +143 -246
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +652 -976
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
- package/dist/chempot-diagram/async-compute.svelte.js +1 -1
- package/dist/chempot-diagram/color.d.ts +3 -6
- package/dist/chempot-diagram/color.js +5 -5
- package/dist/chempot-diagram/compute.d.ts +3 -3
- package/dist/chempot-diagram/compute.js +3 -1
- package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
- package/dist/chempot-diagram/controls-state.svelte.js +42 -0
- package/dist/chempot-diagram/export.d.ts +47 -0
- package/dist/chempot-diagram/export.js +133 -0
- package/dist/chempot-diagram/index.d.ts +1 -0
- package/dist/chempot-diagram/index.js +1 -0
- package/dist/chempot-diagram/pointer.d.ts +0 -10
- package/dist/chempot-diagram/pointer.js +4 -4
- package/dist/chempot-diagram/types.d.ts +3 -3
- package/dist/colors/index.d.ts +0 -4
- package/dist/colors/index.js +21 -22
- 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 +96 -98
- package/dist/composition/PieChart.svelte +60 -46
- package/dist/composition/chem-sys.js +3 -2
- package/dist/composition/format.js +4 -3
- package/dist/composition/index.d.ts +2 -0
- package/dist/composition/index.js +14 -0
- package/dist/composition/parse.d.ts +2 -3
- package/dist/composition/parse.js +27 -28
- package/dist/constants.js +11 -9
- package/dist/controls.d.ts +1 -0
- package/dist/controls.js +0 -1
- package/dist/convex-hull/ConvexHull.svelte +20 -25
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
- package/dist/convex-hull/ConvexHull2D.svelte +176 -256
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +269 -804
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +236 -755
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +264 -0
- package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
- package/dist/convex-hull/ConvexHullControls.svelte +128 -49
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
- package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
- package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
- package/dist/convex-hull/ConvexHullStats.svelte +210 -351
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +16 -14
- package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
- 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/barycentric-coords.d.ts +2 -4
- package/dist/convex-hull/barycentric-coords.js +6 -33
- package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
- package/dist/convex-hull/canvas-interactions.svelte.js +279 -0
- package/dist/convex-hull/helpers.d.ts +47 -17
- package/dist/convex-hull/helpers.js +186 -101
- package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
- package/dist/convex-hull/hull-state.svelte.js +124 -0
- package/dist/convex-hull/index.d.ts +9 -7
- package/dist/convex-hull/index.js +7 -2
- package/dist/convex-hull/thermodynamics.js +109 -937
- package/dist/convex-hull/types.d.ts +12 -4
- package/dist/convex-hull/types.js +12 -0
- package/dist/coordination/CoordinationBarPlot.svelte +41 -43
- 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 +6 -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/ElementTile.svelte.d.ts +1 -1
- 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 -0
- package/dist/element/index.js +3 -0
- package/dist/feedback/DragOverlay.svelte +5 -3
- package/dist/feedback/DragOverlay.svelte.d.ts +2 -1
- package/dist/feedback/StatusMessage.svelte +20 -7
- package/dist/fermi-surface/FermiSlice.svelte +21 -18
- package/dist/fermi-surface/FermiSurface.svelte +78 -165
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +9 -20
- package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
- package/dist/fermi-surface/FermiSurfaceScene.svelte +93 -272
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
- package/dist/fermi-surface/compute.js +14 -13
- package/dist/fermi-surface/export.js +4 -15
- package/dist/fermi-surface/index.d.ts +0 -1
- package/dist/fermi-surface/index.js +0 -1
- package/dist/fermi-surface/parse.d.ts +1 -1
- package/dist/fermi-surface/parse.js +84 -97
- package/dist/fermi-surface/types.d.ts +2 -2
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +161 -185
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +6 -5
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +12 -9
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
- package/dist/heatmap-matrix/index.d.ts +8 -2
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/io/ExportPane.svelte +170 -0
- package/dist/io/ExportPane.svelte.d.ts +17 -0
- package/dist/io/decompress.d.ts +2 -1
- package/dist/io/decompress.js +22 -36
- package/dist/io/export.d.ts +9 -1
- package/dist/io/export.js +37 -29
- package/dist/io/fetch.d.ts +2 -4
- package/dist/io/fetch.js +0 -11
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +13 -0
- package/dist/io/index.d.ts +1 -0
- package/dist/io/index.js +3 -0
- package/dist/io/is-binary.d.ts +9 -0
- package/dist/io/is-binary.js +45 -1
- package/dist/io/types.d.ts +13 -0
- 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 +50 -48
- package/dist/labels.d.ts +6 -2
- package/dist/labels.js +44 -14
- package/dist/layout/FullscreenButton.svelte +34 -0
- package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
- package/dist/layout/FullscreenToggle.svelte +12 -12
- 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 +115 -0
- package/dist/layout/ViewerChrome.svelte.d.ts +18 -0
- package/dist/layout/fullscreen.d.ts +4 -0
- package/dist/layout/fullscreen.js +3 -5
- package/dist/layout/fullscreen.svelte.d.ts +8 -0
- package/dist/layout/fullscreen.svelte.js +36 -0
- package/dist/layout/index.d.ts +4 -0
- package/dist/layout/index.js +4 -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 +9 -3
- package/dist/math.js +37 -21
- 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 +11 -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 +115 -146
- 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 +73 -96
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +49 -134
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
- 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/colors.js +1 -1
- package/dist/phase-diagram/diagram-input.d.ts +1 -2
- package/dist/phase-diagram/parse.d.ts +2 -1
- 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 +494 -692
- package/dist/plot/bar/BarPlot.svelte.d.ts +9 -15
- package/dist/plot/bar/BarPlotControls.svelte +1 -3
- package/dist/plot/bar/BarPlotControls.svelte.d.ts +5 -7
- package/dist/plot/bar/SpacegroupBarPlot.svelte +31 -37
- package/dist/plot/bar/data.d.ts +5 -4
- package/dist/plot/bar/data.js +2 -1
- package/dist/plot/box/BoxPlot.svelte +361 -439
- package/dist/plot/box/BoxPlot.svelte.d.ts +6 -3
- package/dist/plot/box/BoxPlotControls.svelte.d.ts +1 -1
- package/dist/plot/box/Violin.svelte.d.ts +2 -1
- package/dist/plot/box/box-plot.d.ts +3 -2
- package/dist/plot/box/box-plot.js +6 -3
- package/dist/plot/box/kde.d.ts +2 -1
- package/dist/plot/box/kde.js +4 -4
- package/dist/plot/core/auto-place.d.ts +1 -1
- package/dist/plot/core/auto-place.js +5 -2
- 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 +106 -111
- package/dist/plot/core/components/ColorBar.svelte.d.ts +5 -4
- 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 +21 -11
- package/dist/plot/core/components/Line.svelte.d.ts +5 -2
- package/dist/plot/core/components/PlotAxis.svelte +42 -18
- package/dist/plot/core/components/PlotAxis.svelte.d.ts +2 -1
- package/dist/plot/core/components/PlotControls.svelte +65 -41
- package/dist/plot/core/components/PlotControls.svelte.d.ts +1 -1
- 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 +56 -59
- package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +4 -4
- package/dist/plot/core/components/ReferencePlane.svelte +9 -10
- package/dist/plot/core/components/ReferencePlane.svelte.d.ts +4 -4
- 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 +29 -476
- package/dist/plot/core/data-transform.js +9 -5
- package/dist/plot/core/fill-utils.d.ts +7 -4
- package/dist/plot/core/fill-utils.js +34 -9
- package/dist/plot/core/index.d.ts +1 -0
- package/dist/plot/core/index.js +1 -0
- package/dist/plot/core/interactions.d.ts +5 -1
- package/dist/plot/core/interactions.js +14 -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/pan-zoom.svelte.d.ts +35 -0
- package/dist/plot/core/pan-zoom.svelte.js +221 -0
- package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -0
- package/dist/plot/core/reference-line.d.ts +10 -10
- package/dist/plot/core/reference-line.js +7 -7
- package/dist/plot/core/scales.d.ts +40 -25
- package/dist/plot/core/scales.js +49 -21
- package/dist/plot/core/svg.d.ts +2 -1
- 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 +47 -331
- 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.d.ts +1 -1
- package/dist/plot/core/utils/label-placement.js +5 -5
- package/dist/plot/core/utils.d.ts +2 -1
- package/dist/plot/histogram/Histogram.svelte +373 -631
- package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
- package/dist/plot/histogram/HistogramControls.svelte +30 -28
- package/dist/plot/histogram/HistogramControls.svelte.d.ts +1 -1
- 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 +79 -73
- package/dist/plot/sankey/Sankey.svelte.d.ts +3 -3
- package/dist/plot/sankey/SankeyControls.svelte +22 -16
- package/dist/plot/sankey/sankey.js +3 -1
- package/dist/plot/scatter/BinnedScatterPlot.svelte +264 -112
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +11 -4
- package/dist/plot/scatter/ElementScatter.svelte +4 -1
- package/dist/plot/scatter/ScatterPlot.svelte +623 -821
- package/dist/plot/scatter/ScatterPlot.svelte.d.ts +9 -15
- 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 +6 -12
- package/dist/plot/scatter/binned-scatter-types.js +6 -1
- package/dist/plot/scatter/index.d.ts +1 -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 +40 -60
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +6 -14
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +17 -15
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +5 -5
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +232 -234
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +5 -14
- package/dist/plot/scatter-3d/Surface3D.svelte +9 -17
- package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +4 -3
- package/dist/plot/sunburst/Sunburst.svelte +256 -338
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +4 -3
- 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 +14 -4
- 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 +14 -3
- package/dist/scene/SceneCamera.svelte +62 -0
- package/dist/scene/SceneCamera.svelte.d.ts +19 -0
- package/dist/scene/bind-renderer.svelte.d.ts +2 -0
- package/dist/scene/bind-renderer.svelte.js +22 -0
- package/dist/scene/index.d.ts +4 -0
- package/dist/scene/index.js +5 -0
- package/dist/scene/props.js +52 -0
- package/dist/scene/types.d.ts +26 -0
- package/dist/scene/types.js +1 -0
- package/dist/settings.d.ts +33 -11
- package/dist/settings.js +136 -51
- package/dist/spectral/Bands.svelte +231 -237
- package/dist/spectral/Bands.svelte.d.ts +3 -2
- package/dist/spectral/BandsAndDos.svelte +29 -29
- package/dist/spectral/BrillouinBandsDos.svelte +21 -29
- package/dist/spectral/Dos.svelte +75 -77
- package/dist/spectral/Dos.svelte.d.ts +2 -1
- package/dist/spectral/helpers.d.ts +9 -9
- package/dist/spectral/helpers.js +66 -70
- package/dist/state.svelte.d.ts +0 -7
- package/dist/state.svelte.js +5 -24
- package/dist/structure/Arrow.svelte +6 -21
- 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 +16 -3
- package/dist/structure/CellSelect.svelte +22 -29
- package/dist/structure/CellSelect.svelte.d.ts +2 -1
- 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 +725 -735
- package/dist/structure/Structure.svelte.d.ts +8 -16
- package/dist/structure/StructureCarousel.svelte +630 -0
- package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
- package/dist/structure/StructureControls.svelte +298 -325
- package/dist/structure/StructureControls.svelte.d.ts +5 -3
- package/dist/structure/StructureExportPane.svelte +62 -168
- package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
- package/dist/structure/StructureInfoPane.svelte +77 -69
- package/dist/structure/StructureInfoPane.svelte.d.ts +6 -6
- package/dist/structure/StructureScene.svelte +758 -600
- package/dist/structure/StructureScene.svelte.d.ts +24 -20
- package/dist/structure/StructureViewport.svelte +386 -0
- package/dist/structure/StructureViewport.svelte.d.ts +63 -0
- package/dist/structure/atom-label-placement.d.ts +18 -0
- package/dist/structure/atom-label-placement.js +115 -0
- package/dist/structure/atom-properties.d.ts +3 -1
- package/dist/structure/atom-properties.js +115 -54
- package/dist/structure/bond-order-perception.js +2 -4
- package/dist/structure/bonding.d.ts +12 -2
- package/dist/structure/bonding.js +172 -73
- package/dist/structure/edit-history.d.ts +6 -0
- package/dist/structure/edit-history.js +27 -0
- package/dist/structure/export.d.ts +25 -4
- package/dist/structure/export.js +103 -153
- 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 +18 -1
- package/dist/structure/index.js +15 -2
- package/dist/structure/measure.d.ts +1 -1
- package/dist/structure/measure.js +6 -12
- package/dist/structure/parse.d.ts +5 -3
- package/dist/structure/parse.js +551 -567
- package/dist/structure/partial-occupancy.d.ts +0 -1
- package/dist/structure/partial-occupancy.js +5 -3
- package/dist/structure/pbc.d.ts +1 -1
- package/dist/structure/pbc.js +204 -51
- package/dist/structure/polyhedra.d.ts +40 -0
- package/dist/structure/polyhedra.js +587 -0
- package/dist/structure/site.d.ts +4 -0
- package/dist/structure/site.js +1 -0
- package/dist/structure/supercell.d.ts +1 -2
- package/dist/structure/supercell.js +10 -15
- package/dist/structure/validation.js +5 -6
- package/dist/symmetry/SymmetryElementControls.svelte +69 -0
- package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
- package/dist/symmetry/SymmetryElements.svelte +350 -0
- package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
- package/dist/symmetry/SymmetryStats.svelte +142 -49
- package/dist/symmetry/WyckoffTable.svelte +58 -16
- package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
- package/dist/symmetry/cell-transform.js +8 -14
- package/dist/symmetry/index.d.ts +15 -4
- package/dist/symmetry/index.js +308 -81
- package/dist/symmetry/spacegroups.d.ts +5 -1
- package/dist/symmetry/spacegroups.js +18 -3
- package/dist/symmetry/symmetry-elements.d.ts +33 -0
- package/dist/symmetry/symmetry-elements.js +521 -0
- package/dist/symmetry/wyckoff-db.d.ts +9 -0
- package/dist/symmetry/wyckoff-db.js +87 -0
- package/dist/table/HeatmapTable.svelte +1104 -378
- 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 +556 -352
- package/dist/trajectory/Trajectory.svelte.d.ts +10 -22
- package/dist/trajectory/TrajectoryError.svelte +11 -8
- package/dist/trajectory/TrajectoryExportPane.svelte +28 -54
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
- package/dist/trajectory/TrajectoryInfoPane.svelte +88 -99
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
- package/dist/trajectory/constants.js +6 -2
- package/dist/trajectory/extract.js +73 -71
- package/dist/trajectory/format-detect.d.ts +0 -1
- package/dist/trajectory/format-detect.js +13 -17
- package/dist/trajectory/frame-reader.d.ts +2 -1
- package/dist/trajectory/frame-reader.js +74 -136
- package/dist/trajectory/helpers.d.ts +12 -2
- package/dist/trajectory/helpers.js +68 -37
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +3 -0
- package/dist/trajectory/parse/ase.d.ts +9 -1
- package/dist/trajectory/parse/ase.js +47 -32
- package/dist/trajectory/parse/diagnostics.d.ts +3 -0
- package/dist/trajectory/parse/diagnostics.js +14 -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 +3 -4
- package/dist/trajectory/parse/index.js +68 -119
- package/dist/trajectory/parse/lammps.d.ts +0 -2
- package/dist/trajectory/parse/lammps.js +14 -16
- package/dist/trajectory/parse/pymatgen.d.ts +2 -0
- package/dist/trajectory/parse/pymatgen.js +74 -0
- package/dist/trajectory/parse/vasp.js +13 -9
- 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.d.ts +9 -21
- package/dist/trajectory/parse/xyz.js +38 -39
- package/dist/trajectory/plotting.d.ts +8 -10
- package/dist/trajectory/plotting.js +102 -127
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +8 -1
- package/dist/xrd/XrdPlot.svelte +56 -85
- package/dist/xrd/broadening.d.ts +2 -1
- package/dist/xrd/broadening.js +2 -1
- package/dist/xrd/calc-xrd.js +8 -15
- package/dist/xrd/index.d.ts +2 -2
- package/dist/xrd/parse.d.ts +0 -1
- package/dist/xrd/parse.js +56 -73
- package/package.json +77 -36
- package/dist/api/mp.d.ts +0 -6
- package/dist/api/mp.js +0 -22
- package/dist/element/data.json +0 -11864
- package/dist/fermi-surface/marching-cubes.d.ts +0 -2
- package/dist/fermi-surface/marching-cubes.js +0 -2
- package/dist/plot/core/hover-lock.svelte.d.ts +0 -14
- package/dist/plot/core/hover-lock.svelte.js +0 -45
- package/dist/plot/sunburst/SunburstControls.svelte +0 -200
- package/dist/structure/label-placement.d.ts +0 -14
- package/dist/structure/label-placement.js +0 -72
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
lang="ts"
|
|
3
3
|
generics="Metadata extends Record<string, unknown> = Record<string, unknown>"
|
|
4
4
|
>
|
|
5
|
-
import type {
|
|
6
|
-
import {
|
|
5
|
+
import type { D3InterpolateName } from '../../colors'
|
|
6
|
+
import { 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'
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
BarSeries,
|
|
15
15
|
BarStyle,
|
|
16
16
|
BasePlotProps,
|
|
17
|
+
ColorScaleConfig,
|
|
17
18
|
DataLoaderFn,
|
|
18
|
-
InitialRanges,
|
|
19
19
|
InternalPoint,
|
|
20
20
|
LegendConfig,
|
|
21
21
|
LegendItem,
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
PlotConfig,
|
|
26
26
|
RefLine,
|
|
27
27
|
RefLineEvent,
|
|
28
|
-
|
|
28
|
+
SizeScaleConfig,
|
|
29
29
|
UserContentProps,
|
|
30
30
|
} from '..'
|
|
31
31
|
import {
|
|
@@ -33,53 +33,55 @@
|
|
|
33
33
|
compute_element_placement,
|
|
34
34
|
PlotAxis,
|
|
35
35
|
PlotLegend,
|
|
36
|
+
PlotMarginals,
|
|
36
37
|
ReferenceLine,
|
|
37
38
|
ScatterPoint,
|
|
38
39
|
} from '..'
|
|
39
|
-
import type {
|
|
40
|
-
import { create_axis_loader } from '../core/axis-utils'
|
|
40
|
+
import type { MarginalSeriesInput, MarginalsProp } from '../core/marginals'
|
|
41
41
|
import {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
add_sides,
|
|
43
|
+
marginal_axis,
|
|
44
|
+
marginal_axis_presence,
|
|
45
|
+
normalize_marginals,
|
|
46
|
+
reserve_marginal_pad,
|
|
47
|
+
} from '../core/marginals'
|
|
48
|
+
import { type AxisChangeState, create_axis_loader } from '../core/axis-utils'
|
|
49
|
+
import { create_placed_tween } from '../core/placed-tween.svelte'
|
|
50
|
+
import { create_pan_zoom } from '../core/pan-zoom.svelte'
|
|
45
51
|
import { create_legend_visibility } from '../core/utils/series-visibility'
|
|
46
52
|
import {
|
|
47
53
|
axis_ranges_equal,
|
|
48
|
-
|
|
49
|
-
MIN_TOUCH_DISTANCE_PIXELS,
|
|
50
|
-
pan_range_by_pixels,
|
|
51
|
-
PINCH_ZOOM_THRESHOLD,
|
|
52
|
-
remove_drag_listeners,
|
|
54
|
+
invert_rect_range,
|
|
53
55
|
resolve_axis_ranges,
|
|
54
|
-
sorted_range,
|
|
55
|
-
to_epoch_num,
|
|
56
|
-
zoom_range_by_factor,
|
|
57
56
|
} from '../core/interactions'
|
|
58
57
|
import type { IndexedRefLine } from '../core/reference-line'
|
|
59
58
|
import { group_ref_lines_by_z, index_ref_lines } from '../core/reference-line'
|
|
60
59
|
import {
|
|
60
|
+
create_axis_scales,
|
|
61
61
|
create_color_scale,
|
|
62
|
-
create_scale,
|
|
63
62
|
create_size_scale,
|
|
64
63
|
generate_ticks,
|
|
65
64
|
get_tick_label,
|
|
66
65
|
} from '../core/scales'
|
|
67
|
-
import { DEFAULT_MARKERS } from '../core/types'
|
|
66
|
+
import { DEFAULT_MARKERS, SCALE_DEFAULTS } from '../core/types'
|
|
68
67
|
import { DEFAULTS } from '../../settings'
|
|
69
68
|
import { extent } from 'd3-array'
|
|
70
69
|
import type { Snippet } from 'svelte'
|
|
71
70
|
import { onDestroy, untrack } from 'svelte'
|
|
72
71
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
73
|
-
import {
|
|
72
|
+
import type { TweenOptions } from 'svelte/motion'
|
|
74
73
|
import {
|
|
75
74
|
build_obstacles_norm,
|
|
76
75
|
clip_bar,
|
|
77
76
|
has_explicit_position,
|
|
78
77
|
measured_footprint,
|
|
79
78
|
place_decorations,
|
|
79
|
+
placed_coords,
|
|
80
80
|
} from '../core/auto-place'
|
|
81
81
|
import {
|
|
82
|
+
AXIS_TITLE_OFFSET,
|
|
82
83
|
calc_auto_padding,
|
|
84
|
+
DEFAULT_PLOT_PADDING,
|
|
83
85
|
filter_padding,
|
|
84
86
|
LABEL_GAP_DEFAULT,
|
|
85
87
|
y2_axis_label_x,
|
|
@@ -116,8 +118,8 @@
|
|
|
116
118
|
y_axis = $bindable({}),
|
|
117
119
|
y2_axis: y2_axis_prop = $bindable({}),
|
|
118
120
|
display = $bindable(DEFAULTS.bar.display),
|
|
119
|
-
range_padding = 0
|
|
120
|
-
padding =
|
|
121
|
+
range_padding = 0,
|
|
122
|
+
padding = DEFAULT_PLOT_PADDING,
|
|
121
123
|
legend = {},
|
|
122
124
|
show_legend,
|
|
123
125
|
bar = {},
|
|
@@ -129,12 +131,8 @@
|
|
|
129
131
|
on_bar_click,
|
|
130
132
|
on_bar_hover,
|
|
131
133
|
// Line marker props (matching ScatterPlot)
|
|
132
|
-
color_scale =
|
|
133
|
-
|
|
134
|
-
scheme: `interpolateViridis`,
|
|
135
|
-
value_range: undefined,
|
|
136
|
-
},
|
|
137
|
-
size_scale = { type: `linear`, radius_range: [2, 10], value_range: undefined },
|
|
134
|
+
color_scale = SCALE_DEFAULTS.color,
|
|
135
|
+
size_scale = SCALE_DEFAULTS.size,
|
|
138
136
|
point_tween,
|
|
139
137
|
on_point_click,
|
|
140
138
|
on_point_hover,
|
|
@@ -154,73 +152,65 @@
|
|
|
154
152
|
on_axis_change,
|
|
155
153
|
on_error,
|
|
156
154
|
pan = {},
|
|
155
|
+
marginals = false,
|
|
157
156
|
...rest
|
|
158
|
-
}: HTMLAttributes<HTMLDivElement> &
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
-
data_loader?: DataLoaderFn<Metadata, BarSeries<Metadata>>
|
|
216
|
-
on_axis_change?: (
|
|
217
|
-
axis: `x` | `x2` | `y` | `y2`,
|
|
218
|
-
key: string,
|
|
219
|
-
new_series: BarSeries<Metadata>[],
|
|
220
|
-
) => void
|
|
221
|
-
on_error?: (error: AxisLoadError) => void
|
|
222
|
-
pan?: PanConfig
|
|
223
|
-
} = $props()
|
|
157
|
+
}: HTMLAttributes<HTMLDivElement> &
|
|
158
|
+
BasePlotProps &
|
|
159
|
+
PlotConfig & {
|
|
160
|
+
series?: BarSeries<Metadata>[]
|
|
161
|
+
// Component-specific props
|
|
162
|
+
orientation?: Orientation
|
|
163
|
+
mode?: BarMode
|
|
164
|
+
legend?: LegendConfig | null
|
|
165
|
+
show_legend?: boolean
|
|
166
|
+
bar?: BarStyle
|
|
167
|
+
line?: LineStyle
|
|
168
|
+
tooltip?: Snippet<[BarHandlerProps<Metadata>]>
|
|
169
|
+
user_content?: Snippet<[UserContentProps]>
|
|
170
|
+
header_controls?: Snippet<[{ height: number; width: number; fullscreen: boolean }]>
|
|
171
|
+
controls_extra?: Snippet<
|
|
172
|
+
[{ orientation: Orientation; mode: BarMode } & Required<PlotConfig>]
|
|
173
|
+
>
|
|
174
|
+
change?: (data: BarHandlerProps<Metadata> | null) => void
|
|
175
|
+
on_bar_click?: (
|
|
176
|
+
data: BarHandlerProps<Metadata> & { event: MouseEvent | KeyboardEvent },
|
|
177
|
+
) => void
|
|
178
|
+
on_bar_hover?: (
|
|
179
|
+
data:
|
|
180
|
+
| (BarHandlerProps<Metadata> & { event: MouseEvent | FocusEvent | KeyboardEvent })
|
|
181
|
+
| null,
|
|
182
|
+
) => void
|
|
183
|
+
// Line marker props (matching ScatterPlot)
|
|
184
|
+
// Note: For line series with markers, BOTH on_bar_* AND on_point_* events fire.
|
|
185
|
+
// Use on_point_* for marker-specific data (includes `point` with InternalPoint details)
|
|
186
|
+
// or on_bar_* for backward compatibility with bar-style event handling.
|
|
187
|
+
color_scale?: ColorScaleConfig | D3InterpolateName
|
|
188
|
+
size_scale?: SizeScaleConfig
|
|
189
|
+
point_tween?: TweenOptions<Point2D>
|
|
190
|
+
on_point_click?: (
|
|
191
|
+
data: LineMarkerHandlerProps & { event: MouseEvent | KeyboardEvent },
|
|
192
|
+
) => void
|
|
193
|
+
on_point_hover?: (
|
|
194
|
+
data:
|
|
195
|
+
| (LineMarkerHandlerProps & {
|
|
196
|
+
event: MouseEvent | FocusEvent | KeyboardEvent
|
|
197
|
+
})
|
|
198
|
+
| null,
|
|
199
|
+
) => void
|
|
200
|
+
ref_lines?: RefLine[]
|
|
201
|
+
on_ref_line_click?: (event: RefLineEvent) => void
|
|
202
|
+
on_ref_line_hover?: (event: RefLineEvent | null) => void
|
|
203
|
+
// Interactive axis props
|
|
204
|
+
data_loader?: DataLoaderFn<Metadata, BarSeries<Metadata>>
|
|
205
|
+
on_axis_change?: (
|
|
206
|
+
axis: `x` | `x2` | `y` | `y2`,
|
|
207
|
+
key: string,
|
|
208
|
+
new_series: BarSeries<Metadata>[],
|
|
209
|
+
) => void
|
|
210
|
+
on_error?: (error: AxisLoadError) => void
|
|
211
|
+
pan?: PanConfig
|
|
212
|
+
marginals?: MarginalsProp
|
|
213
|
+
} = $props()
|
|
224
214
|
|
|
225
215
|
// Initialize bar, line, y2_axis with defaults - using $derived for reactivity
|
|
226
216
|
let bar_state = $derived({ ...DEFAULTS.bar.bar, ...bar })
|
|
@@ -240,7 +230,7 @@
|
|
|
240
230
|
format: ``,
|
|
241
231
|
scale_type: `linear`,
|
|
242
232
|
ticks: 5,
|
|
243
|
-
label_shift: { x: 0, y:
|
|
233
|
+
label_shift: { x: 0, y: AXIS_TITLE_OFFSET },
|
|
244
234
|
tick: { label: { shift: { x: 0, y: 0 } } },
|
|
245
235
|
range: [null, null],
|
|
246
236
|
...x2_axis_prop,
|
|
@@ -258,8 +248,7 @@
|
|
|
258
248
|
let axis_loading = $state<`x` | `x2` | `y` | `y2` | null>(null)
|
|
259
249
|
|
|
260
250
|
// Compute ref_lines with index and group by z-index (using shared utilities)
|
|
261
|
-
let
|
|
262
|
-
let ref_lines_by_z = $derived(group_ref_lines_by_z(indexed_ref_lines))
|
|
251
|
+
let ref_lines_by_z = $derived(group_ref_lines_by_z(index_ref_lines(ref_lines)))
|
|
263
252
|
|
|
264
253
|
// === Categorical Normalization (string x values -> integer indices, see ./data) ===
|
|
265
254
|
let cat_norm = $derived(normalize_categorical(series, x_axis.categories))
|
|
@@ -277,47 +266,44 @@
|
|
|
277
266
|
const axis_px = (orientation === `horizontal` ? height : width) || 0
|
|
278
267
|
const max_ticks = Math.max(1, Math.floor(axis_px / 28)) // ~28px per category label
|
|
279
268
|
const step = Math.ceil(category_indices.length / max_ticks)
|
|
280
|
-
return step <= 1
|
|
281
|
-
? category_indices
|
|
282
|
-
: category_indices.filter((_, idx) => idx % step === 0)
|
|
269
|
+
return step <= 1 ? category_indices : category_indices.filter((_, idx) => idx % step === 0)
|
|
283
270
|
})
|
|
284
271
|
|
|
285
272
|
// Compute auto ranges from visible series
|
|
286
|
-
let visible_series = $derived(
|
|
287
|
-
internal_series.filter((srs) => srs?.visible ?? true),
|
|
288
|
-
)
|
|
273
|
+
let visible_series = $derived(internal_series.filter((srs) => srs?.visible ?? true))
|
|
289
274
|
|
|
290
275
|
// Separate series by y-axis
|
|
291
|
-
let y1_series = $derived(
|
|
292
|
-
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
|
|
276
|
+
let y1_series = $derived(visible_series.filter((srs) => (srs.y_axis ?? `y1`) === `y1`))
|
|
277
|
+
let y2_series = $derived(visible_series.filter((srs) => srs.y_axis === `y2`))
|
|
278
|
+
let x2_series = $derived(visible_series.filter((srs) => srs.x_axis === `x2`))
|
|
279
|
+
// Whether the secondary x2 (top) / y2 (right) axis actually renders: BarPlot only supports
|
|
280
|
+
// them in vertical orientation. Derive once so ticks, padding, axis rendering, and marginal
|
|
281
|
+
// placement stay in sync. (Data-existence checks below use the bare `*_series.length` instead.)
|
|
282
|
+
let show_x2 = $derived(x2_series.length > 0 && orientation === `vertical`)
|
|
283
|
+
let show_y2 = $derived(y2_series.length > 0 && orientation === `vertical`)
|
|
284
|
+
|
|
285
|
+
let auto_ranges = $derived(
|
|
286
|
+
compute_bar_auto_ranges({
|
|
287
|
+
visible_series,
|
|
288
|
+
y1_series,
|
|
289
|
+
y2_series,
|
|
290
|
+
x2_series,
|
|
291
|
+
mode,
|
|
292
|
+
orientation,
|
|
293
|
+
range_padding,
|
|
294
|
+
category_count: category_list.length,
|
|
295
|
+
x_range: x_axis.range ?? [null, null],
|
|
296
|
+
x_scale_type: x_axis.scale_type ?? `linear`,
|
|
297
|
+
x_is_time: x_axis.format?.startsWith(`%`) || false,
|
|
298
|
+
x2_range: x2_axis.range ?? [null, null],
|
|
299
|
+
x2_scale_type: x2_axis.scale_type ?? `linear`,
|
|
300
|
+
x2_is_time: x2_axis.format?.startsWith(`%`) || false,
|
|
301
|
+
y_range: y_axis.range ?? [null, null],
|
|
302
|
+
y_scale_type: y_axis.scale_type ?? `linear`,
|
|
303
|
+
y2_range: y2_axis.range ?? [null, null],
|
|
304
|
+
y2_scale_type: y2_axis.scale_type ?? `linear`,
|
|
305
|
+
}),
|
|
296
306
|
)
|
|
297
|
-
let x2_series = $derived(
|
|
298
|
-
visible_series.filter((srs) => srs.x_axis === `x2`),
|
|
299
|
-
)
|
|
300
|
-
|
|
301
|
-
let auto_ranges = $derived(compute_bar_auto_ranges({
|
|
302
|
-
visible_series,
|
|
303
|
-
y1_series,
|
|
304
|
-
y2_series,
|
|
305
|
-
x2_series,
|
|
306
|
-
mode,
|
|
307
|
-
orientation,
|
|
308
|
-
range_padding,
|
|
309
|
-
category_count: category_list.length,
|
|
310
|
-
x_range: x_axis.range ?? [null, null],
|
|
311
|
-
x_scale_type: x_axis.scale_type ?? `linear`,
|
|
312
|
-
x_is_time: x_axis.format?.startsWith(`%`) || false,
|
|
313
|
-
x2_range: x2_axis.range ?? [null, null],
|
|
314
|
-
x2_scale_type: x2_axis.scale_type ?? `linear`,
|
|
315
|
-
x2_is_time: x2_axis.format?.startsWith(`%`) || false,
|
|
316
|
-
y_range: y_axis.range ?? [null, null],
|
|
317
|
-
y_scale_type: y_axis.scale_type ?? `linear`,
|
|
318
|
-
y2_range: y2_axis.range ?? [null, null],
|
|
319
|
-
y2_scale_type: y2_axis.scale_type ?? `linear`,
|
|
320
|
-
}))
|
|
321
307
|
|
|
322
308
|
// Initialize and current ranges
|
|
323
309
|
let ranges = $state<{
|
|
@@ -328,10 +314,14 @@
|
|
|
328
314
|
current: { x: [0, 1], x2: [0, 1], y: [0, 1], y2: [0, 1] },
|
|
329
315
|
})
|
|
330
316
|
|
|
331
|
-
$effect(() => {
|
|
317
|
+
$effect(() => {
|
|
318
|
+
// handle x_axis.range / x2_axis.range / y_axis.range / y2_axis.range changes
|
|
332
319
|
// resolve_axis_ranges returns null for transient non-finite bounds (skip: writing
|
|
333
320
|
// NaN breaks scales and, since NaN !== NaN, loops the effect)
|
|
334
|
-
const next = resolve_axis_ranges(
|
|
321
|
+
const next = resolve_axis_ranges(
|
|
322
|
+
{ x: x_axis, x2: x2_axis, y: y_axis, y2: y2_axis },
|
|
323
|
+
auto_ranges,
|
|
324
|
+
)
|
|
335
325
|
if (!next) return
|
|
336
326
|
// Only update if the initial (data-driven) ranges changed, not when user pans.
|
|
337
327
|
// untrack the read of `ranges` so the assignment below can't re-trigger this effect
|
|
@@ -343,42 +333,33 @@
|
|
|
343
333
|
})
|
|
344
334
|
|
|
345
335
|
// Layout: dynamic padding based on tick label widths
|
|
346
|
-
const default_padding = { t: 20, b: 60, l: 60, r: 20 }
|
|
347
336
|
// base_pad reserves space for tick labels/axis titles; pad (below) adds decoration reservations
|
|
348
|
-
let base_pad = $derived(filter_padding(padding,
|
|
337
|
+
let base_pad = $derived(filter_padding(padding, DEFAULT_PLOT_PADDING))
|
|
349
338
|
|
|
350
339
|
// Update padding when format or ticks change
|
|
351
340
|
$effect(() => {
|
|
352
|
-
const new_pad =
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
341
|
+
const new_pad =
|
|
342
|
+
width && height && ticks.y.length > 0
|
|
343
|
+
? calc_auto_padding({
|
|
344
|
+
padding,
|
|
345
|
+
default_padding: DEFAULT_PLOT_PADDING,
|
|
346
|
+
x2_axis: { ...x2_axis, tick_values: ticks.x2 },
|
|
347
|
+
y_axis: { ...y_axis, tick_values: ticks.y },
|
|
348
|
+
y2_axis: { ...y2_axis, tick_values: ticks.y2 },
|
|
349
|
+
})
|
|
350
|
+
: filter_padding(padding, DEFAULT_PLOT_PADDING)
|
|
361
351
|
// Expand right padding if y2 ticks are shown (only for vertical orientation)
|
|
362
|
-
if (
|
|
363
|
-
width && height && y2_series.length > 0 && ticks.y2.length > 0 &&
|
|
364
|
-
orientation === `vertical`
|
|
365
|
-
) {
|
|
352
|
+
if (width && height && show_y2 && ticks.y2.length > 0) {
|
|
366
353
|
// Need space for: tick shift + tick width + gap (30px) + label space (20px if present)
|
|
367
354
|
// When ticks are inside, they don't contribute to padding
|
|
368
355
|
const inside = y2_axis.tick?.label?.inside ?? false
|
|
369
356
|
const tick_shift = inside ? 0 : (y2_axis.tick?.label?.shift?.x ?? 0) + 8
|
|
370
357
|
const tick_width_contribution = inside ? 0 : tick_label_widths.y2_max
|
|
371
358
|
const label_space = y2_axis.label ? 20 : 0
|
|
372
|
-
new_pad.r = Math.max(
|
|
373
|
-
new_pad.r,
|
|
374
|
-
tick_shift + tick_width_contribution + 30 + label_space,
|
|
375
|
-
)
|
|
359
|
+
new_pad.r = Math.max(new_pad.r, tick_shift + tick_width_contribution + 30 + label_space)
|
|
376
360
|
}
|
|
377
361
|
// Expand top padding if x2 ticks are shown (only for vertical orientation)
|
|
378
|
-
if (
|
|
379
|
-
width && height && x2_series.length > 0 && ticks.x2.length > 0 &&
|
|
380
|
-
orientation === `vertical`
|
|
381
|
-
) {
|
|
362
|
+
if (width && height && show_x2 && ticks.x2.length > 0) {
|
|
382
363
|
const inside = x2_axis.tick?.label?.inside ?? false
|
|
383
364
|
const tick_shift = inside ? 0 : Math.abs(x2_axis.tick?.label?.shift?.y ?? 0) + 5
|
|
384
365
|
const tick_height = inside ? 0 : 16
|
|
@@ -388,13 +369,18 @@
|
|
|
388
369
|
|
|
389
370
|
// Only update if padding actually changed (prevents infinite loop)
|
|
390
371
|
if (
|
|
391
|
-
base_pad.t !== new_pad.t ||
|
|
392
|
-
base_pad.
|
|
393
|
-
|
|
372
|
+
base_pad.t !== new_pad.t ||
|
|
373
|
+
base_pad.b !== new_pad.b ||
|
|
374
|
+
base_pad.l !== new_pad.l ||
|
|
375
|
+
base_pad.r !== new_pad.r
|
|
376
|
+
)
|
|
377
|
+
base_pad = new_pad
|
|
394
378
|
})
|
|
395
379
|
|
|
396
380
|
let legend_element = $state<HTMLDivElement | undefined>()
|
|
397
|
-
const legend_footprint = $derived(
|
|
381
|
+
const legend_footprint = $derived(
|
|
382
|
+
measured_footprint(legend_element, { width: 120, height: 60 }),
|
|
383
|
+
)
|
|
398
384
|
const legend_has_explicit_pos = $derived(has_explicit_position(legend?.style))
|
|
399
385
|
|
|
400
386
|
// Obstacle field in normalized [0,1] plot coords (y=0 at top). Each bar is modeled as a segment
|
|
@@ -423,8 +409,18 @@
|
|
|
423
409
|
const value = base + srs.y[bar_idx]
|
|
424
410
|
// vertical: category on x, value rises on y (inverted). horizontal: category on y, value on x
|
|
425
411
|
const seg = vertical
|
|
426
|
-
? clip_bar(
|
|
427
|
-
|
|
412
|
+
? clip_bar(
|
|
413
|
+
true,
|
|
414
|
+
(x_val - ax0) / x_span,
|
|
415
|
+
1 - (value - vy0) / y_span,
|
|
416
|
+
1 - (base - vy0) / y_span,
|
|
417
|
+
)
|
|
418
|
+
: clip_bar(
|
|
419
|
+
false,
|
|
420
|
+
1 - (x_val - cy0) / cy_span,
|
|
421
|
+
(value - ax0) / x_span,
|
|
422
|
+
(base - ax0) / x_span,
|
|
423
|
+
)
|
|
428
424
|
if (seg) bars.push(seg)
|
|
429
425
|
})
|
|
430
426
|
})
|
|
@@ -439,39 +435,58 @@
|
|
|
439
435
|
height,
|
|
440
436
|
obstacles_norm,
|
|
441
437
|
// gate on legend_element (the render signal) not legend_data, whose entries can read pad
|
|
442
|
-
legend:
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
438
|
+
legend:
|
|
439
|
+
legend != null &&
|
|
440
|
+
(show_legend !== undefined ? show_legend : series.length > 1) &&
|
|
441
|
+
legend_element != null &&
|
|
442
|
+
!legend_has_explicit_pos
|
|
443
|
+
? { footprint: legend_footprint, clearance: legend?.axis_clearance }
|
|
444
|
+
: null,
|
|
445
|
+
}),
|
|
448
446
|
)
|
|
449
|
-
|
|
447
|
+
// Resolve marginals: a cumulative/Pareto CDF over the CATEGORY axis weighted by bar height.
|
|
448
|
+
// Categories sit on x (vertical) or y (horizontal), so the default side and the value array
|
|
449
|
+
// flip with orientation. The value axis carries no marginal (a bar's height isn't a sample).
|
|
450
|
+
const marginal_is_vertical = $derived(orientation === `vertical`)
|
|
451
|
+
const resolved_marginals = $derived(
|
|
452
|
+
normalize_marginals(
|
|
453
|
+
marginals,
|
|
454
|
+
marginal_is_vertical ? { top: { type: `cdf` } } : { right: { type: `cdf` } },
|
|
455
|
+
),
|
|
456
|
+
)
|
|
457
|
+
const pad = $derived(add_sides(decor.pad, reserve_marginal_pad(resolved_marginals)))
|
|
458
|
+
const marginal_series = $derived<MarginalSeriesInput[]>(
|
|
459
|
+
internal_series.map((srs) => ({
|
|
460
|
+
x: marginal_is_vertical ? (srs?.x ?? []) : undefined,
|
|
461
|
+
y: marginal_is_vertical ? undefined : (srs?.x ?? []),
|
|
462
|
+
// magnitude weights so negative bars still yield a monotonic cumulative (CDF) marginal
|
|
463
|
+
weight: srs?.y?.map((value) => Math.abs(value)) ?? [],
|
|
464
|
+
color:
|
|
465
|
+
srs?.color ??
|
|
466
|
+
(srs?.render_mode === `line` ? line_state.color : bar_state.color) ??
|
|
467
|
+
`steelblue`,
|
|
468
|
+
label: srs?.label,
|
|
469
|
+
visible: srs?.visible ?? true,
|
|
470
|
+
x_axis: srs?.x_axis,
|
|
471
|
+
y_axis: srs?.y_axis,
|
|
472
|
+
})),
|
|
473
|
+
)
|
|
474
|
+
const marginal_has_axis = $derived(marginal_axis_presence(show_x2, show_y2))
|
|
450
475
|
const legend_auto_outside = $derived(decor.legend_outside)
|
|
451
476
|
const legend_outside_x = $derived(decor.legend_pos.x)
|
|
452
477
|
const legend_outside_y = $derived(decor.legend_pos.y)
|
|
453
478
|
const chart_width = $derived(Math.max(1, width - pad.l - pad.r))
|
|
454
479
|
const chart_height = $derived(Math.max(1, height - pad.t - pad.b))
|
|
455
480
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
]),
|
|
466
|
-
y: create_scale(y_axis.scale_type ?? `linear`, ranges.current.y, [
|
|
467
|
-
height - pad.b,
|
|
468
|
-
pad.t,
|
|
469
|
-
]),
|
|
470
|
-
y2: create_scale(y2_axis.scale_type ?? `linear`, ranges.current.y2, [
|
|
471
|
-
height - pad.b,
|
|
472
|
-
pad.t,
|
|
473
|
-
]),
|
|
474
|
-
})
|
|
481
|
+
let scales = $derived(
|
|
482
|
+
create_axis_scales(
|
|
483
|
+
{ x: x_axis, x2: x2_axis, y: y_axis, y2: y2_axis },
|
|
484
|
+
ranges.current,
|
|
485
|
+
pad,
|
|
486
|
+
width,
|
|
487
|
+
height,
|
|
488
|
+
),
|
|
489
|
+
)
|
|
475
490
|
|
|
476
491
|
// Compute plot center for point tweening origin
|
|
477
492
|
let plot_center_x = $derived(pad.l + (width - pad.r - pad.l) / 2)
|
|
@@ -482,14 +497,12 @@
|
|
|
482
497
|
visible_series
|
|
483
498
|
.filter((srs: BarSeries<Metadata>) => srs.render_mode === `line`)
|
|
484
499
|
.flatMap((srs: BarSeries<Metadata>) =>
|
|
485
|
-
(srs.color_values ?? []).filter(
|
|
486
|
-
(val): val is number => typeof val === `number`,
|
|
487
|
-
)
|
|
500
|
+
(srs.color_values ?? []).filter((val): val is number => typeof val === `number`),
|
|
488
501
|
),
|
|
489
502
|
)
|
|
490
503
|
|
|
491
504
|
// Create auto color range (safely handle empty arrays or undefined extent results)
|
|
492
|
-
let auto_color_range:
|
|
505
|
+
let auto_color_range: Vec2 = $derived.by(() => {
|
|
493
506
|
if (all_color_values.length === 0) return [0, 1]
|
|
494
507
|
const [min_val, max_val] = extent(all_color_values)
|
|
495
508
|
return [min_val ?? 0, max_val ?? 1]
|
|
@@ -500,9 +513,7 @@
|
|
|
500
513
|
visible_series
|
|
501
514
|
.filter((srs: BarSeries<Metadata>) => srs.render_mode === `line`)
|
|
502
515
|
.flatMap((srs: BarSeries<Metadata>) =>
|
|
503
|
-
[...(srs.size_values ?? [])].filter(
|
|
504
|
-
(val): val is number => typeof val === `number`,
|
|
505
|
-
)
|
|
516
|
+
[...(srs.size_values ?? [])].filter((val): val is number => typeof val === `number`),
|
|
506
517
|
),
|
|
507
518
|
)
|
|
508
519
|
|
|
@@ -520,57 +531,37 @@
|
|
|
520
531
|
// Only respect user ticks when they're a Record (custom label mapping),
|
|
521
532
|
// not a number (tick count) or array (tick positions)
|
|
522
533
|
const user_ticks = cat_axis === `x` ? x_axis.ticks : y_axis.ticks
|
|
523
|
-
if (
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
) return user_ticks
|
|
527
|
-
return Object.fromEntries(
|
|
528
|
-
category_list.map((cat, idx) => [idx, cat]),
|
|
529
|
-
) as Record<number, string>
|
|
534
|
+
if (user_ticks != null && typeof user_ticks === `object` && !Array.isArray(user_ticks))
|
|
535
|
+
return user_ticks
|
|
536
|
+
return Object.fromEntries(category_list.map((cat, idx): [number, string] => [idx, cat]))
|
|
530
537
|
})
|
|
531
538
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
:
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
{
|
|
559
|
-
default_count: 6,
|
|
560
|
-
},
|
|
561
|
-
)
|
|
562
|
-
: [],
|
|
563
|
-
x2: width && height && x2_series.length > 0 && orientation === `vertical`
|
|
564
|
-
? generate_ticks(
|
|
565
|
-
ranges.current.x2,
|
|
566
|
-
x2_axis.scale_type ?? `linear`,
|
|
567
|
-
x2_axis.ticks,
|
|
568
|
-
scales.x2,
|
|
569
|
-
{
|
|
570
|
-
default_count: 8,
|
|
571
|
-
},
|
|
572
|
-
)
|
|
573
|
-
: [],
|
|
539
|
+
let ticks = $derived.by(() => {
|
|
540
|
+
const axis_ticks = (
|
|
541
|
+
axis: typeof x_axis,
|
|
542
|
+
range: Vec2,
|
|
543
|
+
scale: typeof scales.x,
|
|
544
|
+
default_count: number,
|
|
545
|
+
show = true,
|
|
546
|
+
) =>
|
|
547
|
+
width && height && show
|
|
548
|
+
? generate_ticks(range, axis.scale_type ?? `linear`, axis.ticks, scale, {
|
|
549
|
+
default_count,
|
|
550
|
+
})
|
|
551
|
+
: []
|
|
552
|
+
// categorical axes show one tick per category instead of generated numeric ticks
|
|
553
|
+
return {
|
|
554
|
+
x:
|
|
555
|
+
category_indices && cat_axis === `x` && width && height
|
|
556
|
+
? cat_tick_indices
|
|
557
|
+
: axis_ticks(x_axis, ranges.current.x, scales.x, 8),
|
|
558
|
+
y:
|
|
559
|
+
category_indices && cat_axis === `y` && width && height
|
|
560
|
+
? cat_tick_indices
|
|
561
|
+
: axis_ticks(y_axis, ranges.current.y, scales.y, 6),
|
|
562
|
+
y2: axis_ticks(y2_axis, ranges.current.y2, scales.y2, 6, show_y2),
|
|
563
|
+
x2: axis_ticks(x2_axis, ranges.current.x2, scales.x2, 8, show_x2),
|
|
564
|
+
}
|
|
574
565
|
})
|
|
575
566
|
|
|
576
567
|
// Cache measured tick-label widths so expensive canvas text measurement
|
|
@@ -581,212 +572,45 @@
|
|
|
581
572
|
x2_max: measure_max_tick_width(ticks.x2, x2_axis.format ?? ``),
|
|
582
573
|
})
|
|
583
574
|
|
|
584
|
-
//
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
const y2_2 = scales.y2.invert(drag_state.current.y)
|
|
615
|
-
const x2a_1_raw = scales.x2.invert(drag_state.start.x) as number | Date
|
|
616
|
-
const x2a_2_raw = scales.x2.invert(drag_state.current.x) as number | Date
|
|
617
|
-
const dx = Math.abs(drag_state.start.x - drag_state.current.x)
|
|
618
|
-
const dy = Math.abs(drag_state.start.y - drag_state.current.y)
|
|
619
|
-
|
|
620
|
-
// Same scale inverts both coords, so each pair is all-number or all-Date
|
|
621
|
-
const [xr1, xr2] = [to_epoch_num(x1_raw), to_epoch_num(x2_raw)]
|
|
622
|
-
const [x2r1, x2r2] = [to_epoch_num(x2a_1_raw), to_epoch_num(x2a_2_raw)]
|
|
623
|
-
|
|
624
|
-
if (dx > 5 && dy > 5 && Number.isFinite(xr1) && Number.isFinite(xr2)) {
|
|
625
|
-
// Update axis ranges to trigger reactivity and prevent effect from overriding
|
|
626
|
-
x_axis = { ...x_axis, range: sorted_range(xr1, xr2) }
|
|
627
|
-
if (x2_series.length > 0 && Number.isFinite(x2r1) && Number.isFinite(x2r2)) {
|
|
628
|
-
x2_axis_prop = { ...x2_axis_prop, range: sorted_range(x2r1, x2r2) }
|
|
629
|
-
}
|
|
630
|
-
y_axis = { ...y_axis, range: sorted_range(y1, y2) }
|
|
631
|
-
// gate on y2 series presence (like x2): the y2 scale is a [0, 1] sentinel
|
|
632
|
-
// otherwise, so inverting would store a phantom range in the bindable prop
|
|
633
|
-
if (y2_series.length > 0) {
|
|
634
|
-
y2_axis_prop = { ...y2_axis_prop, range: sorted_range(y2_1, y2_2) }
|
|
635
|
-
}
|
|
575
|
+
// Shared pan/zoom/touch/drag-rect interaction controller
|
|
576
|
+
const pan_zoom = create_pan_zoom({
|
|
577
|
+
ranges: () => ranges.current,
|
|
578
|
+
scale_type: (axis) =>
|
|
579
|
+
({ x: x_axis, x2: x2_axis, y: y_axis, y2: y2_axis })[axis].scale_type,
|
|
580
|
+
plot_dims: () => ({ width: chart_width, height: chart_height }),
|
|
581
|
+
pan: () => pan,
|
|
582
|
+
set_range: (axis, range) => (ranges.current[axis] = range),
|
|
583
|
+
svg: () => svg_element,
|
|
584
|
+
on_rect_zoom: (start, current) => {
|
|
585
|
+
// Update axis ranges to trigger reactivity and prevent effect from overriding
|
|
586
|
+
const next_x = invert_rect_range(scales.x, start.x, current.x)
|
|
587
|
+
if (!next_x) return
|
|
588
|
+
x_axis = { ...x_axis, range: next_x }
|
|
589
|
+
// gate x2/y2 on whether they actually render (show_x2/show_y2 also require vertical);
|
|
590
|
+
// otherwise their [0, 1] sentinel scales would store a phantom range in the bindable prop
|
|
591
|
+
const next_x2 = show_x2 ? invert_rect_range(scales.x2, start.x, current.x) : null
|
|
592
|
+
if (next_x2) x2_axis_prop = { ...x2_axis_prop, range: next_x2 }
|
|
593
|
+
const next_y = invert_rect_range(scales.y, start.y, current.y)
|
|
594
|
+
if (next_y) y_axis = { ...y_axis, range: next_y }
|
|
595
|
+
const next_y2 = show_y2 ? invert_rect_range(scales.y2, start.y, current.y) : null
|
|
596
|
+
if (next_y2) y2_axis_prop = { ...y2_axis_prop, range: next_y2 }
|
|
597
|
+
},
|
|
598
|
+
on_reset: () => {
|
|
599
|
+
// Reset zoom to initial ranges (undo any pan/zoom)
|
|
600
|
+
ranges.current = {
|
|
601
|
+
x: [...ranges.initial.x] as Vec2,
|
|
602
|
+
x2: [...ranges.initial.x2] as Vec2,
|
|
603
|
+
y: [...ranges.initial.y] as Vec2,
|
|
604
|
+
y2: [...ranges.initial.y2] as Vec2,
|
|
636
605
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
// Pan/zoom all four axes from an interaction-start snapshot, each in its own
|
|
645
|
-
// scale's transform space (log axes pan by a constant factor, linear by a shift)
|
|
646
|
-
const pan_all_axes = (init: InitialRanges, dx_px: number, dy_px: number) => {
|
|
647
|
-
ranges.current.x = pan_range_by_pixels(init.initial_x_range, dx_px, chart_width, x_axis.scale_type)
|
|
648
|
-
ranges.current.x2 = pan_range_by_pixels(init.initial_x2_range, dx_px, chart_width, x2_axis.scale_type)
|
|
649
|
-
ranges.current.y = pan_range_by_pixels(init.initial_y_range, dy_px, chart_height, y_axis.scale_type)
|
|
650
|
-
ranges.current.y2 = pan_range_by_pixels(init.initial_y2_range, dy_px, chart_height, y2_axis.scale_type)
|
|
651
|
-
}
|
|
652
|
-
const zoom_all_axes = (init: InitialRanges, factor: number) => {
|
|
653
|
-
ranges.current.x = zoom_range_by_factor(init.initial_x_range, factor, x_axis.scale_type)
|
|
654
|
-
ranges.current.x2 = zoom_range_by_factor(init.initial_x2_range, factor, x2_axis.scale_type)
|
|
655
|
-
ranges.current.y = zoom_range_by_factor(init.initial_y_range, factor, y_axis.scale_type)
|
|
656
|
-
ranges.current.y2 = zoom_range_by_factor(init.initial_y2_range, factor, y2_axis.scale_type)
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
// Pan drag handler (drag direction inverted on x for natural pan feel)
|
|
660
|
-
const on_pan_move = (evt: MouseEvent) => {
|
|
661
|
-
if (!pan_drag_state) return
|
|
662
|
-
const sensitivity = pan?.drag_sensitivity ?? 1
|
|
663
|
-
pan_all_axes(
|
|
664
|
-
pan_drag_state,
|
|
665
|
-
-(evt.clientX - pan_drag_state.start.x) * sensitivity,
|
|
666
|
-
(evt.clientY - pan_drag_state.start.y) * sensitivity,
|
|
667
|
-
)
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
const on_pan_end = () => {
|
|
671
|
-
pan_drag_state = null
|
|
672
|
-
document.body.style.cursor = ``
|
|
673
|
-
window.removeEventListener(`mousemove`, on_pan_move)
|
|
674
|
-
window.removeEventListener(`mouseup`, on_pan_end)
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
// Tear down any window listeners + cursor override if the component unmounts mid-drag
|
|
678
|
-
// (mouseup/panend would otherwise never fire, leaking listeners and a stuck cursor).
|
|
679
|
-
// onDestroy also runs during SSR teardown, where window/document don't exist.
|
|
680
|
-
onDestroy(() => {
|
|
681
|
-
remove_drag_listeners([on_window_mouse_move, on_pan_move], [on_window_mouse_up, on_pan_end])
|
|
682
|
-
drag_state = { start: null, current: null, bounds: null }
|
|
683
|
-
pan_drag_state = null
|
|
606
|
+
// Also reset axis props so future data changes recalculate auto ranges
|
|
607
|
+
x_axis = { ...x_axis, range: [null, null] }
|
|
608
|
+
x2_axis_prop = { ...x2_axis_prop, range: [null, null] }
|
|
609
|
+
y_axis = { ...y_axis, range: [null, null] }
|
|
610
|
+
y2_axis_prop = { ...y2_axis_prop, range: [null, null] }
|
|
611
|
+
},
|
|
684
612
|
})
|
|
685
|
-
|
|
686
|
-
function handle_mouse_down(evt: MouseEvent) {
|
|
687
|
-
const coords = get_relative_coords(evt)
|
|
688
|
-
if (!coords || !svg_element) return
|
|
689
|
-
|
|
690
|
-
// Check if pan is enabled and shift is held for pan mode
|
|
691
|
-
const pan_enabled = pan?.enabled !== false
|
|
692
|
-
if (pan_enabled && evt.shiftKey) {
|
|
693
|
-
evt.preventDefault()
|
|
694
|
-
pan_drag_state = {
|
|
695
|
-
start: { x: evt.clientX, y: evt.clientY },
|
|
696
|
-
initial_x_range: [...ranges.current.x] as [number, number],
|
|
697
|
-
initial_x2_range: [...ranges.current.x2] as [number, number],
|
|
698
|
-
initial_y_range: [...ranges.current.y] as [number, number],
|
|
699
|
-
initial_y2_range: [...ranges.current.y2] as [number, number],
|
|
700
|
-
}
|
|
701
|
-
document.body.style.cursor = `grabbing`
|
|
702
|
-
window.addEventListener(`mousemove`, on_pan_move)
|
|
703
|
-
window.addEventListener(`mouseup`, on_pan_end)
|
|
704
|
-
return
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
drag_state = {
|
|
708
|
-
start: coords,
|
|
709
|
-
current: coords,
|
|
710
|
-
bounds: svg_element.getBoundingClientRect(),
|
|
711
|
-
}
|
|
712
|
-
window.addEventListener(`mousemove`, on_window_mouse_move)
|
|
713
|
-
window.addEventListener(`mouseup`, on_window_mouse_up)
|
|
714
|
-
evt.preventDefault()
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
// Wheel handler for pan (requires focus and shift)
|
|
718
|
-
function handle_wheel(evt: WheelEvent) {
|
|
719
|
-
const pan_enabled = pan?.enabled !== false
|
|
720
|
-
// Only capture wheel when focused AND Shift is held
|
|
721
|
-
// Use shift_held state (tracked via keydown/keyup) for compatibility with synthetic events
|
|
722
|
-
if (!pan_enabled || !is_focused || !shift_held) return
|
|
723
|
-
|
|
724
|
-
evt.preventDefault()
|
|
725
|
-
|
|
726
|
-
const sensitivity = pan?.wheel_sensitivity ?? 1
|
|
727
|
-
|
|
728
|
-
// Pan along the dominant wheel direction
|
|
729
|
-
if (Math.abs(evt.deltaX) > Math.abs(evt.deltaY)) {
|
|
730
|
-
const dx = evt.deltaX * sensitivity
|
|
731
|
-
ranges.current.x = pan_range_by_pixels(ranges.current.x, dx, chart_width, x_axis.scale_type)
|
|
732
|
-
ranges.current.x2 = pan_range_by_pixels(ranges.current.x2, dx, chart_width, x2_axis.scale_type)
|
|
733
|
-
} else {
|
|
734
|
-
const dy = evt.deltaY * sensitivity
|
|
735
|
-
ranges.current.y = pan_range_by_pixels(ranges.current.y, dy, chart_height, y_axis.scale_type)
|
|
736
|
-
ranges.current.y2 = pan_range_by_pixels(ranges.current.y2, dy, chart_height, y2_axis.scale_type)
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
// Touch handlers for pinch-zoom and two-finger pan
|
|
741
|
-
function handle_touch_start(evt: TouchEvent) {
|
|
742
|
-
const touch_enabled = pan?.enabled !== false && pan?.touch_enabled !== false
|
|
743
|
-
if (!touch_enabled || evt.touches.length !== 2) return
|
|
744
|
-
|
|
745
|
-
evt.preventDefault()
|
|
746
|
-
const touches = Array.from(evt.touches)
|
|
747
|
-
touch_state = {
|
|
748
|
-
start_touches: touches.map((touch) => ({ x: touch.clientX, y: touch.clientY })),
|
|
749
|
-
initial_x_range: [...ranges.current.x] as [number, number],
|
|
750
|
-
initial_x2_range: [...ranges.current.x2] as [number, number],
|
|
751
|
-
initial_y_range: [...ranges.current.y] as [number, number],
|
|
752
|
-
initial_y2_range: [...ranges.current.y2] as [number, number],
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
function handle_touch_move(evt: TouchEvent) {
|
|
757
|
-
if (!touch_state || evt.touches.length !== 2) return
|
|
758
|
-
evt.preventDefault()
|
|
759
|
-
|
|
760
|
-
const [t1, t2] = Array.from(evt.touches)
|
|
761
|
-
const [s1, s2] = touch_state.start_touches
|
|
762
|
-
|
|
763
|
-
// Calculate center movement for pan
|
|
764
|
-
const start_center = { x: (s1.x + s2.x) / 2, y: (s1.y + s2.y) / 2 }
|
|
765
|
-
const curr_center = {
|
|
766
|
-
x: (t1.clientX + t2.clientX) / 2,
|
|
767
|
-
y: (t1.clientY + t2.clientY) / 2,
|
|
768
|
-
}
|
|
769
|
-
const dx = curr_center.x - start_center.x
|
|
770
|
-
const dy = curr_center.y - start_center.y
|
|
771
|
-
|
|
772
|
-
// Calculate pinch scale (curr/start so spread = zoom out, pinch = zoom in)
|
|
773
|
-
const start_dist = Math.hypot(s2.x - s1.x, s2.y - s1.y)
|
|
774
|
-
// ignore near-coincident touches so curr_dist / start_dist can't blow up the scale
|
|
775
|
-
if (start_dist < MIN_TOUCH_DISTANCE_PIXELS) return
|
|
776
|
-
const curr_dist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY)
|
|
777
|
-
const scale = curr_dist / start_dist
|
|
778
|
-
|
|
779
|
-
// If scale changed significantly, treat as pinch-zoom
|
|
780
|
-
// Also guard against scale being too small to avoid division by zero
|
|
781
|
-
// Pinch zoom about the view center (spread = zoom in, pinch = zoom out)
|
|
782
|
-
if (Math.abs(scale - 1) > PINCH_ZOOM_THRESHOLD && scale > Number.EPSILON) {
|
|
783
|
-
zoom_all_axes(touch_state, scale)
|
|
784
|
-
} else pan_all_axes(touch_state, -dx, dy)
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
function handle_touch_end() {
|
|
788
|
-
touch_state = null
|
|
789
|
-
}
|
|
613
|
+
onDestroy(() => pan_zoom.destroy())
|
|
790
614
|
|
|
791
615
|
// Legend data and handlers
|
|
792
616
|
let legend_data = $derived.by<LegendItem[]>(() =>
|
|
@@ -794,8 +618,7 @@
|
|
|
794
618
|
const is_line = srs.render_mode === `line`
|
|
795
619
|
const series_markers = srs.markers ?? DEFAULT_MARKERS
|
|
796
620
|
const has_line = series_markers === `line` || series_markers === `line+points`
|
|
797
|
-
const has_points = series_markers === `points` ||
|
|
798
|
-
series_markers === `line+points`
|
|
621
|
+
const has_points = series_markers === `points` || series_markers === `line+points`
|
|
799
622
|
const series_color = srs.color ?? (is_line ? line_state.color : bar_state.color)
|
|
800
623
|
|
|
801
624
|
// Get point style for symbol color (handle array or single object)
|
|
@@ -803,9 +626,10 @@
|
|
|
803
626
|
? srs.point_style[0]
|
|
804
627
|
: srs.point_style
|
|
805
628
|
const first_color_value = srs.color_values?.[0]
|
|
806
|
-
const point_color =
|
|
807
|
-
|
|
808
|
-
|
|
629
|
+
const point_color =
|
|
630
|
+
first_color_value != null
|
|
631
|
+
? color_scale_fn(first_color_value)
|
|
632
|
+
: (first_point_style?.fill ?? series_color)
|
|
809
633
|
|
|
810
634
|
if (is_line) {
|
|
811
635
|
// Line series: show line and/or symbol based on markers
|
|
@@ -817,16 +641,15 @@
|
|
|
817
641
|
display_style: {
|
|
818
642
|
...(has_line
|
|
819
643
|
? {
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
644
|
+
line_color: series_color,
|
|
645
|
+
line_dash: srs.line_style?.line_dash,
|
|
646
|
+
}
|
|
823
647
|
: {}),
|
|
824
648
|
...(has_points
|
|
825
649
|
? {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
}
|
|
650
|
+
symbol_type: first_point_style?.symbol_type ?? DEFAULTS.scatter.symbol_type,
|
|
651
|
+
symbol_color: point_color,
|
|
652
|
+
}
|
|
830
653
|
: {}),
|
|
831
654
|
},
|
|
832
655
|
}
|
|
@@ -842,10 +665,13 @@
|
|
|
842
665
|
symbol_color: series_color,
|
|
843
666
|
},
|
|
844
667
|
}
|
|
845
|
-
})
|
|
668
|
+
}),
|
|
846
669
|
)
|
|
847
670
|
|
|
848
|
-
const legend_vis = create_legend_visibility(
|
|
671
|
+
const legend_vis = create_legend_visibility(
|
|
672
|
+
() => series,
|
|
673
|
+
(next) => (series = next),
|
|
674
|
+
)
|
|
849
675
|
|
|
850
676
|
// Collect bar and line positions for legend placement
|
|
851
677
|
let bar_points_for_placement = $derived.by(() => {
|
|
@@ -862,12 +688,11 @@
|
|
|
862
688
|
return srs.x
|
|
863
689
|
.map((x_val, bar_idx) => {
|
|
864
690
|
const y_val = srs.y[bar_idx]
|
|
865
|
-
const base = !is_line && mode === `stacked`
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
: [x_scale_pl(base + y_val), scales.y(x_val)]
|
|
691
|
+
const base = !is_line && mode === `stacked` ? (series_offsets[bar_idx] ?? 0) : 0
|
|
692
|
+
const [bar_x, bar_y] =
|
|
693
|
+
orientation === `vertical`
|
|
694
|
+
? [x_scale_pl(x_val), y_scale(base + y_val)]
|
|
695
|
+
: [x_scale_pl(base + y_val), scales.y(x_val)]
|
|
871
696
|
return { x: bar_x, y: bar_y }
|
|
872
697
|
})
|
|
873
698
|
.filter(({ x, y }) => isFinite(x) && isFinite(y))
|
|
@@ -876,12 +701,6 @@
|
|
|
876
701
|
|
|
877
702
|
// Legend placement stability state (legend_element declared above for the auto-place block)
|
|
878
703
|
let hovered_legend_series_idx = $state<number | null>(null)
|
|
879
|
-
const legend_hover = create_hover_lock()
|
|
880
|
-
const dim_tracker = create_dimension_tracker()
|
|
881
|
-
let has_initial_legend_placement = $state(false)
|
|
882
|
-
|
|
883
|
-
// Clear pending hover lock timeout on unmount
|
|
884
|
-
$effect(() => () => legend_hover.cleanup())
|
|
885
704
|
|
|
886
705
|
// Calculate best legend placement using continuous grid sampling
|
|
887
706
|
let legend_placement = $derived.by(() => {
|
|
@@ -900,37 +719,13 @@
|
|
|
900
719
|
return result
|
|
901
720
|
})
|
|
902
721
|
|
|
903
|
-
// Tweened legend coordinates
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
{
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
// Update legend position with stability checks
|
|
911
|
-
$effect(() => {
|
|
912
|
-
if (!width || !height || !legend_placement) return
|
|
913
|
-
|
|
914
|
-
// Track dimensions for resize detection
|
|
915
|
-
const dims_changed = dim_tracker.has_changed(width, height)
|
|
916
|
-
if (dims_changed) dim_tracker.update(width, height)
|
|
917
|
-
|
|
918
|
-
const is_responsive = legend?.responsive ?? false
|
|
919
|
-
// Only update if: resize occurred, OR (not hover-locked AND (responsive OR not yet initially placed))
|
|
920
|
-
const should_update = dims_changed || (!legend_hover.is_locked.current &&
|
|
921
|
-
(is_responsive || !has_initial_legend_placement))
|
|
922
|
-
|
|
923
|
-
if (should_update) {
|
|
924
|
-
tweened_legend_coords.set(
|
|
925
|
-
{ x: legend_placement.x, y: legend_placement.y },
|
|
926
|
-
// Skip animation on initial placement to avoid jump from (0, 0)
|
|
927
|
-
has_initial_legend_placement ? undefined : { duration: 0 },
|
|
928
|
-
)
|
|
929
|
-
// Only lock position after we have actual measured size
|
|
930
|
-
if (legend_element) {
|
|
931
|
-
has_initial_legend_placement = true
|
|
932
|
-
}
|
|
933
|
-
}
|
|
722
|
+
// Tweened legend coordinates with shared placement stability gating
|
|
723
|
+
const legend_tween = create_placed_tween({
|
|
724
|
+
placement: () => legend_placement,
|
|
725
|
+
dims: () => ({ width, height }),
|
|
726
|
+
responsive: () => legend?.responsive ?? false,
|
|
727
|
+
element: () => legend_element,
|
|
728
|
+
tween: () => legend?.tween,
|
|
934
729
|
})
|
|
935
730
|
|
|
936
731
|
// Tooltip state
|
|
@@ -944,9 +739,7 @@
|
|
|
944
739
|
const srs = internal_series[series_idx]
|
|
945
740
|
const [x, y] = [srs.x[bar_idx], srs.y[bar_idx]]
|
|
946
741
|
const [orient_x, orient_y] = orientation === `horizontal` ? [y, x] : [x, y]
|
|
947
|
-
const metadata = Array.isArray(srs.metadata)
|
|
948
|
-
? srs.metadata[bar_idx]
|
|
949
|
-
: srs.metadata
|
|
742
|
+
const metadata = Array.isArray(srs.metadata) ? srs.metadata[bar_idx] : srs.metadata
|
|
950
743
|
const label = srs.labels?.[bar_idx] ?? null
|
|
951
744
|
const active_y_axis = srs.y_axis ?? `y1`
|
|
952
745
|
const active_x_axis = srs.x_axis ?? `x1`
|
|
@@ -1001,7 +794,7 @@
|
|
|
1001
794
|
const line_point_fill = (pt: LineSeriesPoint, series_color: string): string =>
|
|
1002
795
|
pt.color_value != null
|
|
1003
796
|
? color_scale_fn(pt.color_value)
|
|
1004
|
-
: pt.point_style?.fill ?? series_color
|
|
797
|
+
: (pt.point_style?.fill ?? series_color)
|
|
1005
798
|
|
|
1006
799
|
const handle_bar_hover =
|
|
1007
800
|
(series_idx: number, bar_idx: number, color: string) => (event: MouseEvent) => {
|
|
@@ -1023,31 +816,31 @@
|
|
|
1023
816
|
})
|
|
1024
817
|
|
|
1025
818
|
// State accessors for shared axis change handler
|
|
819
|
+
// Secondary axes read the merged $derived (x2_axis/y2_axis) but write the raw $bindable props
|
|
820
|
+
// (x2_axis_prop/y2_axis_prop) so library defaults aren't pushed into the parent's bound state
|
|
1026
821
|
const axis_state: AxisChangeState<BarSeries<Metadata>> = {
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
822
|
+
axes: {
|
|
823
|
+
x: { get: () => x_axis, set: (config) => (x_axis = { ...x_axis, ...config }) },
|
|
824
|
+
x2: {
|
|
825
|
+
get: () => x2_axis,
|
|
826
|
+
set: (config) => (x2_axis_prop = { ...x2_axis_prop, ...config }),
|
|
827
|
+
},
|
|
828
|
+
y: { get: () => y_axis, set: (config) => (y_axis = { ...y_axis, ...config }) },
|
|
829
|
+
y2: {
|
|
830
|
+
get: () => y2_axis,
|
|
831
|
+
set: (config) => (y2_axis_prop = { ...y2_axis_prop, ...config }),
|
|
832
|
+
},
|
|
1032
833
|
},
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
if (axis === `x`) x_axis = { ...x_axis, ...config }
|
|
1036
|
-
else if (axis === `x2`) x2_axis_prop = { ...x2_axis_prop, ...config }
|
|
1037
|
-
else if (axis === `y`) y_axis = { ...y_axis, ...config }
|
|
1038
|
-
else y2_axis_prop = { ...y2_axis_prop, ...config }
|
|
1039
|
-
},
|
|
1040
|
-
get_series: () => series,
|
|
1041
|
-
set_series: (new_series) => (series = new_series),
|
|
1042
|
-
get_loading: () => axis_loading,
|
|
1043
|
-
set_loading: (axis) => (axis_loading = axis),
|
|
834
|
+
series: { get: () => series, set: (next) => (series = next) },
|
|
835
|
+
loading: { get: () => axis_loading, set: (axis) => (axis_loading = axis) },
|
|
1044
836
|
}
|
|
1045
837
|
|
|
1046
838
|
// Shared handler + one-shot auto-load bound to this component's state
|
|
1047
|
-
const { handle_axis_change, try_auto_load } = create_axis_loader(
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
839
|
+
const { handle_axis_change, try_auto_load } = create_axis_loader(axis_state, () => ({
|
|
840
|
+
data_loader,
|
|
841
|
+
on_axis_change,
|
|
842
|
+
on_error,
|
|
843
|
+
}))
|
|
1051
844
|
$effect(try_auto_load)
|
|
1052
845
|
</script>
|
|
1053
846
|
|
|
@@ -1085,11 +878,9 @@
|
|
|
1085
878
|
evt.preventDefault()
|
|
1086
879
|
fullscreen = false
|
|
1087
880
|
}
|
|
1088
|
-
|
|
1089
|
-
}}
|
|
1090
|
-
onkeyup={(evt) => {
|
|
1091
|
-
if (evt.key === `Shift`) shift_held = false
|
|
881
|
+
pan_zoom.on_window_key_down(evt)
|
|
1092
882
|
}}
|
|
883
|
+
onkeyup={pan_zoom.on_window_key_up}
|
|
1093
884
|
/>
|
|
1094
885
|
|
|
1095
886
|
<div
|
|
@@ -1097,7 +888,7 @@
|
|
|
1097
888
|
bind:clientWidth={width}
|
|
1098
889
|
bind:clientHeight={height}
|
|
1099
890
|
{...rest}
|
|
1100
|
-
class=
|
|
891
|
+
class={[`bar-plot`, rest.class]}
|
|
1101
892
|
class:fullscreen
|
|
1102
893
|
>
|
|
1103
894
|
{#if width && height}
|
|
@@ -1113,41 +904,27 @@
|
|
|
1113
904
|
bind:this={svg_element}
|
|
1114
905
|
role="application"
|
|
1115
906
|
aria-label={rest[`aria-label`] ??
|
|
1116
|
-
|
|
907
|
+
([x_axis.label, y_axis.label].filter(Boolean).join(` vs `) || `Bar chart`)}
|
|
1117
908
|
tabindex="0"
|
|
1118
|
-
onfocusin={() => (
|
|
1119
|
-
onfocusout={() => (
|
|
1120
|
-
onmousedown={
|
|
1121
|
-
ondblclick={
|
|
1122
|
-
|
|
1123
|
-
ranges.current.x = [...ranges.initial.x] as [number, number]
|
|
1124
|
-
ranges.current.x2 = [...ranges.initial.x2] as [number, number]
|
|
1125
|
-
ranges.current.y = [...ranges.initial.y] as [number, number]
|
|
1126
|
-
ranges.current.y2 = [...ranges.initial.y2] as [number, number]
|
|
1127
|
-
// Also reset axis props so future data changes recalculate auto ranges
|
|
1128
|
-
x_axis = { ...x_axis, range: [null, null] }
|
|
1129
|
-
x2_axis_prop = { ...x2_axis_prop, range: [null, null] }
|
|
1130
|
-
y_axis = { ...y_axis, range: [null, null] }
|
|
1131
|
-
y2_axis_prop = { ...y2_axis_prop, range: [null, null] }
|
|
1132
|
-
}}
|
|
909
|
+
onfocusin={() => pan_zoom.set_focused(true)}
|
|
910
|
+
onfocusout={() => pan_zoom.set_focused(false)}
|
|
911
|
+
onmousedown={pan_zoom.on_mouse_down}
|
|
912
|
+
ondblclick={pan_zoom.reset_view}
|
|
913
|
+
onkeydown={pan_zoom.on_key_down}
|
|
1133
914
|
onmouseleave={() => {
|
|
1134
915
|
hovered = false
|
|
1135
916
|
hover_info = null
|
|
1136
917
|
change(null)
|
|
1137
918
|
on_bar_hover?.(null)
|
|
1138
919
|
}}
|
|
1139
|
-
onwheel={
|
|
1140
|
-
ontouchstart={
|
|
1141
|
-
ontouchmove={
|
|
1142
|
-
ontouchend={
|
|
1143
|
-
ontouchcancel={
|
|
1144
|
-
style:cursor={
|
|
1145
|
-
? `grabbing`
|
|
1146
|
-
: shift_held && pan?.enabled !== false
|
|
1147
|
-
? `grab`
|
|
1148
|
-
: `crosshair`}
|
|
920
|
+
onwheel={pan_zoom.on_wheel}
|
|
921
|
+
ontouchstart={pan_zoom.on_touch_start}
|
|
922
|
+
ontouchmove={pan_zoom.on_touch_move}
|
|
923
|
+
ontouchend={pan_zoom.on_touch_end}
|
|
924
|
+
ontouchcancel={pan_zoom.on_touch_end}
|
|
925
|
+
style:cursor={pan_zoom.cursor}
|
|
1149
926
|
>
|
|
1150
|
-
<ZoomRect start={
|
|
927
|
+
<ZoomRect start={pan_zoom.drag_start} current={pan_zoom.drag_current} />
|
|
1151
928
|
|
|
1152
929
|
<!-- User content (custom overlays, reference lines, etc.) -->
|
|
1153
930
|
{@render user_content?.({
|
|
@@ -1171,38 +948,38 @@
|
|
|
1171
948
|
<!-- X-axis -->
|
|
1172
949
|
<PlotAxis
|
|
1173
950
|
side="x"
|
|
1174
|
-
ticks={ticks.x
|
|
951
|
+
ticks={ticks.x}
|
|
1175
952
|
place={scales.x}
|
|
1176
953
|
axis={x_axis}
|
|
1177
|
-
domain={ranges.current.x
|
|
954
|
+
domain={ranges.current.x}
|
|
1178
955
|
{pad}
|
|
1179
956
|
{width}
|
|
1180
957
|
{height}
|
|
1181
958
|
show_grid={display.x_grid}
|
|
1182
959
|
tick_label={(tick) =>
|
|
1183
|
-
|
|
960
|
+
get_tick_label(tick, cat_axis === `x` ? effective_cat_ticks : x_axis.ticks)}
|
|
1184
961
|
label_x={pad.l + chart_width / 2 + (x_axis.label_shift?.x ?? 0)}
|
|
1185
|
-
label_y={height - pad.b
|
|
962
|
+
label_y={height - pad.b + AXIS_TITLE_OFFSET + (x_axis.label_shift?.y ?? 0)}
|
|
1186
963
|
axis_loading={axis_loading === `x`}
|
|
1187
964
|
on_axis_change={(key) => handle_axis_change(`x`, key)}
|
|
1188
965
|
/>
|
|
1189
966
|
|
|
1190
967
|
<!-- X2-axis (Top) -->
|
|
1191
968
|
<!-- Note: x2 axis is only supported for vertical orientation -->
|
|
1192
|
-
{#if
|
|
969
|
+
{#if show_x2}
|
|
1193
970
|
<PlotAxis
|
|
1194
971
|
side="x2"
|
|
1195
|
-
ticks={ticks.x2
|
|
972
|
+
ticks={ticks.x2}
|
|
1196
973
|
place={scales.x2}
|
|
1197
974
|
axis={x2_axis}
|
|
1198
|
-
domain={ranges.current.x2
|
|
975
|
+
domain={ranges.current.x2}
|
|
1199
976
|
{pad}
|
|
1200
977
|
{width}
|
|
1201
978
|
{height}
|
|
1202
979
|
show_grid={display.x2_grid}
|
|
1203
980
|
tick_label={(tick) => get_tick_label(tick, x2_axis.ticks)}
|
|
1204
981
|
label_x={pad.l + chart_width / 2 + (x2_axis.label_shift?.x ?? 0)}
|
|
1205
|
-
label_y={Math.max(12, pad.t - (x2_axis.label_shift?.y ??
|
|
982
|
+
label_y={Math.max(12, pad.t - (x2_axis.label_shift?.y ?? AXIS_TITLE_OFFSET))}
|
|
1206
983
|
axis_loading={axis_loading === `x2`}
|
|
1207
984
|
on_axis_change={(key) => handle_axis_change(`x2`, key)}
|
|
1208
985
|
/>
|
|
@@ -1211,19 +988,20 @@
|
|
|
1211
988
|
<!-- Y-axis -->
|
|
1212
989
|
<PlotAxis
|
|
1213
990
|
side="y"
|
|
1214
|
-
ticks={ticks.y
|
|
991
|
+
ticks={ticks.y}
|
|
1215
992
|
place={scales.y}
|
|
1216
993
|
axis={y_axis}
|
|
1217
|
-
domain={ranges.current.y
|
|
994
|
+
domain={ranges.current.y}
|
|
1218
995
|
{pad}
|
|
1219
996
|
{width}
|
|
1220
997
|
{height}
|
|
1221
998
|
show_grid={display.y_grid}
|
|
1222
999
|
tick_label={(tick) =>
|
|
1223
|
-
|
|
1000
|
+
get_tick_label(tick, cat_axis === `y` ? effective_cat_ticks : y_axis.ticks)}
|
|
1224
1001
|
label_x={Math.max(
|
|
1225
1002
|
12,
|
|
1226
|
-
pad.l -
|
|
1003
|
+
pad.l -
|
|
1004
|
+
(y_axis.tick?.label?.inside ? 0 : tick_label_widths.y_max) -
|
|
1227
1005
|
LABEL_GAP_DEFAULT,
|
|
1228
1006
|
) + (y_axis.label_shift?.x ?? 0)}
|
|
1229
1007
|
label_y={pad.t + chart_height / 2 + (y_axis.label_shift?.y ?? 0)}
|
|
@@ -1233,13 +1011,13 @@
|
|
|
1233
1011
|
|
|
1234
1012
|
<!-- Y2-axis (Right) -->
|
|
1235
1013
|
<!-- Note: y2 axis is only supported for vertical orientation. Implementing x2 for horizontal mode requires additional complexity. -->
|
|
1236
|
-
{#if
|
|
1014
|
+
{#if show_y2}
|
|
1237
1015
|
<PlotAxis
|
|
1238
1016
|
side="y2"
|
|
1239
|
-
ticks={ticks.y2
|
|
1017
|
+
ticks={ticks.y2}
|
|
1240
1018
|
place={scales.y2}
|
|
1241
1019
|
axis={y2_axis}
|
|
1242
|
-
domain={ranges.current.y2
|
|
1020
|
+
domain={ranges.current.y2}
|
|
1243
1021
|
{pad}
|
|
1244
1022
|
{width}
|
|
1245
1023
|
{height}
|
|
@@ -1280,8 +1058,8 @@
|
|
|
1280
1058
|
y2_scale_type={y2_axis.scale_type}
|
|
1281
1059
|
x_is_time={x_axis.format?.startsWith(`%`) ?? false}
|
|
1282
1060
|
x2_is_time={x2_axis.format?.startsWith(`%`) ?? false}
|
|
1283
|
-
has_x2={
|
|
1284
|
-
has_y2={
|
|
1061
|
+
has_x2={show_x2}
|
|
1062
|
+
has_y2={show_y2}
|
|
1285
1063
|
{width}
|
|
1286
1064
|
{height}
|
|
1287
1065
|
{pad}
|
|
@@ -1299,7 +1077,7 @@
|
|
|
1299
1077
|
class={is_line ? `line-series` : `bar-series`}
|
|
1300
1078
|
data-series-idx={series_idx}
|
|
1301
1079
|
opacity={hovered_legend_series_idx !== null &&
|
|
1302
|
-
|
|
1080
|
+
hovered_legend_series_idx !== series_idx
|
|
1303
1081
|
? 0.25
|
|
1304
1082
|
: 1}
|
|
1305
1083
|
>
|
|
@@ -1313,21 +1091,22 @@
|
|
|
1313
1091
|
{@const use_x2 = srs.x_axis === `x2`}
|
|
1314
1092
|
{@const x_scale = use_x2 ? scales.x2 : scales.x}
|
|
1315
1093
|
{@const series_markers = srs.markers ?? DEFAULT_MARKERS}
|
|
1316
|
-
{@const show_line =
|
|
1317
|
-
|
|
1318
|
-
{@const show_points =
|
|
1319
|
-
|
|
1094
|
+
{@const show_line =
|
|
1095
|
+
series_markers === `line` || series_markers === `line+points`}
|
|
1096
|
+
{@const show_points =
|
|
1097
|
+
series_markers === `points` || series_markers === `line+points`}
|
|
1320
1098
|
{@const points = compute_line_points({
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
{@const polyline_str =
|
|
1329
|
-
|
|
1330
|
-
|
|
1099
|
+
series: srs,
|
|
1100
|
+
series_idx,
|
|
1101
|
+
orientation,
|
|
1102
|
+
x_scale,
|
|
1103
|
+
y_scale,
|
|
1104
|
+
cat_y_scale: scales.y,
|
|
1105
|
+
})}
|
|
1106
|
+
{@const polyline_str =
|
|
1107
|
+
show_line && points.length > 1
|
|
1108
|
+
? points.map((pt) => `${pt.x},${pt.y}`).join(` `)
|
|
1109
|
+
: ``}
|
|
1331
1110
|
{#if polyline_str}
|
|
1332
1111
|
<polyline
|
|
1333
1112
|
points={polyline_str}
|
|
@@ -1376,44 +1155,41 @@
|
|
|
1376
1155
|
{#if show_points}
|
|
1377
1156
|
{@const clickable = on_bar_click || on_point_click}
|
|
1378
1157
|
{@const get_pt = (evt: Event) => {
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
}}
|
|
1158
|
+
const attr =
|
|
1159
|
+
evt.target instanceof Element
|
|
1160
|
+
? evt.target.closest(`[data-bar-idx]`)?.getAttribute(`data-bar-idx`)
|
|
1161
|
+
: null
|
|
1162
|
+
return points.find((pt) => pt.idx === parseInt(attr ?? ``, 10))
|
|
1163
|
+
}}
|
|
1386
1164
|
{@const set_hover = (
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
)
|
|
1403
|
-
}}
|
|
1165
|
+
pt: LineSeriesPoint | null,
|
|
1166
|
+
evt: MouseEvent | FocusEvent,
|
|
1167
|
+
) => {
|
|
1168
|
+
if (pt) {
|
|
1169
|
+
hovered = true
|
|
1170
|
+
const fill = line_point_fill(pt, color)
|
|
1171
|
+
hover_info = get_bar_data(series_idx, pt.idx, fill)
|
|
1172
|
+
change(hover_info)
|
|
1173
|
+
} else {
|
|
1174
|
+
change(null)
|
|
1175
|
+
hover_info = null
|
|
1176
|
+
}
|
|
1177
|
+
on_bar_hover?.(pt ? { ...hover_info!, event: evt } : null)
|
|
1178
|
+
on_point_hover?.(pt ? { ...hover_info!, event: evt, point: pt } : null)
|
|
1179
|
+
}}
|
|
1404
1180
|
{@const do_click = (
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1181
|
+
pt: LineSeriesPoint,
|
|
1182
|
+
evt: MouseEvent | KeyboardEvent,
|
|
1183
|
+
) => {
|
|
1184
|
+
const fill = line_point_fill(pt, color)
|
|
1185
|
+
const bar_data = get_bar_data(series_idx, pt.idx, fill)
|
|
1186
|
+
on_bar_click?.({ ...bar_data, event: evt })
|
|
1187
|
+
on_point_click?.({ ...bar_data, event: evt, point: pt })
|
|
1188
|
+
}}
|
|
1413
1189
|
{@const leaving = (evt: MouseEvent | FocusEvent) =>
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1190
|
+
(evt.relatedTarget instanceof Element
|
|
1191
|
+
? evt.relatedTarget.closest(`.line-points`)
|
|
1192
|
+
: null) !== evt.currentTarget}
|
|
1417
1193
|
<!-- svelte-ignore a11y_no_noninteractive_element_interactions, a11y_mouse_events_have_key_events -->
|
|
1418
1194
|
<g
|
|
1419
1195
|
class="line-points"
|
|
@@ -1447,11 +1223,13 @@
|
|
|
1447
1223
|
{#each points as pt (pt.idx)}
|
|
1448
1224
|
{@const sty = pt.point_style}
|
|
1449
1225
|
{@const fl = line_point_fill(pt, color)}
|
|
1450
|
-
{@const rad =
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1226
|
+
{@const rad =
|
|
1227
|
+
pt.size_value != null
|
|
1228
|
+
? size_scale_fn(pt.size_value)
|
|
1229
|
+
: (sty?.radius ?? 4)}
|
|
1230
|
+
{@const hov =
|
|
1231
|
+
hover_info?.series_idx === series_idx &&
|
|
1232
|
+
hover_info?.bar_idx === pt.idx}
|
|
1455
1233
|
<ScatterPoint
|
|
1456
1234
|
x={pt.x}
|
|
1457
1235
|
y={pt.y}
|
|
@@ -1482,31 +1260,30 @@
|
|
|
1482
1260
|
<!-- Render as bars -->
|
|
1483
1261
|
{#each srs.x as x_val, bar_idx (bar_idx)}
|
|
1484
1262
|
{@const y_val = srs.y[bar_idx]}
|
|
1485
|
-
{@const base =
|
|
1486
|
-
|
|
1487
|
-
: 0}
|
|
1263
|
+
{@const base =
|
|
1264
|
+
mode === `stacked` ? (stacked_offsets[series_idx]?.[bar_idx] ?? 0) : 0}
|
|
1488
1265
|
{@const color = srs.color ?? bar_state.color ?? `steelblue`}
|
|
1489
1266
|
{@const bar_width_val = Array.isArray(srs.bar_width)
|
|
1490
|
-
|
|
1491
|
-
|
|
1267
|
+
? (srs.bar_width[bar_idx] ?? 0.5)
|
|
1268
|
+
: (srs.bar_width ?? 0.5)}
|
|
1492
1269
|
{@const is_vertical = orientation === `vertical`}
|
|
1493
1270
|
{@const x_scale_bar = srs.x_axis === `x2` ? scales.x2 : scales.x}
|
|
1494
1271
|
{@const [cat_scale, val_scale] = is_vertical
|
|
1495
|
-
|
|
1496
|
-
|
|
1272
|
+
? [x_scale_bar, srs.y_axis === `y2` ? scales.y2 : scales.y]
|
|
1273
|
+
: [scales.y, x_scale_bar]}
|
|
1497
1274
|
{@const { c0, c1, v0, v1, rect_x, rect_y, rect_w, rect_h } =
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1275
|
+
compute_bar_rect({
|
|
1276
|
+
cat_val: x_val,
|
|
1277
|
+
val: y_val,
|
|
1278
|
+
base,
|
|
1279
|
+
bar_width_val,
|
|
1280
|
+
series_idx,
|
|
1281
|
+
mode,
|
|
1282
|
+
orientation,
|
|
1283
|
+
group_info,
|
|
1284
|
+
cat_scale,
|
|
1285
|
+
val_scale,
|
|
1286
|
+
})}
|
|
1510
1287
|
{#if (is_vertical ? rect_h : rect_w) > 0}
|
|
1511
1288
|
<path
|
|
1512
1289
|
d={bar_path(
|
|
@@ -1533,10 +1310,10 @@
|
|
|
1533
1310
|
on_bar_hover?.(null)
|
|
1534
1311
|
}}
|
|
1535
1312
|
onclick={(evt) =>
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1313
|
+
on_bar_click?.({
|
|
1314
|
+
...get_bar_data(series_idx, bar_idx, color),
|
|
1315
|
+
event: evt,
|
|
1316
|
+
})}
|
|
1540
1317
|
onkeydown={(evt) => {
|
|
1541
1318
|
if (evt.key === `Enter` || evt.key === ` `) {
|
|
1542
1319
|
evt.preventDefault()
|
|
@@ -1568,20 +1345,44 @@
|
|
|
1568
1345
|
|
|
1569
1346
|
{@render ref_lines_layer(ref_lines_by_z.below_points)}
|
|
1570
1347
|
{@render ref_lines_layer(ref_lines_by_z.above_all)}
|
|
1348
|
+
|
|
1349
|
+
<!-- Marginal distribution strips -->
|
|
1350
|
+
<PlotMarginals
|
|
1351
|
+
marginals={resolved_marginals}
|
|
1352
|
+
series={marginal_series}
|
|
1353
|
+
{width}
|
|
1354
|
+
{height}
|
|
1355
|
+
{pad}
|
|
1356
|
+
has_axis={marginal_has_axis}
|
|
1357
|
+
axes={{
|
|
1358
|
+
x1: marginal_axis(
|
|
1359
|
+
scales.x,
|
|
1360
|
+
ranges.current.x,
|
|
1361
|
+
x_axis,
|
|
1362
|
+
cat_axis === `x` ? (pos) => category_list[Math.round(pos)] : undefined,
|
|
1363
|
+
),
|
|
1364
|
+
x2: marginal_axis(scales.x2, ranges.current.x2, x2_axis),
|
|
1365
|
+
y1: marginal_axis(
|
|
1366
|
+
scales.y,
|
|
1367
|
+
ranges.current.y,
|
|
1368
|
+
y_axis,
|
|
1369
|
+
cat_axis === `y` ? (pos) => category_list[Math.round(pos)] : undefined,
|
|
1370
|
+
),
|
|
1371
|
+
y2: marginal_axis(scales.y2, ranges.current.y2, y2_axis),
|
|
1372
|
+
}}
|
|
1373
|
+
id={clip_path_id}
|
|
1374
|
+
/>
|
|
1571
1375
|
</svg>
|
|
1572
1376
|
|
|
1573
1377
|
<!-- Legend -->
|
|
1574
1378
|
{#if legend && (show_legend !== undefined ? show_legend : series.length > 1)}
|
|
1575
|
-
{@const
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
: legend_placement
|
|
1583
|
-
? tweened_legend_coords.current.y
|
|
1584
|
-
: pad.t + 10}
|
|
1379
|
+
{@const legend_pos = placed_coords(
|
|
1380
|
+
legend_auto_outside,
|
|
1381
|
+
{ x: legend_outside_x, y: legend_outside_y },
|
|
1382
|
+
legend_placement,
|
|
1383
|
+
legend_tween.coords.current,
|
|
1384
|
+
{ x: pad.l + 10, y: pad.t + 10 },
|
|
1385
|
+
)}
|
|
1585
1386
|
<PlotLegend
|
|
1586
1387
|
bind:root_element={legend_element}
|
|
1587
1388
|
{...legend}
|
|
@@ -1589,16 +1390,15 @@
|
|
|
1589
1390
|
on_toggle={legend?.on_toggle ?? legend_vis.on_toggle}
|
|
1590
1391
|
on_group_toggle={legend?.on_group_toggle ?? legend_vis.on_group_toggle}
|
|
1591
1392
|
on_double_click={legend?.on_double_click ?? legend_vis.on_double_click}
|
|
1592
|
-
on_hover_change={
|
|
1393
|
+
on_hover_change={legend_tween.set_locked}
|
|
1593
1394
|
on_item_hover={(item) =>
|
|
1594
|
-
(hovered_legend_series_idx =
|
|
1595
|
-
? item.series_idx
|
|
1596
|
-
: null)}
|
|
1395
|
+
(hovered_legend_series_idx =
|
|
1396
|
+
item != null && item.series_idx >= 0 ? item.series_idx : null)}
|
|
1597
1397
|
active_series_idx={hover_info?.series_idx ?? hovered_legend_series_idx}
|
|
1598
1398
|
style={`
|
|
1599
1399
|
position: absolute;
|
|
1600
|
-
left: ${
|
|
1601
|
-
top: ${
|
|
1400
|
+
left: ${legend_pos.x}px;
|
|
1401
|
+
top: ${legend_pos.y}px;
|
|
1602
1402
|
pointer-events: auto;
|
|
1603
1403
|
${legend?.style || ``}
|
|
1604
1404
|
`}
|
|
@@ -1607,11 +1407,11 @@
|
|
|
1607
1407
|
|
|
1608
1408
|
{#if hover_info && hovered}
|
|
1609
1409
|
{@const cx = (hover_info.active_x_axis === `x2` ? scales.x2 : scales.x)(
|
|
1610
|
-
|
|
1611
|
-
|
|
1410
|
+
hover_info.orient_x,
|
|
1411
|
+
)}
|
|
1612
1412
|
{@const cy = (hover_info.active_y_axis === `y2` ? scales.y2 : scales.y)(
|
|
1613
|
-
|
|
1614
|
-
|
|
1413
|
+
hover_info.orient_y,
|
|
1414
|
+
)}
|
|
1615
1415
|
<PlotTooltip
|
|
1616
1416
|
x={cx}
|
|
1617
1417
|
y={cy}
|
|
@@ -1628,16 +1428,16 @@
|
|
|
1628
1428
|
<div><strong>{series_label}</strong></div>
|
|
1629
1429
|
{/if}
|
|
1630
1430
|
<div>
|
|
1631
|
-
{@html sanitize_html(hover_info.x_axis.label || `x`)}: {
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1431
|
+
{@html sanitize_html(hover_info.x_axis.label || `x`)}: {(cat_axis === `x`
|
|
1432
|
+
? hover_info.category_label
|
|
1433
|
+
: undefined) ??
|
|
1434
|
+
format_value_or_num(hover_info.orient_x, hover_info.x_axis.format)}
|
|
1635
1435
|
</div>
|
|
1636
1436
|
<div>
|
|
1637
|
-
{@html sanitize_html(hover_info.y_axis.label || `y`)}: {
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1437
|
+
{@html sanitize_html(hover_info.y_axis.label || `y`)}: {(cat_axis === `y`
|
|
1438
|
+
? hover_info.category_label
|
|
1439
|
+
: undefined) ??
|
|
1440
|
+
format_value_or_num(hover_info.orient_y, hover_info.y_axis.format)}
|
|
1641
1441
|
</div>
|
|
1642
1442
|
{/if}
|
|
1643
1443
|
</PlotTooltip>
|
|
@@ -1661,12 +1461,12 @@
|
|
|
1661
1461
|
bind:y_axis
|
|
1662
1462
|
bind:y2_axis={y2_axis_prop}
|
|
1663
1463
|
bind:display
|
|
1664
|
-
auto_x_range={auto_ranges.x
|
|
1665
|
-
auto_x2_range={auto_ranges.x2
|
|
1666
|
-
auto_y_range={auto_ranges.y
|
|
1667
|
-
auto_y2_range={auto_ranges.y2
|
|
1668
|
-
has_x2_points={
|
|
1669
|
-
has_y2_points={
|
|
1464
|
+
auto_x_range={auto_ranges.x}
|
|
1465
|
+
auto_x2_range={auto_ranges.x2}
|
|
1466
|
+
auto_y_range={auto_ranges.y}
|
|
1467
|
+
auto_y2_range={auto_ranges.y2}
|
|
1468
|
+
has_x2_points={show_x2}
|
|
1469
|
+
has_y2_points={show_y2}
|
|
1670
1470
|
children={controls_extra}
|
|
1671
1471
|
/>
|
|
1672
1472
|
{/if}
|
|
@@ -1726,7 +1526,9 @@
|
|
|
1726
1526
|
.bar-plot :global(.pane-toggle),
|
|
1727
1527
|
.bar-plot .header-controls {
|
|
1728
1528
|
opacity: 0;
|
|
1729
|
-
transition:
|
|
1529
|
+
transition:
|
|
1530
|
+
opacity 0.2s,
|
|
1531
|
+
background-color 0.2s;
|
|
1730
1532
|
}
|
|
1731
1533
|
.bar-plot:hover :global(.pane-toggle),
|
|
1732
1534
|
.bar-plot:hover .header-controls,
|