matterviz 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EmptyState.svelte +10 -4
- package/dist/FilePicker.svelte +48 -60
- package/dist/Icon.svelte +7 -4
- package/dist/MillerIndexInput.svelte +2 -2
- package/dist/api/optimade.js +10 -7
- package/dist/app.css +68 -0
- package/dist/brillouin/BrillouinZone.svelte +90 -91
- 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 +46 -68
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/brillouin/compute.js +10 -16
- package/dist/brillouin/geometry.js +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte +48 -50
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +61 -169
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +559 -755
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/async-compute.svelte.js +13 -14
- package/dist/chempot-diagram/color.d.ts +21 -1
- package/dist/chempot-diagram/color.js +70 -1
- package/dist/chempot-diagram/compute.d.ts +7 -0
- package/dist/chempot-diagram/compute.js +85 -26
- package/dist/chempot-diagram/controls-state.svelte.js +1 -1
- package/dist/chempot-diagram/export.js +1 -6
- package/dist/chempot-diagram/temperature.js +9 -10
- package/dist/colors/index.d.ts +0 -4
- package/dist/colors/index.js +19 -20
- package/dist/composition/BarChart.svelte +30 -26
- package/dist/composition/BubbleChart.svelte +17 -17
- package/dist/composition/Composition.svelte +10 -19
- package/dist/composition/Formula.svelte +20 -27
- package/dist/composition/FormulaFilter.svelte +115 -184
- package/dist/composition/PieChart.svelte +55 -41
- package/dist/composition/format.js +7 -9
- 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 +61 -115
- package/dist/constants.d.ts +0 -1
- package/dist/constants.js +17 -26
- 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 -94
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +127 -186
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +131 -180
- 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 +18 -22
- 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/gas-thermodynamics.js +21 -53
- package/dist/convex-hull/helpers.d.ts +8 -10
- package/dist/convex-hull/helpers.js +37 -43
- package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
- package/dist/convex-hull/thermodynamics.js +37 -44
- package/dist/coordination/CoordinationBarPlot.svelte +49 -53
- 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 -9
- 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 +44 -67
- package/dist/element/Nucleus.svelte +4 -2
- package/dist/element/data.d.ts +3 -2
- package/dist/element/data.js +5 -1
- package/dist/element/helpers.d.ts +4 -0
- package/dist/element/helpers.js +18 -0
- package/dist/element/index.d.ts +2 -5
- package/dist/element/index.js +4 -19
- 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 +35 -44
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +7 -13
- package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +64 -136
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
- package/dist/fermi-surface/compute.js +25 -58
- package/dist/fermi-surface/parse.js +54 -88
- package/dist/file-viewer/JsonBrowser.svelte +1043 -0
- package/dist/file-viewer/JsonBrowser.svelte.d.ts +9 -0
- package/dist/file-viewer/PlotPanel.svelte +350 -0
- package/dist/file-viewer/PlotPanel.svelte.d.ts +9 -0
- package/dist/file-viewer/TrajectoryWithDos.svelte +30 -0
- package/dist/file-viewer/TrajectoryWithDos.svelte.d.ts +10 -0
- package/dist/file-viewer/detect.d.ts +11 -0
- package/dist/file-viewer/detect.js +381 -0
- package/dist/file-viewer/eligibility.d.ts +4 -0
- package/dist/file-viewer/eligibility.js +53 -0
- package/dist/file-viewer/host-protocol.d.ts +50 -0
- package/dist/file-viewer/host-transfer.d.ts +25 -0
- package/dist/file-viewer/host-transfer.js +42 -0
- package/dist/file-viewer/index.d.ts +5 -0
- package/dist/file-viewer/index.js +5 -0
- package/dist/file-viewer/main.d.ts +44 -0
- package/dist/file-viewer/main.js +535 -0
- package/dist/file-viewer/parse.d.ts +9 -0
- package/dist/file-viewer/parse.js +170 -0
- package/dist/file-viewer/plot-utils.d.ts +24 -0
- package/dist/file-viewer/plot-utils.js +191 -0
- package/dist/file-viewer/types.d.ts +4 -0
- package/dist/file-viewer/types.js +5 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +153 -219
- 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/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/io/ExportPane.svelte +11 -7
- package/dist/io/decompress.d.ts +4 -1
- package/dist/io/decompress.js +24 -36
- package/dist/io/export.d.ts +11 -4
- package/dist/io/export.js +75 -19
- package/dist/io/fetch.d.ts +0 -3
- package/dist/io/fetch.js +0 -11
- package/dist/io/file-drop.js +60 -35
- 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.d.ts +2 -0
- package/dist/io/url-drop.js +40 -40
- package/dist/isosurface/Isosurface.svelte +700 -215
- package/dist/isosurface/Isosurface.svelte.d.ts +7 -1
- package/dist/isosurface/IsosurfaceControls.svelte +590 -116
- package/dist/isosurface/IsosurfaceControls.svelte.d.ts +1 -1
- package/dist/isosurface/VolumeSlice.svelte +224 -0
- package/dist/isosurface/VolumeSlice.svelte.d.ts +28 -0
- package/dist/isosurface/coloring.d.ts +20 -0
- package/dist/isosurface/coloring.js +118 -0
- package/dist/isosurface/geometry-worker-types.d.ts +38 -0
- package/dist/isosurface/geometry.worker.d.ts +1 -0
- package/dist/isosurface/geometry.worker.js +59 -0
- package/dist/isosurface/grid.d.ts +10 -0
- package/dist/isosurface/grid.js +31 -0
- package/dist/isosurface/index.d.ts +4 -0
- package/dist/isosurface/index.js +4 -0
- 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/isosurface/profile.d.ts +12 -0
- package/dist/isosurface/profile.js +19 -0
- package/dist/isosurface/sampling.d.ts +34 -0
- package/dist/isosurface/sampling.js +408 -0
- package/dist/isosurface/slice-rendering.d.ts +13 -0
- package/dist/isosurface/slice-rendering.js +79 -0
- package/dist/isosurface/slice.d.ts +22 -2
- package/dist/isosurface/slice.js +200 -116
- package/dist/isosurface/types.d.ts +24 -1
- package/dist/isosurface/types.js +120 -8
- package/dist/json-path.d.ts +4 -0
- package/dist/json-path.js +89 -0
- package/dist/labels.d.ts +6 -2
- package/dist/labels.js +44 -14
- package/dist/layout/FullscreenButton.svelte +2 -1
- package/dist/layout/FullscreenToggle.svelte +10 -4
- package/dist/layout/InfoCard.svelte +8 -21
- 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 +57 -62
- package/dist/layout/SettingsSection.svelte.d.ts +6 -7
- package/dist/layout/SubpageGrid.svelte +3 -1
- package/dist/layout/ViewerChrome.svelte +16 -11
- 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 +22 -59
- package/dist/layout/json-tree/JsonTree.svelte +101 -172
- package/dist/layout/json-tree/JsonValue.svelte +9 -32
- package/dist/layout/json-tree/utils.d.ts +0 -3
- package/dist/layout/json-tree/utils.js +50 -188
- package/dist/marching-cubes.d.ts +8 -1
- package/dist/marching-cubes.js +115 -48
- package/dist/math.d.ts +5 -2
- package/dist/math.js +48 -38
- package/dist/overlays/ContextMenu.svelte +19 -34
- package/dist/overlays/CopyButton.svelte +11 -5
- package/dist/overlays/DragControlTab.svelte +6 -1
- package/dist/overlays/DraggablePane.svelte +110 -74
- package/dist/overlays/DraggablePane.svelte.d.ts +2 -1
- package/dist/overlays/GlassChip.svelte +32 -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 +37 -115
- package/dist/periodic-table/TableInset.svelte +9 -4
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +68 -105
- 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 +4 -9
- 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 +28 -27
- package/dist/phase-diagram/utils.js +2 -3
- package/dist/plot/bar/BarPlot.svelte +461 -426
- 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 +46 -77
- package/dist/plot/bar/data.d.ts +5 -4
- package/dist/plot/bar/data.js +2 -1
- package/dist/plot/box/BoxPlot.svelte +322 -226
- 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.d.ts +1 -1
- package/dist/plot/core/auto-place.js +2 -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 +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.d.ts +1 -2
- package/dist/plot/core/data-transform.js +9 -15
- 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 +15 -6
- package/dist/plot/core/layout.js +57 -38
- 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 +2 -4
- package/dist/plot/core/pan-zoom.svelte.js +34 -17
- package/dist/plot/core/placed-tween.svelte.d.ts +3 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -21
- 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/svg.js +0 -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 +29 -324
- package/dist/plot/core/types.js +23 -20
- package/dist/plot/core/utils/hierarchy-chart.d.ts +52 -0
- package/dist/plot/core/utils/hierarchy-chart.js +191 -0
- package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
- package/dist/plot/core/utils/hierarchy-labels.js +100 -0
- package/dist/plot/core/utils/label-placement.js +2 -2
- package/dist/plot/histogram/Histogram.svelte +314 -340
- 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/sankey/sankey.js +13 -9
- package/dist/plot/scatter/BinnedScatterPlot.svelte +311 -141
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
- package/dist/plot/scatter/ElementScatter.svelte +4 -1
- package/dist/plot/scatter/ScatterPlot.svelte +517 -410
- 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/adaptive-density.d.ts +1 -1
- package/dist/plot/scatter/adaptive-density.js +36 -20
- 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 +269 -347
- 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 +1022 -0
- package/dist/plot/treemap/Treemap.svelte.d.ts +90 -0
- package/dist/plot/treemap/index.d.ts +4 -0
- package/dist/plot/treemap/index.js +4 -0
- package/dist/plot/treemap/labels.d.ts +38 -0
- package/dist/plot/treemap/labels.js +80 -0
- package/dist/plot/treemap/treemap.d.ts +28 -0
- package/dist/plot/treemap/treemap.js +102 -0
- package/dist/rdf/RdfPlot.svelte +37 -59
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/calc-rdf.js +63 -52
- package/dist/rdf/index.d.ts +0 -1
- package/dist/sanitize.js +85 -27
- package/dist/scene/SceneCamera.svelte +1 -1
- package/dist/scene/SceneCamera.svelte.d.ts +1 -1
- package/dist/scene/bind-renderer.svelte.js +14 -6
- package/dist/scene/index.d.ts +1 -2
- package/dist/scene/index.js +1 -1
- package/dist/scene/{props.js → props.svelte.js} +15 -1
- package/dist/settings.d.ts +19 -9
- package/dist/settings.js +229 -525
- package/dist/spectral/Bands.svelte +207 -221
- package/dist/spectral/BandsAndDos.svelte +11 -9
- package/dist/spectral/BrillouinBandsDos.svelte +19 -42
- package/dist/spectral/Dos.svelte +92 -93
- package/dist/spectral/helpers.d.ts +3 -3
- package/dist/spectral/helpers.js +65 -140
- 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 +120 -85
- package/dist/structure/AtomLegend.svelte.d.ts +2 -3
- package/dist/structure/Bond.svelte +31 -23
- package/dist/structure/CanvasTooltip.svelte +15 -3
- package/dist/structure/CellSelect.svelte +45 -35
- 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 +636 -504
- package/dist/structure/Structure.svelte.d.ts +4 -2
- package/dist/structure/StructureCarousel.svelte +637 -0
- package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
- package/dist/structure/StructureControls.svelte +165 -425
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureExportPane.svelte +17 -21
- package/dist/structure/StructureInfoPane.svelte +128 -133
- package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
- package/dist/structure/StructureScene.svelte +535 -578
- package/dist/structure/StructureScene.svelte.d.ts +6 -2
- package/dist/structure/StructureViewport.svelte +451 -0
- package/dist/structure/StructureViewport.svelte.d.ts +65 -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 +105 -38
- package/dist/structure/bond-order-perception.js +3 -8
- package/dist/structure/bonding.d.ts +9 -3
- package/dist/structure/bonding.js +95 -46
- 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 +89 -105
- package/dist/structure/format-detect.d.ts +1 -0
- package/dist/structure/format-detect.js +20 -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 +15 -10
- 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 +272 -313
- package/dist/structure/partial-occupancy.js +10 -5
- package/dist/structure/pbc.js +85 -107
- package/dist/structure/polyhedra.d.ts +0 -1
- package/dist/structure/polyhedra.js +7 -21
- package/dist/structure/prop-groups.d.ts +85 -0
- package/dist/structure/prop-groups.js +18 -0
- 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 +55 -71
- package/dist/symmetry/WyckoffTable.svelte +10 -28
- package/dist/symmetry/cell-transform.js +6 -14
- package/dist/symmetry/index.d.ts +1 -0
- package/dist/symmetry/index.js +13 -10
- package/dist/symmetry/spacegroups.js +3 -2
- package/dist/table/HeatmapTable.svelte +1142 -447
- package/dist/table/HeatmapTable.svelte.d.ts +12 -2
- package/dist/table/ToggleMenu.svelte +168 -53
- package/dist/table/ToggleMenu.svelte.d.ts +1 -1
- 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/embedded.d.ts +18 -0
- package/dist/theme/embedded.js +206 -0
- package/dist/theme/index.d.ts +5 -5
- package/dist/theme/index.js +5 -12
- package/dist/theme/themes.mjs +44 -66
- package/dist/tooltip/KCoords.svelte +4 -1
- package/dist/tooltip/TooltipContent.svelte +3 -6
- package/dist/tooltip/TooltipContent.svelte.d.ts +1 -1
- package/dist/tooltip/index.d.ts +8 -1
- package/dist/trajectory/Trajectory.svelte +613 -386
- package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
- package/dist/trajectory/TrajectoryError.svelte +12 -74
- package/dist/trajectory/TrajectoryExportPane.svelte +14 -32
- package/dist/trajectory/TrajectoryInfoPane.svelte +127 -164
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +2 -1
- package/dist/trajectory/extract.js +61 -49
- package/dist/trajectory/format-detect.d.ts +2 -0
- package/dist/trajectory/format-detect.js +17 -13
- package/dist/trajectory/frame-reader.d.ts +2 -0
- package/dist/trajectory/frame-reader.js +35 -32
- package/dist/trajectory/helpers.d.ts +2 -0
- package/dist/trajectory/helpers.js +34 -56
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +5 -8
- package/dist/trajectory/parse/ase.js +1 -1
- 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 +6 -6
- package/dist/trajectory/parse/index.js +25 -33
- 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 +4 -0
- package/dist/trajectory/parse/vaspout-h5.js +281 -0
- package/dist/trajectory/parse/xyz.js +59 -9
- package/dist/trajectory/plotting.d.ts +8 -9
- package/dist/trajectory/plotting.js +113 -64
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +7 -0
- package/dist/xrd/XrdPlot.svelte +79 -118
- package/dist/xrd/broadening.js +2 -1
- package/dist/xrd/calc-xrd.js +24 -62
- package/dist/xrd/parse.d.ts +0 -1
- package/dist/xrd/parse.js +69 -95
- package/package.json +94 -34
- package/readme.md +6 -5
- package/dist/api/mp.d.ts +0 -6
- package/dist/api/mp.js +0 -22
- package/dist/plot/sunburst/SunburstControls.svelte +0 -200
- package/dist/scene/types.d.ts +0 -26
- package/dist/tooltip/types.d.ts +0 -8
- package/dist/trajectory/constants.d.ts +0 -6
- package/dist/trajectory/constants.js +0 -11
- /package/dist/{scene/types.js → file-viewer/host-protocol.js} +0 -0
- /package/dist/{tooltip/types.js → isosurface/geometry-worker-types.js} +0 -0
|
@@ -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 {
|
|
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'
|
|
@@ -33,11 +33,19 @@
|
|
|
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 {
|
|
40
|
+
import type { MarginalSeriesInput, MarginalsProp } from '../core/marginals'
|
|
41
|
+
import {
|
|
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'
|
|
41
49
|
import { create_placed_tween } from '../core/placed-tween.svelte'
|
|
42
50
|
import { create_pan_zoom } from '../core/pan-zoom.svelte'
|
|
43
51
|
import { create_legend_visibility } from '../core/utils/series-visibility'
|
|
@@ -49,13 +57,13 @@
|
|
|
49
57
|
import type { IndexedRefLine } from '../core/reference-line'
|
|
50
58
|
import { group_ref_lines_by_z, index_ref_lines } from '../core/reference-line'
|
|
51
59
|
import {
|
|
60
|
+
create_axis_scales,
|
|
52
61
|
create_color_scale,
|
|
53
|
-
create_scale,
|
|
54
62
|
create_size_scale,
|
|
55
63
|
generate_ticks,
|
|
56
64
|
get_tick_label,
|
|
57
65
|
} from '../core/scales'
|
|
58
|
-
import { DEFAULT_MARKERS } from '../core/types'
|
|
66
|
+
import { DEFAULT_MARKERS, SCALE_DEFAULTS } from '../core/types'
|
|
59
67
|
import { DEFAULTS } from '../../settings'
|
|
60
68
|
import { extent } from 'd3-array'
|
|
61
69
|
import type { Snippet } from 'svelte'
|
|
@@ -71,7 +79,9 @@
|
|
|
71
79
|
placed_coords,
|
|
72
80
|
} from '../core/auto-place'
|
|
73
81
|
import {
|
|
82
|
+
AXIS_TITLE_OFFSET,
|
|
74
83
|
calc_auto_padding,
|
|
84
|
+
DEFAULT_PLOT_PADDING,
|
|
75
85
|
filter_padding,
|
|
76
86
|
LABEL_GAP_DEFAULT,
|
|
77
87
|
y2_axis_label_x,
|
|
@@ -108,8 +118,8 @@
|
|
|
108
118
|
y_axis = $bindable({}),
|
|
109
119
|
y2_axis: y2_axis_prop = $bindable({}),
|
|
110
120
|
display = $bindable(DEFAULTS.bar.display),
|
|
111
|
-
range_padding = 0
|
|
112
|
-
padding =
|
|
121
|
+
range_padding = 0,
|
|
122
|
+
padding = DEFAULT_PLOT_PADDING,
|
|
113
123
|
legend = {},
|
|
114
124
|
show_legend,
|
|
115
125
|
bar = {},
|
|
@@ -121,12 +131,8 @@
|
|
|
121
131
|
on_bar_click,
|
|
122
132
|
on_bar_hover,
|
|
123
133
|
// Line marker props (matching ScatterPlot)
|
|
124
|
-
color_scale =
|
|
125
|
-
|
|
126
|
-
scheme: `interpolateViridis`,
|
|
127
|
-
value_range: undefined,
|
|
128
|
-
},
|
|
129
|
-
size_scale = { type: `linear`, radius_range: [2, 10], value_range: undefined },
|
|
134
|
+
color_scale = SCALE_DEFAULTS.color,
|
|
135
|
+
size_scale = SCALE_DEFAULTS.size,
|
|
130
136
|
point_tween,
|
|
131
137
|
on_point_click,
|
|
132
138
|
on_point_hover,
|
|
@@ -146,61 +152,65 @@
|
|
|
146
152
|
on_axis_change,
|
|
147
153
|
on_error,
|
|
148
154
|
pan = {},
|
|
155
|
+
marginals = false,
|
|
149
156
|
...rest
|
|
150
|
-
}: HTMLAttributes<HTMLDivElement> &
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
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()
|
|
204
214
|
|
|
205
215
|
// Initialize bar, line, y2_axis with defaults - using $derived for reactivity
|
|
206
216
|
let bar_state = $derived({ ...DEFAULTS.bar.bar, ...bar })
|
|
@@ -220,7 +230,7 @@
|
|
|
220
230
|
format: ``,
|
|
221
231
|
scale_type: `linear`,
|
|
222
232
|
ticks: 5,
|
|
223
|
-
label_shift: { x: 0, y:
|
|
233
|
+
label_shift: { x: 0, y: AXIS_TITLE_OFFSET },
|
|
224
234
|
tick: { label: { shift: { x: 0, y: 0 } } },
|
|
225
235
|
range: [null, null],
|
|
226
236
|
...x2_axis_prop,
|
|
@@ -238,13 +248,12 @@
|
|
|
238
248
|
let axis_loading = $state<`x` | `x2` | `y` | `y2` | null>(null)
|
|
239
249
|
|
|
240
250
|
// Compute ref_lines with index and group by z-index (using shared utilities)
|
|
241
|
-
let
|
|
242
|
-
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)))
|
|
243
252
|
|
|
244
253
|
// === Categorical Normalization (string x values -> integer indices, see ./data) ===
|
|
245
|
-
let
|
|
246
|
-
|
|
247
|
-
|
|
254
|
+
let { category_list, internal_series } = $derived(
|
|
255
|
+
normalize_categorical(series, x_axis.categories),
|
|
256
|
+
)
|
|
248
257
|
|
|
249
258
|
let category_indices = $derived(
|
|
250
259
|
category_list.length > 0 ? category_list.map((_, idx) => idx) : null,
|
|
@@ -257,47 +266,44 @@
|
|
|
257
266
|
const axis_px = (orientation === `horizontal` ? height : width) || 0
|
|
258
267
|
const max_ticks = Math.max(1, Math.floor(axis_px / 28)) // ~28px per category label
|
|
259
268
|
const step = Math.ceil(category_indices.length / max_ticks)
|
|
260
|
-
return step <= 1
|
|
261
|
-
? category_indices
|
|
262
|
-
: category_indices.filter((_, idx) => idx % step === 0)
|
|
269
|
+
return step <= 1 ? category_indices : category_indices.filter((_, idx) => idx % step === 0)
|
|
263
270
|
})
|
|
264
271
|
|
|
265
272
|
// Compute auto ranges from visible series
|
|
266
|
-
let visible_series = $derived(
|
|
267
|
-
internal_series.filter((srs) => srs?.visible ?? true),
|
|
268
|
-
)
|
|
273
|
+
let visible_series = $derived(internal_series.filter((srs) => srs?.visible ?? true))
|
|
269
274
|
|
|
270
275
|
// Separate series by y-axis
|
|
271
|
-
let y1_series = $derived(
|
|
272
|
-
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
|
|
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
|
+
}),
|
|
276
306
|
)
|
|
277
|
-
let x2_series = $derived(
|
|
278
|
-
visible_series.filter((srs) => srs.x_axis === `x2`),
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
let auto_ranges = $derived(compute_bar_auto_ranges({
|
|
282
|
-
visible_series,
|
|
283
|
-
y1_series,
|
|
284
|
-
y2_series,
|
|
285
|
-
x2_series,
|
|
286
|
-
mode,
|
|
287
|
-
orientation,
|
|
288
|
-
range_padding,
|
|
289
|
-
category_count: category_list.length,
|
|
290
|
-
x_range: x_axis.range ?? [null, null],
|
|
291
|
-
x_scale_type: x_axis.scale_type ?? `linear`,
|
|
292
|
-
x_is_time: x_axis.format?.startsWith(`%`) || false,
|
|
293
|
-
x2_range: x2_axis.range ?? [null, null],
|
|
294
|
-
x2_scale_type: x2_axis.scale_type ?? `linear`,
|
|
295
|
-
x2_is_time: x2_axis.format?.startsWith(`%`) || false,
|
|
296
|
-
y_range: y_axis.range ?? [null, null],
|
|
297
|
-
y_scale_type: y_axis.scale_type ?? `linear`,
|
|
298
|
-
y2_range: y2_axis.range ?? [null, null],
|
|
299
|
-
y2_scale_type: y2_axis.scale_type ?? `linear`,
|
|
300
|
-
}))
|
|
301
307
|
|
|
302
308
|
// Initialize and current ranges
|
|
303
309
|
let ranges = $state<{
|
|
@@ -308,10 +314,14 @@
|
|
|
308
314
|
current: { x: [0, 1], x2: [0, 1], y: [0, 1], y2: [0, 1] },
|
|
309
315
|
})
|
|
310
316
|
|
|
311
|
-
$effect(() => {
|
|
317
|
+
$effect(() => {
|
|
318
|
+
// handle x_axis.range / x2_axis.range / y_axis.range / y2_axis.range changes
|
|
312
319
|
// resolve_axis_ranges returns null for transient non-finite bounds (skip: writing
|
|
313
320
|
// NaN breaks scales and, since NaN !== NaN, loops the effect)
|
|
314
|
-
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
|
+
)
|
|
315
325
|
if (!next) return
|
|
316
326
|
// Only update if the initial (data-driven) ranges changed, not when user pans.
|
|
317
327
|
// untrack the read of `ranges` so the assignment below can't re-trigger this effect
|
|
@@ -323,42 +333,33 @@
|
|
|
323
333
|
})
|
|
324
334
|
|
|
325
335
|
// Layout: dynamic padding based on tick label widths
|
|
326
|
-
const default_padding = { t: 20, b: 60, l: 60, r: 20 }
|
|
327
336
|
// base_pad reserves space for tick labels/axis titles; pad (below) adds decoration reservations
|
|
328
|
-
let base_pad = $derived(filter_padding(padding,
|
|
337
|
+
let base_pad = $derived(filter_padding(padding, DEFAULT_PLOT_PADDING))
|
|
329
338
|
|
|
330
339
|
// Update padding when format or ticks change
|
|
331
340
|
$effect(() => {
|
|
332
|
-
const new_pad =
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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)
|
|
341
351
|
// Expand right padding if y2 ticks are shown (only for vertical orientation)
|
|
342
|
-
if (
|
|
343
|
-
width && height && y2_series.length > 0 && ticks.y2.length > 0 &&
|
|
344
|
-
orientation === `vertical`
|
|
345
|
-
) {
|
|
352
|
+
if (width && height && show_y2 && ticks.y2.length > 0) {
|
|
346
353
|
// Need space for: tick shift + tick width + gap (30px) + label space (20px if present)
|
|
347
354
|
// When ticks are inside, they don't contribute to padding
|
|
348
355
|
const inside = y2_axis.tick?.label?.inside ?? false
|
|
349
356
|
const tick_shift = inside ? 0 : (y2_axis.tick?.label?.shift?.x ?? 0) + 8
|
|
350
357
|
const tick_width_contribution = inside ? 0 : tick_label_widths.y2_max
|
|
351
358
|
const label_space = y2_axis.label ? 20 : 0
|
|
352
|
-
new_pad.r = Math.max(
|
|
353
|
-
new_pad.r,
|
|
354
|
-
tick_shift + tick_width_contribution + 30 + label_space,
|
|
355
|
-
)
|
|
359
|
+
new_pad.r = Math.max(new_pad.r, tick_shift + tick_width_contribution + 30 + label_space)
|
|
356
360
|
}
|
|
357
361
|
// Expand top padding if x2 ticks are shown (only for vertical orientation)
|
|
358
|
-
if (
|
|
359
|
-
width && height && x2_series.length > 0 && ticks.x2.length > 0 &&
|
|
360
|
-
orientation === `vertical`
|
|
361
|
-
) {
|
|
362
|
+
if (width && height && show_x2 && ticks.x2.length > 0) {
|
|
362
363
|
const inside = x2_axis.tick?.label?.inside ?? false
|
|
363
364
|
const tick_shift = inside ? 0 : Math.abs(x2_axis.tick?.label?.shift?.y ?? 0) + 5
|
|
364
365
|
const tick_height = inside ? 0 : 16
|
|
@@ -368,14 +369,22 @@
|
|
|
368
369
|
|
|
369
370
|
// Only update if padding actually changed (prevents infinite loop)
|
|
370
371
|
if (
|
|
371
|
-
base_pad.t !== new_pad.t ||
|
|
372
|
-
base_pad.
|
|
373
|
-
|
|
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
|
|
374
378
|
})
|
|
375
379
|
|
|
376
380
|
let legend_element = $state<HTMLDivElement | undefined>()
|
|
377
|
-
|
|
381
|
+
let legend_size_revision = $state(0)
|
|
382
|
+
const legend_footprint = $derived.by(() => {
|
|
383
|
+
void legend_size_revision
|
|
384
|
+
return measured_footprint(legend_element, { width: 120, height: 60 })
|
|
385
|
+
})
|
|
378
386
|
const legend_has_explicit_pos = $derived(has_explicit_position(legend?.style))
|
|
387
|
+
const should_show_legend = $derived(show_legend ?? series.length > 1)
|
|
379
388
|
|
|
380
389
|
// Obstacle field in normalized [0,1] plot coords (y=0 at top). Each bar is modeled as a segment
|
|
381
390
|
// from baseline to its tip so the legend can't hide inside a tall bar. Built from internal_series
|
|
@@ -403,8 +412,18 @@
|
|
|
403
412
|
const value = base + srs.y[bar_idx]
|
|
404
413
|
// vertical: category on x, value rises on y (inverted). horizontal: category on y, value on x
|
|
405
414
|
const seg = vertical
|
|
406
|
-
? clip_bar(
|
|
407
|
-
|
|
415
|
+
? clip_bar(
|
|
416
|
+
true,
|
|
417
|
+
(x_val - ax0) / x_span,
|
|
418
|
+
1 - (value - vy0) / y_span,
|
|
419
|
+
1 - (base - vy0) / y_span,
|
|
420
|
+
)
|
|
421
|
+
: clip_bar(
|
|
422
|
+
false,
|
|
423
|
+
1 - (x_val - cy0) / cy_span,
|
|
424
|
+
(value - ax0) / x_span,
|
|
425
|
+
(base - ax0) / x_span,
|
|
426
|
+
)
|
|
408
427
|
if (seg) bars.push(seg)
|
|
409
428
|
})
|
|
410
429
|
})
|
|
@@ -412,46 +431,62 @@
|
|
|
412
431
|
})
|
|
413
432
|
|
|
414
433
|
// Move the legend to the bottom margin when no interior spot avoids the bars
|
|
415
|
-
const decor = $derived
|
|
434
|
+
const decor = $derived(
|
|
416
435
|
place_decorations({
|
|
417
436
|
base_pad,
|
|
418
437
|
width,
|
|
419
438
|
height,
|
|
420
439
|
obstacles_norm,
|
|
421
440
|
// gate on legend_element (the render signal) not legend_data, whose entries can read pad
|
|
422
|
-
legend:
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
441
|
+
legend:
|
|
442
|
+
legend != null &&
|
|
443
|
+
should_show_legend &&
|
|
444
|
+
legend_element != null &&
|
|
445
|
+
!legend_has_explicit_pos
|
|
446
|
+
? { footprint: legend_footprint, clearance: legend?.axis_clearance }
|
|
447
|
+
: null,
|
|
448
|
+
}),
|
|
449
|
+
)
|
|
450
|
+
// Resolve marginals: a cumulative/Pareto CDF over the CATEGORY axis weighted by bar height.
|
|
451
|
+
// Categories sit on x (vertical) or y (horizontal), so the default side and the value array
|
|
452
|
+
// flip with orientation. The value axis carries no marginal (a bar's height isn't a sample).
|
|
453
|
+
const marginal_is_vertical = $derived(orientation === `vertical`)
|
|
454
|
+
const resolved_marginals = $derived(
|
|
455
|
+
normalize_marginals(
|
|
456
|
+
marginals,
|
|
457
|
+
marginal_is_vertical ? { top: { type: `cdf` } } : { right: { type: `cdf` } },
|
|
458
|
+
),
|
|
428
459
|
)
|
|
429
|
-
const pad = $derived(decor.pad)
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
460
|
+
const pad = $derived(add_sides(decor.pad, reserve_marginal_pad(resolved_marginals)))
|
|
461
|
+
const marginal_series = $derived<MarginalSeriesInput[]>(
|
|
462
|
+
internal_series.map((srs) => ({
|
|
463
|
+
x: marginal_is_vertical ? (srs?.x ?? []) : undefined,
|
|
464
|
+
y: marginal_is_vertical ? undefined : (srs?.x ?? []),
|
|
465
|
+
// magnitude weights so negative bars still yield a monotonic cumulative (CDF) marginal
|
|
466
|
+
weight: srs?.y?.map((value) => Math.abs(value)) ?? [],
|
|
467
|
+
color:
|
|
468
|
+
srs?.color ??
|
|
469
|
+
(srs?.render_mode === `line` ? line_state.color : bar_state.color) ??
|
|
470
|
+
`steelblue`,
|
|
471
|
+
label: srs?.label,
|
|
472
|
+
visible: srs?.visible ?? true,
|
|
473
|
+
x_axis: srs?.x_axis,
|
|
474
|
+
y_axis: srs?.y_axis,
|
|
475
|
+
})),
|
|
476
|
+
)
|
|
477
|
+
const marginal_has_axis = $derived(marginal_axis_presence(show_x2, show_y2))
|
|
433
478
|
const chart_width = $derived(Math.max(1, width - pad.l - pad.r))
|
|
434
479
|
const chart_height = $derived(Math.max(1, height - pad.t - pad.b))
|
|
435
480
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
]),
|
|
446
|
-
y: create_scale(y_axis.scale_type ?? `linear`, ranges.current.y, [
|
|
447
|
-
height - pad.b,
|
|
448
|
-
pad.t,
|
|
449
|
-
]),
|
|
450
|
-
y2: create_scale(y2_axis.scale_type ?? `linear`, ranges.current.y2, [
|
|
451
|
-
height - pad.b,
|
|
452
|
-
pad.t,
|
|
453
|
-
]),
|
|
454
|
-
})
|
|
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
|
+
)
|
|
455
490
|
|
|
456
491
|
// Compute plot center for point tweening origin
|
|
457
492
|
let plot_center_x = $derived(pad.l + (width - pad.r - pad.l) / 2)
|
|
@@ -462,9 +497,7 @@
|
|
|
462
497
|
visible_series
|
|
463
498
|
.filter((srs: BarSeries<Metadata>) => srs.render_mode === `line`)
|
|
464
499
|
.flatMap((srs: BarSeries<Metadata>) =>
|
|
465
|
-
(srs.color_values ?? []).filter(
|
|
466
|
-
(val): val is number => typeof val === `number`,
|
|
467
|
-
)
|
|
500
|
+
(srs.color_values ?? []).filter((val): val is number => typeof val === `number`),
|
|
468
501
|
),
|
|
469
502
|
)
|
|
470
503
|
|
|
@@ -480,9 +513,7 @@
|
|
|
480
513
|
visible_series
|
|
481
514
|
.filter((srs: BarSeries<Metadata>) => srs.render_mode === `line`)
|
|
482
515
|
.flatMap((srs: BarSeries<Metadata>) =>
|
|
483
|
-
[...(srs.size_values ?? [])].filter(
|
|
484
|
-
(val): val is number => typeof val === `number`,
|
|
485
|
-
)
|
|
516
|
+
[...(srs.size_values ?? [])].filter((val): val is number => typeof val === `number`),
|
|
486
517
|
),
|
|
487
518
|
)
|
|
488
519
|
|
|
@@ -500,57 +531,37 @@
|
|
|
500
531
|
// Only respect user ticks when they're a Record (custom label mapping),
|
|
501
532
|
// not a number (tick count) or array (tick positions)
|
|
502
533
|
const user_ticks = cat_axis === `x` ? x_axis.ticks : y_axis.ticks
|
|
503
|
-
if (
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
) return user_ticks
|
|
507
|
-
return Object.fromEntries(
|
|
508
|
-
category_list.map((cat, idx) => [idx, cat]),
|
|
509
|
-
) 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]))
|
|
510
537
|
})
|
|
511
538
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
:
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
{
|
|
539
|
-
default_count: 6,
|
|
540
|
-
},
|
|
541
|
-
)
|
|
542
|
-
: [],
|
|
543
|
-
x2: width && height && x2_series.length > 0 && orientation === `vertical`
|
|
544
|
-
? generate_ticks(
|
|
545
|
-
ranges.current.x2,
|
|
546
|
-
x2_axis.scale_type ?? `linear`,
|
|
547
|
-
x2_axis.ticks,
|
|
548
|
-
scales.x2,
|
|
549
|
-
{
|
|
550
|
-
default_count: 8,
|
|
551
|
-
},
|
|
552
|
-
)
|
|
553
|
-
: [],
|
|
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
|
+
}
|
|
554
565
|
})
|
|
555
566
|
|
|
556
567
|
// Cache measured tick-label widths so expensive canvas text measurement
|
|
@@ -558,14 +569,19 @@
|
|
|
558
569
|
let tick_label_widths = $derived({
|
|
559
570
|
y_max: measure_max_tick_width(ticks.y, y_axis.format ?? ``),
|
|
560
571
|
y2_max: measure_max_tick_width(ticks.y2, y2_axis.format ?? ``),
|
|
561
|
-
x2_max: measure_max_tick_width(ticks.x2, x2_axis.format ?? ``),
|
|
562
572
|
})
|
|
563
573
|
|
|
564
574
|
// Shared pan/zoom/touch/drag-rect interaction controller
|
|
565
575
|
const pan_zoom = create_pan_zoom({
|
|
566
576
|
ranges: () => ranges.current,
|
|
567
|
-
scale_type: (axis) =>
|
|
568
|
-
|
|
577
|
+
scale_type: (axis) =>
|
|
578
|
+
({ x: x_axis, x2: x2_axis, y: y_axis, y2: y2_axis })[axis].scale_type,
|
|
579
|
+
plot_bounds: () => ({
|
|
580
|
+
x: pad.l,
|
|
581
|
+
y: pad.t,
|
|
582
|
+
width: chart_width,
|
|
583
|
+
height: chart_height,
|
|
584
|
+
}),
|
|
569
585
|
pan: () => pan,
|
|
570
586
|
set_range: (axis, range) => (ranges.current[axis] = range),
|
|
571
587
|
svg: () => svg_element,
|
|
@@ -574,13 +590,13 @@
|
|
|
574
590
|
const next_x = invert_rect_range(scales.x, start.x, current.x)
|
|
575
591
|
if (!next_x) return
|
|
576
592
|
x_axis = { ...x_axis, range: next_x }
|
|
577
|
-
// gate x2/y2 on
|
|
578
|
-
//
|
|
579
|
-
const next_x2 =
|
|
593
|
+
// gate x2/y2 on whether they actually render (show_x2/show_y2 also require vertical);
|
|
594
|
+
// otherwise their [0, 1] sentinel scales would store a phantom range in the bindable prop
|
|
595
|
+
const next_x2 = show_x2 ? invert_rect_range(scales.x2, start.x, current.x) : null
|
|
580
596
|
if (next_x2) x2_axis_prop = { ...x2_axis_prop, range: next_x2 }
|
|
581
597
|
const next_y = invert_rect_range(scales.y, start.y, current.y)
|
|
582
598
|
if (next_y) y_axis = { ...y_axis, range: next_y }
|
|
583
|
-
const next_y2 =
|
|
599
|
+
const next_y2 = show_y2 ? invert_rect_range(scales.y2, start.y, current.y) : null
|
|
584
600
|
if (next_y2) y2_axis_prop = { ...y2_axis_prop, range: next_y2 }
|
|
585
601
|
},
|
|
586
602
|
on_reset: () => {
|
|
@@ -606,8 +622,7 @@
|
|
|
606
622
|
const is_line = srs.render_mode === `line`
|
|
607
623
|
const series_markers = srs.markers ?? DEFAULT_MARKERS
|
|
608
624
|
const has_line = series_markers === `line` || series_markers === `line+points`
|
|
609
|
-
const has_points = series_markers === `points` ||
|
|
610
|
-
series_markers === `line+points`
|
|
625
|
+
const has_points = series_markers === `points` || series_markers === `line+points`
|
|
611
626
|
const series_color = srs.color ?? (is_line ? line_state.color : bar_state.color)
|
|
612
627
|
|
|
613
628
|
// Get point style for symbol color (handle array or single object)
|
|
@@ -615,9 +630,10 @@
|
|
|
615
630
|
? srs.point_style[0]
|
|
616
631
|
: srs.point_style
|
|
617
632
|
const first_color_value = srs.color_values?.[0]
|
|
618
|
-
const point_color =
|
|
619
|
-
|
|
620
|
-
|
|
633
|
+
const point_color =
|
|
634
|
+
first_color_value != null
|
|
635
|
+
? color_scale_fn(first_color_value)
|
|
636
|
+
: (first_point_style?.fill ?? series_color)
|
|
621
637
|
|
|
622
638
|
if (is_line) {
|
|
623
639
|
// Line series: show line and/or symbol based on markers
|
|
@@ -629,16 +645,15 @@
|
|
|
629
645
|
display_style: {
|
|
630
646
|
...(has_line
|
|
631
647
|
? {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
648
|
+
line_color: series_color,
|
|
649
|
+
line_dash: srs.line_style?.line_dash,
|
|
650
|
+
}
|
|
635
651
|
: {}),
|
|
636
652
|
...(has_points
|
|
637
653
|
? {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
}
|
|
654
|
+
symbol_type: first_point_style?.symbol_type ?? DEFAULTS.scatter.symbol_type,
|
|
655
|
+
symbol_color: point_color,
|
|
656
|
+
}
|
|
642
657
|
: {}),
|
|
643
658
|
},
|
|
644
659
|
}
|
|
@@ -654,10 +669,13 @@
|
|
|
654
669
|
symbol_color: series_color,
|
|
655
670
|
},
|
|
656
671
|
}
|
|
657
|
-
})
|
|
672
|
+
}),
|
|
658
673
|
)
|
|
659
674
|
|
|
660
|
-
const legend_vis = create_legend_visibility(
|
|
675
|
+
const legend_vis = create_legend_visibility(
|
|
676
|
+
() => series,
|
|
677
|
+
(next) => (series = next),
|
|
678
|
+
)
|
|
661
679
|
|
|
662
680
|
// Collect bar and line positions for legend placement
|
|
663
681
|
let bar_points_for_placement = $derived.by(() => {
|
|
@@ -674,12 +692,11 @@
|
|
|
674
692
|
return srs.x
|
|
675
693
|
.map((x_val, bar_idx) => {
|
|
676
694
|
const y_val = srs.y[bar_idx]
|
|
677
|
-
const base = !is_line && mode === `stacked`
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
: [x_scale_pl(base + y_val), scales.y(x_val)]
|
|
695
|
+
const base = !is_line && mode === `stacked` ? (series_offsets[bar_idx] ?? 0) : 0
|
|
696
|
+
const [bar_x, bar_y] =
|
|
697
|
+
orientation === `vertical`
|
|
698
|
+
? [x_scale_pl(x_val), y_scale(base + y_val)]
|
|
699
|
+
: [x_scale_pl(base + y_val), scales.y(x_val)]
|
|
683
700
|
return { x: bar_x, y: bar_y }
|
|
684
701
|
})
|
|
685
702
|
.filter(({ x, y }) => isFinite(x) && isFinite(y))
|
|
@@ -690,11 +707,10 @@
|
|
|
690
707
|
let hovered_legend_series_idx = $state<number | null>(null)
|
|
691
708
|
|
|
692
709
|
// Calculate best legend placement using continuous grid sampling
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
if (!should_show || !width || !height) return null
|
|
710
|
+
const get_legend_placement = () => {
|
|
711
|
+
if (!should_show_legend || !width || !height) return null
|
|
696
712
|
|
|
697
|
-
|
|
713
|
+
return compute_element_placement({
|
|
698
714
|
plot_bounds: { x: pad.l, y: pad.t, width: chart_width, height: chart_height },
|
|
699
715
|
element: legend_element,
|
|
700
716
|
element_size: { width: 120, height: 60 }, // fallback before first render
|
|
@@ -702,17 +718,16 @@
|
|
|
702
718
|
exclude_rects: [],
|
|
703
719
|
points: bar_points_for_placement,
|
|
704
720
|
})
|
|
705
|
-
|
|
706
|
-
return result
|
|
707
|
-
})
|
|
721
|
+
}
|
|
708
722
|
|
|
709
723
|
// Tweened legend coordinates with shared placement stability gating
|
|
710
724
|
const legend_tween = create_placed_tween({
|
|
711
|
-
placement:
|
|
725
|
+
placement: get_legend_placement,
|
|
712
726
|
dims: () => ({ width, height }),
|
|
713
727
|
responsive: () => legend?.responsive ?? false,
|
|
714
728
|
element: () => legend_element,
|
|
715
729
|
tween: () => legend?.tween,
|
|
730
|
+
on_element_resize: () => (legend_size_revision += 1),
|
|
716
731
|
})
|
|
717
732
|
|
|
718
733
|
// Tooltip state
|
|
@@ -726,9 +741,7 @@
|
|
|
726
741
|
const srs = internal_series[series_idx]
|
|
727
742
|
const [x, y] = [srs.x[bar_idx], srs.y[bar_idx]]
|
|
728
743
|
const [orient_x, orient_y] = orientation === `horizontal` ? [y, x] : [x, y]
|
|
729
|
-
const metadata = Array.isArray(srs.metadata)
|
|
730
|
-
? srs.metadata[bar_idx]
|
|
731
|
-
: srs.metadata
|
|
744
|
+
const metadata = Array.isArray(srs.metadata) ? srs.metadata[bar_idx] : srs.metadata
|
|
732
745
|
const label = srs.labels?.[bar_idx] ?? null
|
|
733
746
|
const active_y_axis = srs.y_axis ?? `y1`
|
|
734
747
|
const active_x_axis = srs.x_axis ?? `x1`
|
|
@@ -783,7 +796,7 @@
|
|
|
783
796
|
const line_point_fill = (pt: LineSeriesPoint, series_color: string): string =>
|
|
784
797
|
pt.color_value != null
|
|
785
798
|
? color_scale_fn(pt.color_value)
|
|
786
|
-
: pt.point_style?.fill ?? series_color
|
|
799
|
+
: (pt.point_style?.fill ?? series_color)
|
|
787
800
|
|
|
788
801
|
const handle_bar_hover =
|
|
789
802
|
(series_idx: number, bar_idx: number, color: string) => (event: MouseEvent) => {
|
|
@@ -793,6 +806,12 @@
|
|
|
793
806
|
on_bar_hover?.({ ...hover_info, event })
|
|
794
807
|
}
|
|
795
808
|
|
|
809
|
+
const clear_hover = () => {
|
|
810
|
+
hover_info = null
|
|
811
|
+
change(null)
|
|
812
|
+
on_bar_hover?.(null)
|
|
813
|
+
}
|
|
814
|
+
|
|
796
815
|
// Stack offsets (only for bar series in stacked mode, grouped by y-axis)
|
|
797
816
|
let stacked_offsets = $derived(compute_stacked_offsets(internal_series, mode))
|
|
798
817
|
|
|
@@ -805,31 +824,31 @@
|
|
|
805
824
|
})
|
|
806
825
|
|
|
807
826
|
// State accessors for shared axis change handler
|
|
827
|
+
// Secondary axes read the merged $derived (x2_axis/y2_axis) but write the raw $bindable props
|
|
828
|
+
// (x2_axis_prop/y2_axis_prop) so library defaults aren't pushed into the parent's bound state
|
|
808
829
|
const axis_state: AxisChangeState<BarSeries<Metadata>> = {
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
830
|
+
axes: {
|
|
831
|
+
x: { get: () => x_axis, set: (config) => (x_axis = { ...x_axis, ...config }) },
|
|
832
|
+
x2: {
|
|
833
|
+
get: () => x2_axis,
|
|
834
|
+
set: (config) => (x2_axis_prop = { ...x2_axis_prop, ...config }),
|
|
835
|
+
},
|
|
836
|
+
y: { get: () => y_axis, set: (config) => (y_axis = { ...y_axis, ...config }) },
|
|
837
|
+
y2: {
|
|
838
|
+
get: () => y2_axis,
|
|
839
|
+
set: (config) => (y2_axis_prop = { ...y2_axis_prop, ...config }),
|
|
840
|
+
},
|
|
814
841
|
},
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
if (axis === `x`) x_axis = { ...x_axis, ...config }
|
|
818
|
-
else if (axis === `x2`) x2_axis_prop = { ...x2_axis_prop, ...config }
|
|
819
|
-
else if (axis === `y`) y_axis = { ...y_axis, ...config }
|
|
820
|
-
else y2_axis_prop = { ...y2_axis_prop, ...config }
|
|
821
|
-
},
|
|
822
|
-
get_series: () => series,
|
|
823
|
-
set_series: (new_series) => (series = new_series),
|
|
824
|
-
get_loading: () => axis_loading,
|
|
825
|
-
set_loading: (axis) => (axis_loading = axis),
|
|
842
|
+
series: { get: () => series, set: (next) => (series = next) },
|
|
843
|
+
loading: { get: () => axis_loading, set: (axis) => (axis_loading = axis) },
|
|
826
844
|
}
|
|
827
845
|
|
|
828
846
|
// Shared handler + one-shot auto-load bound to this component's state
|
|
829
|
-
const { handle_axis_change, try_auto_load } = create_axis_loader(
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
847
|
+
const { handle_axis_change, try_auto_load } = create_axis_loader(axis_state, () => ({
|
|
848
|
+
data_loader,
|
|
849
|
+
on_axis_change,
|
|
850
|
+
on_error,
|
|
851
|
+
}))
|
|
833
852
|
$effect(try_auto_load)
|
|
834
853
|
</script>
|
|
835
854
|
|
|
@@ -877,7 +896,7 @@
|
|
|
877
896
|
bind:clientWidth={width}
|
|
878
897
|
bind:clientHeight={height}
|
|
879
898
|
{...rest}
|
|
880
|
-
class=
|
|
899
|
+
class={[`bar-plot`, rest.class]}
|
|
881
900
|
class:fullscreen
|
|
882
901
|
>
|
|
883
902
|
{#if width && height}
|
|
@@ -893,7 +912,7 @@
|
|
|
893
912
|
bind:this={svg_element}
|
|
894
913
|
role="application"
|
|
895
914
|
aria-label={rest[`aria-label`] ??
|
|
896
|
-
|
|
915
|
+
([x_axis.label, y_axis.label].filter(Boolean).join(` vs `) || `Bar chart`)}
|
|
897
916
|
tabindex="0"
|
|
898
917
|
onfocusin={() => pan_zoom.set_focused(true)}
|
|
899
918
|
onfocusout={() => pan_zoom.set_focused(false)}
|
|
@@ -902,9 +921,7 @@
|
|
|
902
921
|
onkeydown={pan_zoom.on_key_down}
|
|
903
922
|
onmouseleave={() => {
|
|
904
923
|
hovered = false
|
|
905
|
-
|
|
906
|
-
change(null)
|
|
907
|
-
on_bar_hover?.(null)
|
|
924
|
+
clear_hover()
|
|
908
925
|
}}
|
|
909
926
|
onwheel={pan_zoom.on_wheel}
|
|
910
927
|
ontouchstart={pan_zoom.on_touch_start}
|
|
@@ -937,38 +954,37 @@
|
|
|
937
954
|
<!-- X-axis -->
|
|
938
955
|
<PlotAxis
|
|
939
956
|
side="x"
|
|
940
|
-
ticks={ticks.x
|
|
957
|
+
ticks={ticks.x}
|
|
941
958
|
place={scales.x}
|
|
942
959
|
axis={x_axis}
|
|
943
|
-
domain={ranges.current.x
|
|
960
|
+
domain={ranges.current.x}
|
|
944
961
|
{pad}
|
|
945
962
|
{width}
|
|
946
963
|
{height}
|
|
947
964
|
show_grid={display.x_grid}
|
|
948
965
|
tick_label={(tick) =>
|
|
949
|
-
|
|
966
|
+
get_tick_label(tick, cat_axis === `x` ? effective_cat_ticks : x_axis.ticks)}
|
|
950
967
|
label_x={pad.l + chart_width / 2 + (x_axis.label_shift?.x ?? 0)}
|
|
951
|
-
label_y={height - pad.b
|
|
968
|
+
label_y={height - pad.b + AXIS_TITLE_OFFSET + (x_axis.label_shift?.y ?? 0)}
|
|
952
969
|
axis_loading={axis_loading === `x`}
|
|
953
970
|
on_axis_change={(key) => handle_axis_change(`x`, key)}
|
|
954
971
|
/>
|
|
955
972
|
|
|
956
|
-
<!-- X2-axis (Top) -->
|
|
957
|
-
|
|
958
|
-
{#if x2_series.length > 0 && orientation === `vertical`}
|
|
973
|
+
<!-- X2-axis (Top): only rendered in vertical orientation -->
|
|
974
|
+
{#if show_x2}
|
|
959
975
|
<PlotAxis
|
|
960
976
|
side="x2"
|
|
961
|
-
ticks={ticks.x2
|
|
977
|
+
ticks={ticks.x2}
|
|
962
978
|
place={scales.x2}
|
|
963
979
|
axis={x2_axis}
|
|
964
|
-
domain={ranges.current.x2
|
|
980
|
+
domain={ranges.current.x2}
|
|
965
981
|
{pad}
|
|
966
982
|
{width}
|
|
967
983
|
{height}
|
|
968
984
|
show_grid={display.x2_grid}
|
|
969
985
|
tick_label={(tick) => get_tick_label(tick, x2_axis.ticks)}
|
|
970
986
|
label_x={pad.l + chart_width / 2 + (x2_axis.label_shift?.x ?? 0)}
|
|
971
|
-
label_y={Math.max(12, pad.t - (x2_axis.label_shift?.y ??
|
|
987
|
+
label_y={Math.max(12, pad.t - (x2_axis.label_shift?.y ?? AXIS_TITLE_OFFSET))}
|
|
972
988
|
axis_loading={axis_loading === `x2`}
|
|
973
989
|
on_axis_change={(key) => handle_axis_change(`x2`, key)}
|
|
974
990
|
/>
|
|
@@ -977,19 +993,20 @@
|
|
|
977
993
|
<!-- Y-axis -->
|
|
978
994
|
<PlotAxis
|
|
979
995
|
side="y"
|
|
980
|
-
ticks={ticks.y
|
|
996
|
+
ticks={ticks.y}
|
|
981
997
|
place={scales.y}
|
|
982
998
|
axis={y_axis}
|
|
983
|
-
domain={ranges.current.y
|
|
999
|
+
domain={ranges.current.y}
|
|
984
1000
|
{pad}
|
|
985
1001
|
{width}
|
|
986
1002
|
{height}
|
|
987
1003
|
show_grid={display.y_grid}
|
|
988
1004
|
tick_label={(tick) =>
|
|
989
|
-
|
|
1005
|
+
get_tick_label(tick, cat_axis === `y` ? effective_cat_ticks : y_axis.ticks)}
|
|
990
1006
|
label_x={Math.max(
|
|
991
1007
|
12,
|
|
992
|
-
pad.l -
|
|
1008
|
+
pad.l -
|
|
1009
|
+
(y_axis.tick?.label?.inside ? 0 : tick_label_widths.y_max) -
|
|
993
1010
|
LABEL_GAP_DEFAULT,
|
|
994
1011
|
) + (y_axis.label_shift?.x ?? 0)}
|
|
995
1012
|
label_y={pad.t + chart_height / 2 + (y_axis.label_shift?.y ?? 0)}
|
|
@@ -997,15 +1014,14 @@
|
|
|
997
1014
|
on_axis_change={(key) => handle_axis_change(`y`, key)}
|
|
998
1015
|
/>
|
|
999
1016
|
|
|
1000
|
-
<!-- Y2-axis (Right) -->
|
|
1001
|
-
|
|
1002
|
-
{#if y2_series.length > 0 && orientation === `vertical`}
|
|
1017
|
+
<!-- Y2-axis (Right): only rendered in vertical orientation -->
|
|
1018
|
+
{#if show_y2}
|
|
1003
1019
|
<PlotAxis
|
|
1004
1020
|
side="y2"
|
|
1005
|
-
ticks={ticks.y2
|
|
1021
|
+
ticks={ticks.y2}
|
|
1006
1022
|
place={scales.y2}
|
|
1007
1023
|
axis={y2_axis}
|
|
1008
|
-
domain={ranges.current.y2
|
|
1024
|
+
domain={ranges.current.y2}
|
|
1009
1025
|
{pad}
|
|
1010
1026
|
{width}
|
|
1011
1027
|
{height}
|
|
@@ -1046,8 +1062,8 @@
|
|
|
1046
1062
|
y2_scale_type={y2_axis.scale_type}
|
|
1047
1063
|
x_is_time={x_axis.format?.startsWith(`%`) ?? false}
|
|
1048
1064
|
x2_is_time={x2_axis.format?.startsWith(`%`) ?? false}
|
|
1049
|
-
has_x2={
|
|
1050
|
-
has_y2={
|
|
1065
|
+
has_x2={show_x2}
|
|
1066
|
+
has_y2={show_y2}
|
|
1051
1067
|
{width}
|
|
1052
1068
|
{height}
|
|
1053
1069
|
{pad}
|
|
@@ -1065,7 +1081,7 @@
|
|
|
1065
1081
|
class={is_line ? `line-series` : `bar-series`}
|
|
1066
1082
|
data-series-idx={series_idx}
|
|
1067
1083
|
opacity={hovered_legend_series_idx !== null &&
|
|
1068
|
-
|
|
1084
|
+
hovered_legend_series_idx !== series_idx
|
|
1069
1085
|
? 0.25
|
|
1070
1086
|
: 1}
|
|
1071
1087
|
>
|
|
@@ -1079,21 +1095,22 @@
|
|
|
1079
1095
|
{@const use_x2 = srs.x_axis === `x2`}
|
|
1080
1096
|
{@const x_scale = use_x2 ? scales.x2 : scales.x}
|
|
1081
1097
|
{@const series_markers = srs.markers ?? DEFAULT_MARKERS}
|
|
1082
|
-
{@const show_line =
|
|
1083
|
-
|
|
1084
|
-
{@const show_points =
|
|
1085
|
-
|
|
1098
|
+
{@const show_line =
|
|
1099
|
+
series_markers === `line` || series_markers === `line+points`}
|
|
1100
|
+
{@const show_points =
|
|
1101
|
+
series_markers === `points` || series_markers === `line+points`}
|
|
1086
1102
|
{@const points = compute_line_points({
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
{@const polyline_str =
|
|
1095
|
-
|
|
1096
|
-
|
|
1103
|
+
series: srs,
|
|
1104
|
+
series_idx,
|
|
1105
|
+
orientation,
|
|
1106
|
+
x_scale,
|
|
1107
|
+
y_scale,
|
|
1108
|
+
cat_y_scale: scales.y,
|
|
1109
|
+
})}
|
|
1110
|
+
{@const polyline_str =
|
|
1111
|
+
show_line && points.length > 1
|
|
1112
|
+
? points.map((pt) => `${pt.x},${pt.y}`).join(` `)
|
|
1113
|
+
: ``}
|
|
1097
1114
|
{#if polyline_str}
|
|
1098
1115
|
<polyline
|
|
1099
1116
|
points={polyline_str}
|
|
@@ -1125,11 +1142,7 @@
|
|
|
1125
1142
|
change(hover_info)
|
|
1126
1143
|
on_bar_hover?.({ ...hover_info!, event: evt })
|
|
1127
1144
|
}}
|
|
1128
|
-
onmouseleave={
|
|
1129
|
-
change(null)
|
|
1130
|
-
hover_info = null
|
|
1131
|
-
on_bar_hover?.(null)
|
|
1132
|
-
}}
|
|
1145
|
+
onmouseleave={clear_hover}
|
|
1133
1146
|
onclick={(evt) => {
|
|
1134
1147
|
const pt = find_closest_point(evt, points)
|
|
1135
1148
|
if (!pt) return
|
|
@@ -1142,44 +1155,41 @@
|
|
|
1142
1155
|
{#if show_points}
|
|
1143
1156
|
{@const clickable = on_bar_click || on_point_click}
|
|
1144
1157
|
{@const get_pt = (evt: Event) => {
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
}}
|
|
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
|
+
}}
|
|
1152
1164
|
{@const set_hover = (
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
)
|
|
1169
|
-
}}
|
|
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
|
+
}}
|
|
1170
1180
|
{@const do_click = (
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
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
|
+
}}
|
|
1179
1189
|
{@const leaving = (evt: MouseEvent | FocusEvent) =>
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1190
|
+
(evt.relatedTarget instanceof Element
|
|
1191
|
+
? evt.relatedTarget.closest(`.line-points`)
|
|
1192
|
+
: null) !== evt.currentTarget}
|
|
1183
1193
|
<!-- svelte-ignore a11y_no_noninteractive_element_interactions, a11y_mouse_events_have_key_events -->
|
|
1184
1194
|
<g
|
|
1185
1195
|
class="line-points"
|
|
@@ -1213,11 +1223,13 @@
|
|
|
1213
1223
|
{#each points as pt (pt.idx)}
|
|
1214
1224
|
{@const sty = pt.point_style}
|
|
1215
1225
|
{@const fl = line_point_fill(pt, color)}
|
|
1216
|
-
{@const rad =
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
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}
|
|
1221
1233
|
<ScatterPoint
|
|
1222
1234
|
x={pt.x}
|
|
1223
1235
|
y={pt.y}
|
|
@@ -1248,31 +1260,30 @@
|
|
|
1248
1260
|
<!-- Render as bars -->
|
|
1249
1261
|
{#each srs.x as x_val, bar_idx (bar_idx)}
|
|
1250
1262
|
{@const y_val = srs.y[bar_idx]}
|
|
1251
|
-
{@const base =
|
|
1252
|
-
|
|
1253
|
-
: 0}
|
|
1263
|
+
{@const base =
|
|
1264
|
+
mode === `stacked` ? (stacked_offsets[series_idx]?.[bar_idx] ?? 0) : 0}
|
|
1254
1265
|
{@const color = srs.color ?? bar_state.color ?? `steelblue`}
|
|
1255
1266
|
{@const bar_width_val = Array.isArray(srs.bar_width)
|
|
1256
|
-
|
|
1257
|
-
|
|
1267
|
+
? (srs.bar_width[bar_idx] ?? 0.5)
|
|
1268
|
+
: (srs.bar_width ?? 0.5)}
|
|
1258
1269
|
{@const is_vertical = orientation === `vertical`}
|
|
1259
1270
|
{@const x_scale_bar = srs.x_axis === `x2` ? scales.x2 : scales.x}
|
|
1260
1271
|
{@const [cat_scale, val_scale] = is_vertical
|
|
1261
|
-
|
|
1262
|
-
|
|
1272
|
+
? [x_scale_bar, srs.y_axis === `y2` ? scales.y2 : scales.y]
|
|
1273
|
+
: [scales.y, x_scale_bar]}
|
|
1263
1274
|
{@const { c0, c1, v0, v1, rect_x, rect_y, rect_w, rect_h } =
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
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
|
+
})}
|
|
1276
1287
|
{#if (is_vertical ? rect_h : rect_w) > 0}
|
|
1277
1288
|
<path
|
|
1278
1289
|
d={bar_path(
|
|
@@ -1293,16 +1304,12 @@
|
|
|
1293
1304
|
aria-label={`bar ${bar_idx + 1} of ${srs.label ?? `series`}`}
|
|
1294
1305
|
style:cursor={on_bar_click ? `pointer` : undefined}
|
|
1295
1306
|
onmousemove={handle_bar_hover(series_idx, bar_idx, color)}
|
|
1296
|
-
onmouseleave={
|
|
1297
|
-
hover_info = null
|
|
1298
|
-
change(null)
|
|
1299
|
-
on_bar_hover?.(null)
|
|
1300
|
-
}}
|
|
1307
|
+
onmouseleave={clear_hover}
|
|
1301
1308
|
onclick={(evt) =>
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1309
|
+
on_bar_click?.({
|
|
1310
|
+
...get_bar_data(series_idx, bar_idx, color),
|
|
1311
|
+
event: evt,
|
|
1312
|
+
})}
|
|
1306
1313
|
onkeydown={(evt) => {
|
|
1307
1314
|
if (evt.key === `Enter` || evt.key === ` `) {
|
|
1308
1315
|
evt.preventDefault()
|
|
@@ -1334,17 +1341,44 @@
|
|
|
1334
1341
|
|
|
1335
1342
|
{@render ref_lines_layer(ref_lines_by_z.below_points)}
|
|
1336
1343
|
{@render ref_lines_layer(ref_lines_by_z.above_all)}
|
|
1344
|
+
|
|
1345
|
+
<!-- Marginal distribution strips -->
|
|
1346
|
+
<PlotMarginals
|
|
1347
|
+
marginals={resolved_marginals}
|
|
1348
|
+
series={marginal_series}
|
|
1349
|
+
{width}
|
|
1350
|
+
{height}
|
|
1351
|
+
{pad}
|
|
1352
|
+
has_axis={marginal_has_axis}
|
|
1353
|
+
axes={{
|
|
1354
|
+
x1: marginal_axis(
|
|
1355
|
+
scales.x,
|
|
1356
|
+
ranges.current.x,
|
|
1357
|
+
x_axis,
|
|
1358
|
+
cat_axis === `x` ? (pos) => category_list[Math.round(pos)] : undefined,
|
|
1359
|
+
),
|
|
1360
|
+
x2: marginal_axis(scales.x2, ranges.current.x2, x2_axis),
|
|
1361
|
+
y1: marginal_axis(
|
|
1362
|
+
scales.y,
|
|
1363
|
+
ranges.current.y,
|
|
1364
|
+
y_axis,
|
|
1365
|
+
cat_axis === `y` ? (pos) => category_list[Math.round(pos)] : undefined,
|
|
1366
|
+
),
|
|
1367
|
+
y2: marginal_axis(scales.y2, ranges.current.y2, y2_axis),
|
|
1368
|
+
}}
|
|
1369
|
+
id={clip_path_id}
|
|
1370
|
+
/>
|
|
1337
1371
|
</svg>
|
|
1338
1372
|
|
|
1339
1373
|
<!-- Legend -->
|
|
1340
|
-
{#if legend &&
|
|
1374
|
+
{#if legend && should_show_legend}
|
|
1341
1375
|
{@const legend_pos = placed_coords(
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1376
|
+
decor.legend_outside,
|
|
1377
|
+
decor.legend_pos,
|
|
1378
|
+
legend_tween.placed(),
|
|
1379
|
+
legend_tween.coords.current,
|
|
1380
|
+
{ x: pad.l + 10, y: pad.t + 10 },
|
|
1381
|
+
)}
|
|
1348
1382
|
<PlotLegend
|
|
1349
1383
|
bind:root_element={legend_element}
|
|
1350
1384
|
{...legend}
|
|
@@ -1354,9 +1388,8 @@
|
|
|
1354
1388
|
on_double_click={legend?.on_double_click ?? legend_vis.on_double_click}
|
|
1355
1389
|
on_hover_change={legend_tween.set_locked}
|
|
1356
1390
|
on_item_hover={(item) =>
|
|
1357
|
-
(hovered_legend_series_idx =
|
|
1358
|
-
? item.series_idx
|
|
1359
|
-
: null)}
|
|
1391
|
+
(hovered_legend_series_idx =
|
|
1392
|
+
item != null && item.series_idx >= 0 ? item.series_idx : null)}
|
|
1360
1393
|
active_series_idx={hover_info?.series_idx ?? hovered_legend_series_idx}
|
|
1361
1394
|
style={`
|
|
1362
1395
|
position: absolute;
|
|
@@ -1370,11 +1403,11 @@
|
|
|
1370
1403
|
|
|
1371
1404
|
{#if hover_info && hovered}
|
|
1372
1405
|
{@const cx = (hover_info.active_x_axis === `x2` ? scales.x2 : scales.x)(
|
|
1373
|
-
|
|
1374
|
-
|
|
1406
|
+
hover_info.orient_x,
|
|
1407
|
+
)}
|
|
1375
1408
|
{@const cy = (hover_info.active_y_axis === `y2` ? scales.y2 : scales.y)(
|
|
1376
|
-
|
|
1377
|
-
|
|
1409
|
+
hover_info.orient_y,
|
|
1410
|
+
)}
|
|
1378
1411
|
<PlotTooltip
|
|
1379
1412
|
x={cx}
|
|
1380
1413
|
y={cy}
|
|
@@ -1391,16 +1424,16 @@
|
|
|
1391
1424
|
<div><strong>{series_label}</strong></div>
|
|
1392
1425
|
{/if}
|
|
1393
1426
|
<div>
|
|
1394
|
-
{@html sanitize_html(hover_info.x_axis.label || `x`)}: {
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1427
|
+
{@html sanitize_html(hover_info.x_axis.label || `x`)}: {(cat_axis === `x`
|
|
1428
|
+
? hover_info.category_label
|
|
1429
|
+
: undefined) ??
|
|
1430
|
+
format_value_or_num(hover_info.orient_x, hover_info.x_axis.format)}
|
|
1398
1431
|
</div>
|
|
1399
1432
|
<div>
|
|
1400
|
-
{@html sanitize_html(hover_info.y_axis.label || `y`)}: {
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1433
|
+
{@html sanitize_html(hover_info.y_axis.label || `y`)}: {(cat_axis === `y`
|
|
1434
|
+
? hover_info.category_label
|
|
1435
|
+
: undefined) ??
|
|
1436
|
+
format_value_or_num(hover_info.orient_y, hover_info.y_axis.format)}
|
|
1404
1437
|
</div>
|
|
1405
1438
|
{/if}
|
|
1406
1439
|
</PlotTooltip>
|
|
@@ -1424,12 +1457,12 @@
|
|
|
1424
1457
|
bind:y_axis
|
|
1425
1458
|
bind:y2_axis={y2_axis_prop}
|
|
1426
1459
|
bind:display
|
|
1427
|
-
auto_x_range={auto_ranges.x
|
|
1428
|
-
auto_x2_range={auto_ranges.x2
|
|
1429
|
-
auto_y_range={auto_ranges.y
|
|
1430
|
-
auto_y2_range={auto_ranges.y2
|
|
1431
|
-
has_x2_points={
|
|
1432
|
-
has_y2_points={
|
|
1460
|
+
auto_x_range={auto_ranges.x}
|
|
1461
|
+
auto_x2_range={auto_ranges.x2}
|
|
1462
|
+
auto_y_range={auto_ranges.y}
|
|
1463
|
+
auto_y2_range={auto_ranges.y2}
|
|
1464
|
+
has_x2_points={show_x2}
|
|
1465
|
+
has_y2_points={show_y2}
|
|
1433
1466
|
children={controls_extra}
|
|
1434
1467
|
/>
|
|
1435
1468
|
{/if}
|
|
@@ -1489,7 +1522,9 @@
|
|
|
1489
1522
|
.bar-plot :global(.pane-toggle),
|
|
1490
1523
|
.bar-plot .header-controls {
|
|
1491
1524
|
opacity: 0;
|
|
1492
|
-
transition:
|
|
1525
|
+
transition:
|
|
1526
|
+
opacity 0.2s,
|
|
1527
|
+
background-color 0.2s;
|
|
1493
1528
|
}
|
|
1494
1529
|
.bar-plot:hover :global(.pane-toggle),
|
|
1495
1530
|
.bar-plot:hover .header-controls,
|