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,7 +2,7 @@
|
|
|
2
2
|
lang="ts"
|
|
3
3
|
generics="Metadata extends Record<string, unknown> = Record<string, unknown>"
|
|
4
4
|
>
|
|
5
|
-
import {
|
|
5
|
+
import { format_value_or_num } from '../../labels'
|
|
6
6
|
import { FullscreenToggle, set_fullscreen_bg } from '../../layout'
|
|
7
7
|
import type { Vec2 } from '../../math'
|
|
8
8
|
import type {
|
|
@@ -28,32 +28,39 @@
|
|
|
28
28
|
compute_element_placement,
|
|
29
29
|
PlotAxis,
|
|
30
30
|
PlotLegend,
|
|
31
|
+
PlotMarginals,
|
|
31
32
|
ReferenceLine,
|
|
32
33
|
} from '..'
|
|
34
|
+
import type { MarginalSeriesInput, MarginalsProp } from '../core/marginals'
|
|
35
|
+
import {
|
|
36
|
+
add_sides,
|
|
37
|
+
marginal_axis,
|
|
38
|
+
marginal_axis_presence,
|
|
39
|
+
normalize_marginals,
|
|
40
|
+
reserve_marginal_pad,
|
|
41
|
+
} from '../core/marginals'
|
|
33
42
|
import {
|
|
34
43
|
build_obstacles_norm,
|
|
35
44
|
clip_bar,
|
|
36
45
|
has_explicit_position,
|
|
37
46
|
measured_footprint,
|
|
38
47
|
place_decorations,
|
|
48
|
+
placed_coords,
|
|
39
49
|
} from '../core/auto-place'
|
|
40
50
|
import { compute_box_stats } from './box-plot'
|
|
41
51
|
import { gaussian_kde, type KdeResult } from './kde'
|
|
42
|
-
import {
|
|
52
|
+
import { create_placed_tween } from '../core/placed-tween.svelte'
|
|
53
|
+
import { create_pan_zoom } from '../core/pan-zoom.svelte'
|
|
43
54
|
import { create_legend_visibility } from '../core/utils/series-visibility'
|
|
44
55
|
import {
|
|
45
56
|
axis_ranges_equal,
|
|
46
|
-
|
|
47
|
-
MIN_TOUCH_DISTANCE_PIXELS,
|
|
48
|
-
pan_range_by_pixels,
|
|
49
|
-
PINCH_ZOOM_THRESHOLD,
|
|
50
|
-
remove_drag_listeners,
|
|
57
|
+
invert_rect_range,
|
|
51
58
|
resolve_axis_ranges,
|
|
52
|
-
sorted_range,
|
|
53
|
-
zoom_range_by_factor,
|
|
54
59
|
} from '../core/interactions'
|
|
55
60
|
import {
|
|
61
|
+
AXIS_TITLE_OFFSET,
|
|
56
62
|
calc_auto_padding,
|
|
63
|
+
DEFAULT_PLOT_PADDING,
|
|
57
64
|
filter_padding,
|
|
58
65
|
LABEL_GAP_DEFAULT,
|
|
59
66
|
y2_axis_label_x,
|
|
@@ -63,19 +70,17 @@
|
|
|
63
70
|
import type { IndexedRefLine } from '../core/reference-line'
|
|
64
71
|
import { group_ref_lines_by_z, index_ref_lines } from '../core/reference-line'
|
|
65
72
|
import {
|
|
66
|
-
|
|
73
|
+
create_axis_scales,
|
|
67
74
|
generate_ticks,
|
|
68
75
|
get_nice_data_range,
|
|
69
76
|
get_tick_label,
|
|
70
77
|
} from '../core/scales'
|
|
71
|
-
import type { InitialRanges } from '../core/types'
|
|
72
78
|
import { DEFAULT_SERIES_COLORS } from '../core/types'
|
|
73
79
|
import { unique_id } from '../core/utils'
|
|
74
80
|
import { DEFAULTS } from '../../settings'
|
|
75
81
|
import type { Snippet } from 'svelte'
|
|
76
82
|
import { onDestroy, untrack } from 'svelte'
|
|
77
83
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
78
|
-
import { Tween, type TweenOptions } from 'svelte/motion'
|
|
79
84
|
import { SvelteMap } from 'svelte/reactivity'
|
|
80
85
|
import PlotTooltip from '../core/components/PlotTooltip.svelte'
|
|
81
86
|
import { violin_path } from '../core/svg'
|
|
@@ -120,8 +125,8 @@
|
|
|
120
125
|
y_axis = $bindable({}),
|
|
121
126
|
y2_axis: y2_axis_prop = $bindable({}),
|
|
122
127
|
display = $bindable(DEFAULTS.box.display),
|
|
123
|
-
range_padding = 0
|
|
124
|
-
padding =
|
|
128
|
+
range_padding = 0,
|
|
129
|
+
padding = DEFAULT_PLOT_PADDING,
|
|
125
130
|
legend = {},
|
|
126
131
|
show_legend,
|
|
127
132
|
box = {},
|
|
@@ -135,7 +140,7 @@
|
|
|
135
140
|
show_mean = $bindable(DEFAULTS.box.show_mean),
|
|
136
141
|
show_value_labels = false,
|
|
137
142
|
value_label_stat = `median`,
|
|
138
|
-
value_label_format =
|
|
143
|
+
value_label_format = ``,
|
|
139
144
|
kind = $bindable(DEFAULTS.box.kind),
|
|
140
145
|
side = $bindable(DEFAULTS.box.side),
|
|
141
146
|
bandwidth = DEFAULTS.box.bandwidth,
|
|
@@ -164,51 +169,55 @@
|
|
|
164
169
|
header_controls,
|
|
165
170
|
controls_extra,
|
|
166
171
|
pan = {},
|
|
172
|
+
marginals = false,
|
|
167
173
|
...rest
|
|
168
|
-
}: HTMLAttributes<HTMLDivElement> &
|
|
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
|
-
data: BoxHandlerProps<Metadata>
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
174
|
+
}: HTMLAttributes<HTMLDivElement> &
|
|
175
|
+
BasePlotProps &
|
|
176
|
+
PlotConfig & {
|
|
177
|
+
series?: BoxPlotSeries<Metadata>[]
|
|
178
|
+
orientation?: Orientation
|
|
179
|
+
legend?: LegendConfig | null
|
|
180
|
+
show_legend?: boolean
|
|
181
|
+
box?: BoxStyle
|
|
182
|
+
whisker?: WhiskerStyle
|
|
183
|
+
median_style?: BoxLineStyle
|
|
184
|
+
outlier_style?: OutlierStyle
|
|
185
|
+
whisker_mode?: WhiskerMode
|
|
186
|
+
whisker_range?: number
|
|
187
|
+
whisker_percentiles?: Vec2
|
|
188
|
+
show_outliers?: boolean
|
|
189
|
+
show_mean?: boolean
|
|
190
|
+
show_value_labels?: boolean
|
|
191
|
+
value_label_stat?: `median` | `mean`
|
|
192
|
+
value_label_format?: string
|
|
193
|
+
kind?: ViolinKind
|
|
194
|
+
side?: ViolinSide
|
|
195
|
+
bandwidth?: BandwidthOption
|
|
196
|
+
violin_width?: number
|
|
197
|
+
violin_style?: ViolinStyle
|
|
198
|
+
kde_points?: number
|
|
199
|
+
kde_cut?: number
|
|
200
|
+
kde_max_samples?: number
|
|
201
|
+
kde_clip?: [number | null, number | null]
|
|
202
|
+
tooltip?: Snippet<[BoxHandlerProps<Metadata>]>
|
|
203
|
+
user_content?: Snippet<[UserContentProps]>
|
|
204
|
+
header_controls?: Snippet<[{ height: number; width: number; fullscreen: boolean }]>
|
|
205
|
+
controls_extra?: Snippet<[{ orientation: Orientation } & Required<PlotConfig>]>
|
|
206
|
+
change?: (data: BoxHandlerProps<Metadata> | null) => void
|
|
207
|
+
on_box_click?: (
|
|
208
|
+
data: BoxHandlerProps<Metadata> & { event: MouseEvent | KeyboardEvent },
|
|
209
|
+
) => void
|
|
210
|
+
on_box_hover?: (
|
|
211
|
+
data:
|
|
212
|
+
| (BoxHandlerProps<Metadata> & { event: MouseEvent | FocusEvent | KeyboardEvent })
|
|
213
|
+
| null,
|
|
214
|
+
) => void
|
|
215
|
+
ref_lines?: RefLine[]
|
|
216
|
+
on_ref_line_click?: (event: RefLineEvent) => void
|
|
217
|
+
on_ref_line_hover?: (event: RefLineEvent | null) => void
|
|
218
|
+
pan?: PanConfig
|
|
219
|
+
marginals?: MarginalsProp
|
|
220
|
+
} = $props()
|
|
212
221
|
|
|
213
222
|
let box_state = $derived({ ...DEFAULTS.box.box, ...box })
|
|
214
223
|
let whisker_state = $derived({ ...DEFAULTS.box.whisker, ...whisker })
|
|
@@ -218,24 +227,20 @@
|
|
|
218
227
|
|
|
219
228
|
// Merge secondary-axis defaults as deriveds instead of assigning back into the
|
|
220
229
|
// $bindable props (which would push library defaults into the parent's bound state)
|
|
221
|
-
let y2_axis = $derived(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
range: [null, null],
|
|
236
|
-
...x2_axis_prop,
|
|
237
|
-
} as typeof x2_axis_prop,
|
|
238
|
-
)
|
|
230
|
+
let y2_axis = $derived({
|
|
231
|
+
format: ``,
|
|
232
|
+
scale_type: `linear`,
|
|
233
|
+
ticks: 5,
|
|
234
|
+
range: [null, null],
|
|
235
|
+
...y2_axis_prop,
|
|
236
|
+
} as typeof y2_axis_prop)
|
|
237
|
+
let x2_axis = $derived({
|
|
238
|
+
format: ``,
|
|
239
|
+
scale_type: `linear`,
|
|
240
|
+
ticks: 5,
|
|
241
|
+
range: [null, null],
|
|
242
|
+
...x2_axis_prop,
|
|
243
|
+
} as typeof x2_axis_prop)
|
|
239
244
|
|
|
240
245
|
let [width, height] = $state([0, 0])
|
|
241
246
|
let wrapper: HTMLDivElement | undefined = $state()
|
|
@@ -262,7 +267,7 @@
|
|
|
262
267
|
whisker_range: srs.whisker_range ?? whisker_range,
|
|
263
268
|
whisker_percentiles: srs.whisker_percentiles ?? whisker_percentiles,
|
|
264
269
|
collect_outliers: show_outliers && draws_box(srs) && (srs.visible ?? true),
|
|
265
|
-
})
|
|
270
|
+
}),
|
|
266
271
|
),
|
|
267
272
|
)
|
|
268
273
|
|
|
@@ -315,9 +320,8 @@
|
|
|
315
320
|
// KDE per visible violin series, keyed by series index (bandwidth from the full sample)
|
|
316
321
|
let violin_kdes = $derived.by(() => {
|
|
317
322
|
const map = new SvelteMap<number, KdeResult>()
|
|
318
|
-
const [val_axis, val_axis2] =
|
|
319
|
-
? [y_axis, y2_axis]
|
|
320
|
-
: [x_axis, x2_axis]
|
|
323
|
+
const [val_axis, val_axis2] =
|
|
324
|
+
orientation === `vertical` ? [y_axis, y2_axis] : [x_axis, x2_axis]
|
|
321
325
|
for (const box_item of visible_boxes) {
|
|
322
326
|
if (!draws_violin(box_item.series)) continue
|
|
323
327
|
const samples = box_item.series.y ?? []
|
|
@@ -325,7 +329,10 @@
|
|
|
325
329
|
// On a log value axis the KDE grid tail (data_min - cut*bandwidth) is usually <= 0 →
|
|
326
330
|
// NaN pixels + LOG_EPS range pollution. Clamp the grid to the smallest positive sample.
|
|
327
331
|
if ((is_secondary(box_item.series) ? val_axis2 : val_axis).scale_type === `log`) {
|
|
328
|
-
const min_pos = samples.reduce(
|
|
332
|
+
const min_pos = samples.reduce(
|
|
333
|
+
(min, val) => (val > 0 && val < min ? val : min),
|
|
334
|
+
Infinity,
|
|
335
|
+
)
|
|
329
336
|
// Guard: no positive samples → min_pos is Infinity; leave clip unchanged so the KDE
|
|
330
337
|
// never receives a non-finite lower bound
|
|
331
338
|
if (Number.isFinite(min_pos)) {
|
|
@@ -349,7 +356,11 @@
|
|
|
349
356
|
// The horizontal category pixel axis is inverted, so flip the half-violin side to keep
|
|
350
357
|
// `positive` meaning "above the center line" (vertical/`both` pass through unchanged)
|
|
351
358
|
const to_screen_side = (eff_side: ViolinSide, vertical: boolean): ViolinSide =>
|
|
352
|
-
vertical || eff_side === `both`
|
|
359
|
+
vertical || eff_side === `both`
|
|
360
|
+
? eff_side
|
|
361
|
+
: eff_side === `positive`
|
|
362
|
+
? `negative`
|
|
363
|
+
: `positive`
|
|
353
364
|
|
|
354
365
|
// Peak density per violin, computed once on data change (avoids spreading kde.density into
|
|
355
366
|
// Math.max — unsafe for large kde_points — and re-deriving it on every render/hover).
|
|
@@ -366,8 +377,15 @@
|
|
|
366
377
|
// Which boxes live on the secondary value axis (y2 for vertical, x2 for horizontal)
|
|
367
378
|
const is_secondary = (srs: BoxPlotSeries<Metadata>): boolean =>
|
|
368
379
|
orientation === `vertical` ? srs.y_axis === `y2` : srs.x_axis === `x2`
|
|
369
|
-
let secondary_boxes = $derived(
|
|
380
|
+
let secondary_boxes = $derived(
|
|
381
|
+
visible_boxes.filter((box_item) => is_secondary(box_item.series)),
|
|
382
|
+
)
|
|
370
383
|
let has_secondary = $derived(secondary_boxes.length > 0)
|
|
384
|
+
// The secondary value axis renders transposed by orientation: x2 (top) when horizontal, y2
|
|
385
|
+
// (right) when vertical. Derive once so axis rendering, ticks, range writes, point picking, and
|
|
386
|
+
// marginal placement all stay provably in sync.
|
|
387
|
+
let show_x2 = $derived(has_secondary && orientation === `horizontal`)
|
|
388
|
+
let show_y2 = $derived(has_secondary && orientation === `vertical`)
|
|
371
389
|
|
|
372
390
|
// Collect value-axis points (whiskers, quartiles, outliers, KDE tails) for auto-range
|
|
373
391
|
const value_points = (boxes: Box[]): { x: number; y: number }[] =>
|
|
@@ -413,8 +431,8 @@
|
|
|
413
431
|
)
|
|
414
432
|
|
|
415
433
|
return vertical
|
|
416
|
-
?
|
|
417
|
-
:
|
|
434
|
+
? { x: cat_range, x2: [0, 1] as Vec2, y: value_primary, y2: value_secondary }
|
|
435
|
+
: { x: value_primary, x2: value_secondary, y: cat_range, y2: [0, 1] as Vec2 }
|
|
418
436
|
})
|
|
419
437
|
|
|
420
438
|
let ranges = $state<{
|
|
@@ -425,10 +443,14 @@
|
|
|
425
443
|
current: { x: [0, 1], x2: [0, 1], y: [0, 1], y2: [0, 1] },
|
|
426
444
|
})
|
|
427
445
|
|
|
428
|
-
$effect(() => {
|
|
446
|
+
$effect(() => {
|
|
447
|
+
// sync ranges from axis.range overrides / auto ranges
|
|
429
448
|
// resolve_axis_ranges returns null for transient non-finite bounds (skip: writing
|
|
430
449
|
// NaN breaks scales and, since NaN !== NaN, loops the effect)
|
|
431
|
-
const next = resolve_axis_ranges(
|
|
450
|
+
const next = resolve_axis_ranges(
|
|
451
|
+
{ x: x_axis, x2: x2_axis, y: y_axis, y2: y2_axis },
|
|
452
|
+
auto_ranges,
|
|
453
|
+
)
|
|
432
454
|
if (!next) return
|
|
433
455
|
// untrack the read of `ranges` so the assignment can't re-trigger this effect
|
|
434
456
|
// (reading + writing the same state otherwise causes effect_update_depth_exceeded).
|
|
@@ -438,34 +460,40 @@
|
|
|
438
460
|
}
|
|
439
461
|
})
|
|
440
462
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
const new_pad =
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
) {
|
|
463
|
+
let base_pad = $derived(filter_padding(padding, DEFAULT_PLOT_PADDING))
|
|
464
|
+
|
|
465
|
+
$effect(() => {
|
|
466
|
+
// dynamic padding from tick label widths
|
|
467
|
+
const new_pad =
|
|
468
|
+
width && height && ticks.y.length > 0
|
|
469
|
+
? calc_auto_padding({
|
|
470
|
+
padding,
|
|
471
|
+
default_padding: DEFAULT_PLOT_PADDING,
|
|
472
|
+
x2_axis: { ...x2_axis, tick_values: ticks.x2 },
|
|
473
|
+
y_axis: { ...y_axis, tick_values: ticks.y },
|
|
474
|
+
y2_axis: { ...y2_axis, tick_values: ticks.y2 },
|
|
475
|
+
})
|
|
476
|
+
: filter_padding(padding, DEFAULT_PLOT_PADDING)
|
|
477
|
+
if (width && height && show_y2 && ticks.y2.length > 0) {
|
|
457
478
|
const inside = y2_axis.tick?.label?.inside ?? false
|
|
458
479
|
const tick_shift = inside ? 0 : (y2_axis.tick?.label?.shift?.x ?? 0) + 8
|
|
459
480
|
const tick_width_contribution = inside ? 0 : tick_label_widths.y2_max
|
|
460
481
|
const label_space = y2_axis.label ? 20 : 0
|
|
461
482
|
new_pad.r = Math.max(new_pad.r, tick_shift + tick_width_contribution + 30 + label_space)
|
|
462
483
|
}
|
|
463
|
-
if (
|
|
464
|
-
base_pad.
|
|
484
|
+
if (
|
|
485
|
+
base_pad.t !== new_pad.t ||
|
|
486
|
+
base_pad.b !== new_pad.b ||
|
|
487
|
+
base_pad.l !== new_pad.l ||
|
|
488
|
+
base_pad.r !== new_pad.r
|
|
489
|
+
)
|
|
490
|
+
base_pad = new_pad
|
|
465
491
|
})
|
|
466
492
|
|
|
467
493
|
let legend_element = $state<HTMLDivElement | undefined>()
|
|
468
|
-
const legend_footprint = $derived(
|
|
494
|
+
const legend_footprint = $derived(
|
|
495
|
+
measured_footprint(legend_element, { width: 120, height: 60 }),
|
|
496
|
+
)
|
|
469
497
|
const legend_has_explicit_pos = $derived(has_explicit_position(legend?.style))
|
|
470
498
|
|
|
471
499
|
// Obstacle field in normalized [0,1] coords: each box modeled as a whisker-spanning segment
|
|
@@ -482,8 +510,12 @@
|
|
|
482
510
|
const secondary = is_secondary(box_item.series)
|
|
483
511
|
const cat_rng = vertical ? ranges.current.x : ranges.current.y
|
|
484
512
|
const val_rng = vertical
|
|
485
|
-
?
|
|
486
|
-
|
|
513
|
+
? secondary
|
|
514
|
+
? ranges.current.y2
|
|
515
|
+
: ranges.current.y
|
|
516
|
+
: secondary
|
|
517
|
+
? ranges.current.x2
|
|
518
|
+
: ranges.current.x
|
|
487
519
|
const cat_span = cat_rng[1] - cat_rng[0]
|
|
488
520
|
const val_span = val_rng[1] - val_rng[0]
|
|
489
521
|
if (cat_span === 0 || val_span === 0) continue
|
|
@@ -505,37 +537,70 @@
|
|
|
505
537
|
width,
|
|
506
538
|
height,
|
|
507
539
|
obstacles_norm,
|
|
508
|
-
legend:
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
540
|
+
legend:
|
|
541
|
+
legend != null &&
|
|
542
|
+
should_show_legend &&
|
|
543
|
+
legend_element != null &&
|
|
544
|
+
!legend_has_explicit_pos
|
|
545
|
+
? { footprint: legend_footprint, clearance: legend?.axis_clearance }
|
|
546
|
+
: null,
|
|
547
|
+
}),
|
|
548
|
+
)
|
|
549
|
+
// Marginals are opt-in (default prop `false`) and bind to the VALUE axis, pooling each box's
|
|
550
|
+
// raw samples. The default side follows orientation (value axis = y when vertical, x when
|
|
551
|
+
// horizontal) so the `marginals` boolean / type-string shorthand land on a meaningful side.
|
|
552
|
+
// Each box is tagged with its value axis so a primary-axis marginal ignores secondary boxes.
|
|
553
|
+
const marginal_vertical = $derived(orientation === `vertical`)
|
|
554
|
+
const resolved_marginals = $derived(
|
|
555
|
+
normalize_marginals(marginals, marginal_vertical ? { right: true } : { top: true }),
|
|
513
556
|
)
|
|
514
|
-
const pad = $derived(decor.pad)
|
|
557
|
+
const pad = $derived(add_sides(decor.pad, reserve_marginal_pad(resolved_marginals)))
|
|
558
|
+
const marginal_series = $derived<MarginalSeriesInput[]>(
|
|
559
|
+
visible_boxes.map((box_item) => {
|
|
560
|
+
const secondary = is_secondary(box_item.series)
|
|
561
|
+
return {
|
|
562
|
+
x: marginal_vertical ? undefined : (box_item.series.y ?? []),
|
|
563
|
+
y: marginal_vertical ? (box_item.series.y ?? []) : undefined,
|
|
564
|
+
color: box_color(box_item.idx),
|
|
565
|
+
label: box_item.series.label,
|
|
566
|
+
visible: true,
|
|
567
|
+
x_axis: marginal_vertical ? `x1` : secondary ? `x2` : `x1`,
|
|
568
|
+
y_axis: marginal_vertical ? (secondary ? `y2` : `y1`) : `y1`,
|
|
569
|
+
}
|
|
570
|
+
}),
|
|
571
|
+
)
|
|
572
|
+
const marginal_has_axis = $derived(marginal_axis_presence(show_x2, show_y2))
|
|
515
573
|
const legend_auto_outside = $derived(decor.legend_outside)
|
|
516
574
|
const legend_outside_x = $derived(decor.legend_pos.x)
|
|
517
575
|
const legend_outside_y = $derived(decor.legend_pos.y)
|
|
518
576
|
const chart_width = $derived(Math.max(1, width - pad.l - pad.r))
|
|
519
577
|
const chart_height = $derived(Math.max(1, height - pad.t - pad.b))
|
|
520
578
|
|
|
521
|
-
let scales = $derived(
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
579
|
+
let scales = $derived(
|
|
580
|
+
create_axis_scales(
|
|
581
|
+
{ x: x_axis, x2: x2_axis, y: y_axis, y2: y2_axis },
|
|
582
|
+
ranges.current,
|
|
583
|
+
pad,
|
|
584
|
+
width,
|
|
585
|
+
height,
|
|
586
|
+
),
|
|
587
|
+
)
|
|
527
588
|
|
|
528
589
|
// Value scale for a box (vertical -> y/y2, horizontal -> x/x2), made log-safe: on a
|
|
529
590
|
// log value axis, stats at values <= 0 (whisker_low is often exactly 0; negative
|
|
530
591
|
// outliers) have no finite pixel. Clamp to LOG_EPS so whiskers/boxes/labels draw
|
|
531
592
|
// toward the plot edge (the clip group crops the overshoot) instead of NaN coords.
|
|
532
|
-
const box_val_scale = (srs: BoxPlotSeries<Metadata>): (val: number) => number => {
|
|
593
|
+
const box_val_scale = (srs: BoxPlotSeries<Metadata>): ((val: number) => number) => {
|
|
533
594
|
const vertical = orientation === `vertical`
|
|
534
595
|
const secondary = is_secondary(srs)
|
|
535
596
|
const scale = vertical
|
|
536
|
-
?
|
|
537
|
-
|
|
538
|
-
|
|
597
|
+
? secondary
|
|
598
|
+
? scales.y2
|
|
599
|
+
: scales.y
|
|
600
|
+
: secondary
|
|
601
|
+
? scales.x2
|
|
602
|
+
: scales.x
|
|
603
|
+
const axis = vertical ? (secondary ? y2_axis : y_axis) : secondary ? x2_axis : x_axis
|
|
539
604
|
return axis.scale_type === `log` ? (val) => scale(Math.max(val, LOG_EPS)) : scale
|
|
540
605
|
}
|
|
541
606
|
|
|
@@ -549,35 +614,32 @@
|
|
|
549
614
|
return Object.fromEntries(slot_list.map((cat, idx) => [idx, cat]))
|
|
550
615
|
})
|
|
551
616
|
|
|
552
|
-
let ticks = $derived({
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
:
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
default_count: 8,
|
|
579
|
-
})
|
|
580
|
-
: [],
|
|
617
|
+
let ticks = $derived.by(() => {
|
|
618
|
+
const axis_ticks = (
|
|
619
|
+
axis: typeof x_axis,
|
|
620
|
+
range: Vec2,
|
|
621
|
+
scale: typeof scales.x,
|
|
622
|
+
default_count: number,
|
|
623
|
+
show = true,
|
|
624
|
+
) =>
|
|
625
|
+
width && height && show
|
|
626
|
+
? generate_ticks(range, axis.scale_type ?? `linear`, axis.ticks, scale, {
|
|
627
|
+
default_count,
|
|
628
|
+
})
|
|
629
|
+
: []
|
|
630
|
+
// categorical axes show one tick per slot instead of generated numeric ticks
|
|
631
|
+
return {
|
|
632
|
+
x:
|
|
633
|
+
cat_axis === `x` && width && height
|
|
634
|
+
? slot_indices
|
|
635
|
+
: axis_ticks(x_axis, ranges.current.x, scales.x, 8),
|
|
636
|
+
y:
|
|
637
|
+
cat_axis === `y` && width && height
|
|
638
|
+
? slot_indices
|
|
639
|
+
: axis_ticks(y_axis, ranges.current.y, scales.y, 6),
|
|
640
|
+
y2: axis_ticks(y2_axis, ranges.current.y2, scales.y2, 6, show_y2),
|
|
641
|
+
x2: axis_ticks(x2_axis, ranges.current.x2, scales.x2, 8, show_x2),
|
|
642
|
+
}
|
|
581
643
|
})
|
|
582
644
|
|
|
583
645
|
let tick_label_widths = $derived({
|
|
@@ -586,178 +648,43 @@
|
|
|
586
648
|
x2_max: measure_max_tick_width(ticks.x2, x2_axis.format ?? ``),
|
|
587
649
|
})
|
|
588
650
|
|
|
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
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
const x2_2 = scales.x2.invert(drag_state.current.x) as number
|
|
619
|
-
const dx = Math.abs(drag_state.start.x - drag_state.current.x)
|
|
620
|
-
const dy = Math.abs(drag_state.start.y - drag_state.current.y)
|
|
621
|
-
if (dx > 5 && dy > 5 && Number.isFinite(x1) && Number.isFinite(x2)) {
|
|
622
|
-
x_axis = { ...x_axis, range: sorted_range(x1, x2) }
|
|
623
|
-
// the secondary value axis is x2 only in horizontal mode, y2 only in vertical
|
|
624
|
-
// (is_secondary keys off orientation); writing the off-orientation axis would
|
|
625
|
-
// store a phantom range from its [0, 1] sentinel scale into the bound prop
|
|
626
|
-
if (
|
|
627
|
-
has_secondary && orientation === `horizontal` &&
|
|
628
|
-
Number.isFinite(x2_1) && Number.isFinite(x2_2)
|
|
629
|
-
) {
|
|
630
|
-
x2_axis_prop = { ...x2_axis_prop, range: sorted_range(x2_1, x2_2) }
|
|
631
|
-
}
|
|
632
|
-
y_axis = { ...y_axis, range: sorted_range(y1, y2) }
|
|
633
|
-
if (
|
|
634
|
-
has_secondary && orientation === `vertical` &&
|
|
635
|
-
Number.isFinite(y2_1) && Number.isFinite(y2_2)
|
|
636
|
-
) {
|
|
637
|
-
y2_axis_prop = { ...y2_axis_prop, range: sorted_range(y2_1, y2_2) }
|
|
638
|
-
}
|
|
651
|
+
// Shared pan/zoom/touch/drag-rect interaction controller
|
|
652
|
+
const pan_zoom = create_pan_zoom({
|
|
653
|
+
ranges: () => ranges.current,
|
|
654
|
+
scale_type: (axis) =>
|
|
655
|
+
({ x: x_axis, x2: x2_axis, y: y_axis, y2: y2_axis })[axis].scale_type,
|
|
656
|
+
plot_dims: () => ({ width: chart_width, height: chart_height }),
|
|
657
|
+
pan: () => pan,
|
|
658
|
+
set_range: (axis, range) => (ranges.current[axis] = range),
|
|
659
|
+
svg: () => svg_element,
|
|
660
|
+
on_rect_zoom: (start, current) => {
|
|
661
|
+
const next_x = invert_rect_range(scales.x, start.x, current.x)
|
|
662
|
+
if (!next_x) return
|
|
663
|
+
x_axis = { ...x_axis, range: next_x }
|
|
664
|
+
// the secondary value axis is x2 only in horizontal mode, y2 only in vertical
|
|
665
|
+
// (is_secondary keys off orientation); writing the off-orientation axis would
|
|
666
|
+
// store a phantom range from its [0, 1] sentinel scale into the bound prop
|
|
667
|
+
const next_x2 = show_x2 ? invert_rect_range(scales.x2, start.x, current.x) : null
|
|
668
|
+
if (next_x2) x2_axis_prop = { ...x2_axis_prop, range: next_x2 }
|
|
669
|
+
const next_y = invert_rect_range(scales.y, start.y, current.y)
|
|
670
|
+
if (next_y) y_axis = { ...y_axis, range: next_y }
|
|
671
|
+
const next_y2 = show_y2 ? invert_rect_range(scales.y2, start.y, current.y) : null
|
|
672
|
+
if (next_y2) y2_axis_prop = { ...y2_axis_prop, range: next_y2 }
|
|
673
|
+
},
|
|
674
|
+
on_reset: () => {
|
|
675
|
+
ranges.current = {
|
|
676
|
+
x: [...ranges.initial.x] as Vec2,
|
|
677
|
+
x2: [...ranges.initial.x2] as Vec2,
|
|
678
|
+
y: [...ranges.initial.y] as Vec2,
|
|
679
|
+
y2: [...ranges.initial.y2] as Vec2,
|
|
639
680
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// Pan/zoom all four axes from an interaction-start snapshot, each in its own
|
|
648
|
-
// scale's transform space (log axes pan by a constant factor, linear by a shift)
|
|
649
|
-
const pan_all_axes = (init: InitialRanges, dx_px: number, dy_px: number) => {
|
|
650
|
-
ranges.current.x = pan_range_by_pixels(init.initial_x_range, dx_px, chart_width, x_axis.scale_type)
|
|
651
|
-
ranges.current.x2 = pan_range_by_pixels(init.initial_x2_range, dx_px, chart_width, x2_axis.scale_type)
|
|
652
|
-
ranges.current.y = pan_range_by_pixels(init.initial_y_range, dy_px, chart_height, y_axis.scale_type)
|
|
653
|
-
ranges.current.y2 = pan_range_by_pixels(init.initial_y2_range, dy_px, chart_height, y2_axis.scale_type)
|
|
654
|
-
}
|
|
655
|
-
const zoom_all_axes = (init: InitialRanges, factor: number) => {
|
|
656
|
-
ranges.current.x = zoom_range_by_factor(init.initial_x_range, factor, x_axis.scale_type)
|
|
657
|
-
ranges.current.x2 = zoom_range_by_factor(init.initial_x2_range, factor, x2_axis.scale_type)
|
|
658
|
-
ranges.current.y = zoom_range_by_factor(init.initial_y_range, factor, y_axis.scale_type)
|
|
659
|
-
ranges.current.y2 = zoom_range_by_factor(init.initial_y2_range, factor, y2_axis.scale_type)
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
// Pan drag handler (drag direction inverted on x for natural pan feel)
|
|
663
|
-
const on_pan_move = (evt: MouseEvent) => {
|
|
664
|
-
if (!pan_drag_state) return
|
|
665
|
-
const sensitivity = pan?.drag_sensitivity ?? 1
|
|
666
|
-
pan_all_axes(
|
|
667
|
-
pan_drag_state,
|
|
668
|
-
-(evt.clientX - pan_drag_state.start.x) * sensitivity,
|
|
669
|
-
(evt.clientY - pan_drag_state.start.y) * sensitivity,
|
|
670
|
-
)
|
|
671
|
-
}
|
|
672
|
-
const on_pan_end = () => {
|
|
673
|
-
pan_drag_state = null
|
|
674
|
-
document.body.style.cursor = ``
|
|
675
|
-
window.removeEventListener(`mousemove`, on_pan_move)
|
|
676
|
-
window.removeEventListener(`mouseup`, on_pan_end)
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
// Tear down any window listeners + cursor override if the component unmounts mid-drag
|
|
680
|
-
// (mouseup/panend would otherwise never fire, leaking listeners and a stuck cursor).
|
|
681
|
-
// onDestroy also runs during SSR teardown, where window/document don't exist.
|
|
682
|
-
onDestroy(() => {
|
|
683
|
-
remove_drag_listeners([on_window_mouse_move, on_pan_move], [on_window_mouse_up, on_pan_end])
|
|
684
|
-
drag_state = { start: null, current: null, bounds: null }
|
|
685
|
-
pan_drag_state = null
|
|
681
|
+
x_axis = { ...x_axis, range: [null, null] }
|
|
682
|
+
x2_axis_prop = { ...x2_axis_prop, range: [null, null] }
|
|
683
|
+
y_axis = { ...y_axis, range: [null, null] }
|
|
684
|
+
y2_axis_prop = { ...y2_axis_prop, range: [null, null] }
|
|
685
|
+
},
|
|
686
686
|
})
|
|
687
|
-
|
|
688
|
-
function handle_mouse_down(evt: MouseEvent) {
|
|
689
|
-
const coords = get_relative_coords(evt)
|
|
690
|
-
if (!coords || !svg_element) return
|
|
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 Vec2,
|
|
697
|
-
initial_x2_range: [...ranges.current.x2] as Vec2,
|
|
698
|
-
initial_y_range: [...ranges.current.y] as Vec2,
|
|
699
|
-
initial_y2_range: [...ranges.current.y2] as Vec2,
|
|
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
|
-
drag_state = { start: coords, current: coords, bounds: svg_element.getBoundingClientRect() }
|
|
707
|
-
window.addEventListener(`mousemove`, on_window_mouse_move)
|
|
708
|
-
window.addEventListener(`mouseup`, on_window_mouse_up)
|
|
709
|
-
evt.preventDefault()
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
function handle_wheel(evt: WheelEvent) {
|
|
713
|
-
const pan_enabled = pan?.enabled !== false
|
|
714
|
-
if (!pan_enabled || !is_focused || !shift_held) return
|
|
715
|
-
evt.preventDefault()
|
|
716
|
-
const sensitivity = pan?.wheel_sensitivity ?? 1
|
|
717
|
-
if (Math.abs(evt.deltaX) > Math.abs(evt.deltaY)) {
|
|
718
|
-
const dx = evt.deltaX * sensitivity
|
|
719
|
-
ranges.current.x = pan_range_by_pixels(ranges.current.x, dx, chart_width, x_axis.scale_type)
|
|
720
|
-
ranges.current.x2 = pan_range_by_pixels(ranges.current.x2, dx, chart_width, x2_axis.scale_type)
|
|
721
|
-
} else {
|
|
722
|
-
const dy = evt.deltaY * sensitivity
|
|
723
|
-
ranges.current.y = pan_range_by_pixels(ranges.current.y, dy, chart_height, y_axis.scale_type)
|
|
724
|
-
ranges.current.y2 = pan_range_by_pixels(ranges.current.y2, dy, chart_height, y2_axis.scale_type)
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
function handle_touch_start(evt: TouchEvent) {
|
|
729
|
-
const touch_enabled = pan?.enabled !== false && pan?.touch_enabled !== false
|
|
730
|
-
if (!touch_enabled || evt.touches.length !== 2) return
|
|
731
|
-
evt.preventDefault()
|
|
732
|
-
const touches = Array.from(evt.touches)
|
|
733
|
-
touch_state = {
|
|
734
|
-
start_touches: touches.map((touch) => ({ x: touch.clientX, y: touch.clientY })),
|
|
735
|
-
initial_x_range: [...ranges.current.x] as Vec2,
|
|
736
|
-
initial_x2_range: [...ranges.current.x2] as Vec2,
|
|
737
|
-
initial_y_range: [...ranges.current.y] as Vec2,
|
|
738
|
-
initial_y2_range: [...ranges.current.y2] as Vec2,
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
function handle_touch_move(evt: TouchEvent) {
|
|
742
|
-
if (!touch_state || evt.touches.length !== 2) return
|
|
743
|
-
evt.preventDefault()
|
|
744
|
-
const [t1, t2] = Array.from(evt.touches)
|
|
745
|
-
const [s1, s2] = touch_state.start_touches
|
|
746
|
-
const start_center = { x: (s1.x + s2.x) / 2, y: (s1.y + s2.y) / 2 }
|
|
747
|
-
const curr_center = { x: (t1.clientX + t2.clientX) / 2, y: (t1.clientY + t2.clientY) / 2 }
|
|
748
|
-
const dx = curr_center.x - start_center.x
|
|
749
|
-
const dy = curr_center.y - start_center.y
|
|
750
|
-
const start_dist = Math.hypot(s2.x - s1.x, s2.y - s1.y)
|
|
751
|
-
// ignore near-coincident touches so curr_dist / start_dist can't blow up the scale
|
|
752
|
-
if (start_dist < MIN_TOUCH_DISTANCE_PIXELS) return
|
|
753
|
-
const curr_dist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY)
|
|
754
|
-
const scale = curr_dist / start_dist
|
|
755
|
-
// Pinch zoom about the view center (spread = zoom in, pinch = zoom out)
|
|
756
|
-
if (Math.abs(scale - 1) > PINCH_ZOOM_THRESHOLD && scale > Number.EPSILON) {
|
|
757
|
-
zoom_all_axes(touch_state, scale)
|
|
758
|
-
} else pan_all_axes(touch_state, -dx, dy)
|
|
759
|
-
}
|
|
760
|
-
const handle_touch_end = () => (touch_state = null)
|
|
687
|
+
onDestroy(() => pan_zoom.destroy())
|
|
761
688
|
|
|
762
689
|
// === Legend ===
|
|
763
690
|
let legend_data = $derived<LegendItem[]>(
|
|
@@ -770,7 +697,10 @@
|
|
|
770
697
|
})),
|
|
771
698
|
)
|
|
772
699
|
|
|
773
|
-
const legend_vis = create_legend_visibility(
|
|
700
|
+
const legend_vis = create_legend_visibility(
|
|
701
|
+
() => series,
|
|
702
|
+
(next) => (series = next),
|
|
703
|
+
)
|
|
774
704
|
|
|
775
705
|
let box_points_for_placement = $derived.by(() => {
|
|
776
706
|
if (!width || !height || visible_boxes.length === 0) return []
|
|
@@ -787,10 +717,6 @@
|
|
|
787
717
|
})
|
|
788
718
|
|
|
789
719
|
let hovered_legend_series_idx = $state<number | null>(null)
|
|
790
|
-
const legend_hover = create_hover_lock()
|
|
791
|
-
const dim_tracker = create_dimension_tracker()
|
|
792
|
-
let has_initial_legend_placement = $state(false)
|
|
793
|
-
$effect(() => () => legend_hover.cleanup())
|
|
794
720
|
|
|
795
721
|
let legend_placement = $derived.by(() => {
|
|
796
722
|
if (!should_show_legend || !width || !height) return null
|
|
@@ -804,24 +730,13 @@
|
|
|
804
730
|
})
|
|
805
731
|
})
|
|
806
732
|
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
if (dims_changed) dim_tracker.update(width, height)
|
|
815
|
-
const is_responsive = legend?.responsive ?? false
|
|
816
|
-
const should_update = dims_changed ||
|
|
817
|
-
(!legend_hover.is_locked.current && (is_responsive || !has_initial_legend_placement))
|
|
818
|
-
if (should_update) {
|
|
819
|
-
tweened_legend_coords.set(
|
|
820
|
-
{ x: legend_placement.x, y: legend_placement.y },
|
|
821
|
-
has_initial_legend_placement ? undefined : { duration: 0 },
|
|
822
|
-
)
|
|
823
|
-
if (legend_element) has_initial_legend_placement = true
|
|
824
|
-
}
|
|
733
|
+
// Tweened legend coordinates with shared placement stability gating
|
|
734
|
+
const legend_tween = create_placed_tween({
|
|
735
|
+
placement: () => legend_placement,
|
|
736
|
+
dims: () => ({ width, height }),
|
|
737
|
+
responsive: () => legend?.responsive ?? false,
|
|
738
|
+
element: () => legend_element,
|
|
739
|
+
tween: () => legend?.tween,
|
|
825
740
|
})
|
|
826
741
|
|
|
827
742
|
// === Tooltip / hover ===
|
|
@@ -878,16 +793,13 @@
|
|
|
878
793
|
|
|
879
794
|
// Value label helper
|
|
880
795
|
const value_label_for = (stats: Box[`stats`]): string =>
|
|
881
|
-
|
|
796
|
+
format_value_or_num(
|
|
797
|
+
value_label_stat === `mean` ? stats.mean : stats.median,
|
|
798
|
+
value_label_format,
|
|
799
|
+
)
|
|
882
800
|
</script>
|
|
883
801
|
|
|
884
|
-
{#snippet seg(
|
|
885
|
-
p1: [number, number],
|
|
886
|
-
p2: [number, number],
|
|
887
|
-
stroke: string,
|
|
888
|
-
sw: number,
|
|
889
|
-
dash?: string,
|
|
890
|
-
)}
|
|
802
|
+
{#snippet seg(p1: Vec2, p2: Vec2, stroke: string, sw: number, dash?: string)}
|
|
891
803
|
<line
|
|
892
804
|
x1={p1[0]}
|
|
893
805
|
y1={p1[1]}
|
|
@@ -933,11 +845,9 @@
|
|
|
933
845
|
evt.preventDefault()
|
|
934
846
|
fullscreen = false
|
|
935
847
|
}
|
|
936
|
-
|
|
937
|
-
}}
|
|
938
|
-
onkeyup={(evt) => {
|
|
939
|
-
if (evt.key === `Shift`) shift_held = false
|
|
848
|
+
pan_zoom.on_window_key_down(evt)
|
|
940
849
|
}}
|
|
850
|
+
onkeyup={pan_zoom.on_window_key_up}
|
|
941
851
|
/>
|
|
942
852
|
|
|
943
853
|
<div
|
|
@@ -945,7 +855,7 @@
|
|
|
945
855
|
bind:clientWidth={width}
|
|
946
856
|
bind:clientHeight={height}
|
|
947
857
|
{...rest}
|
|
948
|
-
class=
|
|
858
|
+
class={[`box-plot`, rest.class]}
|
|
949
859
|
class:fullscreen
|
|
950
860
|
>
|
|
951
861
|
{#if width && height}
|
|
@@ -961,39 +871,27 @@
|
|
|
961
871
|
bind:this={svg_element}
|
|
962
872
|
role="application"
|
|
963
873
|
aria-label={rest[`aria-label`] ??
|
|
964
|
-
|
|
874
|
+
([x_axis.label, y_axis.label].filter(Boolean).join(` vs `) || `Box plot`)}
|
|
965
875
|
tabindex="0"
|
|
966
|
-
onfocusin={() => (
|
|
967
|
-
onfocusout={() => (
|
|
968
|
-
onmousedown={
|
|
969
|
-
ondblclick={
|
|
970
|
-
|
|
971
|
-
ranges.current.x2 = [...ranges.initial.x2] as Vec2
|
|
972
|
-
ranges.current.y = [...ranges.initial.y] as Vec2
|
|
973
|
-
ranges.current.y2 = [...ranges.initial.y2] as Vec2
|
|
974
|
-
x_axis = { ...x_axis, range: [null, null] }
|
|
975
|
-
x2_axis_prop = { ...x2_axis_prop, range: [null, null] }
|
|
976
|
-
y_axis = { ...y_axis, range: [null, null] }
|
|
977
|
-
y2_axis_prop = { ...y2_axis_prop, range: [null, null] }
|
|
978
|
-
}}
|
|
876
|
+
onfocusin={() => pan_zoom.set_focused(true)}
|
|
877
|
+
onfocusout={() => pan_zoom.set_focused(false)}
|
|
878
|
+
onmousedown={pan_zoom.on_mouse_down}
|
|
879
|
+
ondblclick={pan_zoom.reset_view}
|
|
880
|
+
onkeydown={pan_zoom.on_key_down}
|
|
979
881
|
onmouseleave={() => {
|
|
980
882
|
hovered = false
|
|
981
883
|
hover_info = null
|
|
982
884
|
change(null)
|
|
983
885
|
on_box_hover?.(null)
|
|
984
886
|
}}
|
|
985
|
-
onwheel={
|
|
986
|
-
ontouchstart={
|
|
987
|
-
ontouchmove={
|
|
988
|
-
ontouchend={
|
|
989
|
-
ontouchcancel={
|
|
990
|
-
style:cursor={
|
|
991
|
-
? `grabbing`
|
|
992
|
-
: shift_held && pan?.enabled !== false
|
|
993
|
-
? `grab`
|
|
994
|
-
: `crosshair`}
|
|
887
|
+
onwheel={pan_zoom.on_wheel}
|
|
888
|
+
ontouchstart={pan_zoom.on_touch_start}
|
|
889
|
+
ontouchmove={pan_zoom.on_touch_move}
|
|
890
|
+
ontouchend={pan_zoom.on_touch_end}
|
|
891
|
+
ontouchcancel={pan_zoom.on_touch_end}
|
|
892
|
+
style:cursor={pan_zoom.cursor}
|
|
995
893
|
>
|
|
996
|
-
<ZoomRect start={
|
|
894
|
+
<ZoomRect start={pan_zoom.drag_start} current={pan_zoom.drag_current} />
|
|
997
895
|
|
|
998
896
|
{@render user_content?.({
|
|
999
897
|
height,
|
|
@@ -1014,65 +912,67 @@
|
|
|
1014
912
|
|
|
1015
913
|
<PlotAxis
|
|
1016
914
|
side="x"
|
|
1017
|
-
ticks={ticks.x
|
|
915
|
+
ticks={ticks.x}
|
|
1018
916
|
place={scales.x}
|
|
1019
917
|
axis={x_axis}
|
|
1020
|
-
domain={ranges.current.x
|
|
918
|
+
domain={ranges.current.x}
|
|
1021
919
|
{pad}
|
|
1022
920
|
{width}
|
|
1023
921
|
{height}
|
|
1024
922
|
show_grid={display.x_grid}
|
|
1025
923
|
tick_label={(tick) =>
|
|
1026
|
-
|
|
924
|
+
get_tick_label(tick, cat_axis === `x` ? effective_cat_ticks : x_axis.ticks)}
|
|
1027
925
|
tick_color={cat_axis === `x` ? (tick) => slot_colors.get(tick) : undefined}
|
|
1028
926
|
label_x={pad.l + chart_width / 2 + (x_axis.label_shift?.x ?? 0)}
|
|
1029
|
-
label_y={height - pad.b
|
|
927
|
+
label_y={height - pad.b + AXIS_TITLE_OFFSET + (x_axis.label_shift?.y ?? 0)}
|
|
1030
928
|
/>
|
|
1031
929
|
|
|
1032
|
-
{#if
|
|
930
|
+
{#if show_x2}
|
|
1033
931
|
<PlotAxis
|
|
1034
932
|
side="x2"
|
|
1035
|
-
ticks={ticks.x2
|
|
933
|
+
ticks={ticks.x2}
|
|
1036
934
|
place={scales.x2}
|
|
1037
935
|
axis={x2_axis}
|
|
1038
|
-
domain={ranges.current.x2
|
|
936
|
+
domain={ranges.current.x2}
|
|
1039
937
|
{pad}
|
|
1040
938
|
{width}
|
|
1041
939
|
{height}
|
|
1042
940
|
show_grid={display.x2_grid}
|
|
1043
941
|
tick_label={(tick) => get_tick_label(tick, x2_axis.ticks)}
|
|
1044
942
|
label_x={pad.l + chart_width / 2 + (x2_axis.label_shift?.x ?? 0)}
|
|
1045
|
-
label_y={Math.max(12, pad.t - (x2_axis.label_shift?.y ??
|
|
943
|
+
label_y={Math.max(12, pad.t - (x2_axis.label_shift?.y ?? AXIS_TITLE_OFFSET))}
|
|
1046
944
|
/>
|
|
1047
945
|
{/if}
|
|
1048
946
|
|
|
1049
947
|
<PlotAxis
|
|
1050
948
|
side="y"
|
|
1051
|
-
ticks={ticks.y
|
|
949
|
+
ticks={ticks.y}
|
|
1052
950
|
place={scales.y}
|
|
1053
951
|
axis={y_axis}
|
|
1054
|
-
domain={ranges.current.y
|
|
952
|
+
domain={ranges.current.y}
|
|
1055
953
|
{pad}
|
|
1056
954
|
{width}
|
|
1057
955
|
{height}
|
|
1058
956
|
show_grid={display.y_grid}
|
|
1059
957
|
tick_label={(tick) =>
|
|
1060
|
-
|
|
958
|
+
get_tick_label(tick, cat_axis === `y` ? effective_cat_ticks : y_axis.ticks)}
|
|
1061
959
|
tick_color={cat_axis === `y` ? (tick) => slot_colors.get(tick) : undefined}
|
|
1062
960
|
label_x={Math.max(
|
|
1063
961
|
12,
|
|
1064
|
-
pad.l -
|
|
962
|
+
pad.l -
|
|
963
|
+
(y_axis.tick?.label?.inside ? 0 : tick_label_widths.y_max) -
|
|
964
|
+
LABEL_GAP_DEFAULT,
|
|
1065
965
|
) + (y_axis.label_shift?.x ?? 0)}
|
|
1066
966
|
label_y={pad.t + chart_height / 2 + (y_axis.label_shift?.y ?? 0)}
|
|
1067
967
|
/>
|
|
1068
968
|
|
|
1069
|
-
{#if
|
|
969
|
+
{#if show_y2}
|
|
1070
970
|
<PlotAxis
|
|
1071
971
|
side="y2"
|
|
1072
|
-
ticks={ticks.y2
|
|
972
|
+
ticks={ticks.y2}
|
|
1073
973
|
place={scales.y2}
|
|
1074
974
|
axis={y2_axis}
|
|
1075
|
-
domain={ranges.current.y2
|
|
975
|
+
domain={ranges.current.y2}
|
|
1076
976
|
{pad}
|
|
1077
977
|
{width}
|
|
1078
978
|
{height}
|
|
@@ -1108,8 +1008,8 @@
|
|
|
1108
1008
|
x2_scale_type={x2_axis.scale_type}
|
|
1109
1009
|
y_scale_type={y_axis.scale_type}
|
|
1110
1010
|
y2_scale_type={y2_axis.scale_type}
|
|
1111
|
-
has_x2={
|
|
1112
|
-
has_y2={
|
|
1011
|
+
has_x2={show_x2}
|
|
1012
|
+
has_y2={show_y2}
|
|
1113
1013
|
{width}
|
|
1114
1014
|
{height}
|
|
1115
1015
|
{pad}
|
|
@@ -1130,12 +1030,13 @@
|
|
|
1130
1030
|
{@const draw_box = draws_box(box_item.series)}
|
|
1131
1031
|
{@const kde = violin_kdes.get(box_item.idx)}
|
|
1132
1032
|
{@const eff_side = box_item.series.side ?? side}
|
|
1133
|
-
{@const bw =
|
|
1134
|
-
|
|
1033
|
+
{@const bw =
|
|
1034
|
+
box_item.series.box_width ??
|
|
1035
|
+
(kde ? DEFAULTS.box.violin_box_width : DEFAULTS.box.box_width)}
|
|
1135
1036
|
{@const c_lo = cat_scale(box_item.slot - bw / 2)}
|
|
1136
1037
|
{@const c_hi = cat_scale(box_item.slot + bw / 2)}
|
|
1137
1038
|
{@const c_center = cat_scale(box_item.slot)}
|
|
1138
|
-
{@const cap = Math.abs(c_hi - c_lo) * (whisker_state.cap_fraction ?? 0.5) / 2}
|
|
1039
|
+
{@const cap = (Math.abs(c_hi - c_lo) * (whisker_state.cap_fraction ?? 0.5)) / 2}
|
|
1139
1040
|
{@const cap_lo = c_center - cap}
|
|
1140
1041
|
{@const cap_hi = c_center + cap}
|
|
1141
1042
|
{@const v_q1 = val_scale(stats.q1)}
|
|
@@ -1144,8 +1045,8 @@
|
|
|
1144
1045
|
{@const v_wl = val_scale(stats.whisker_low)}
|
|
1145
1046
|
{@const v_wh = val_scale(stats.whisker_high)}
|
|
1146
1047
|
{@const v_mean = val_scale(stats.mean)}
|
|
1147
|
-
{@const pt = (cross: number, val: number):
|
|
1148
|
-
|
|
1048
|
+
{@const pt = (cross: number, val: number): Vec2 =>
|
|
1049
|
+
vertical ? [cross, val] : [val, cross]}
|
|
1149
1050
|
{@const [q1x, q1y] = pt(c_lo, v_q1)}
|
|
1150
1051
|
{@const [q3x, q3y] = pt(c_hi, v_q3)}
|
|
1151
1052
|
{@const [wlx, wly] = pt(c_lo, v_wl)}
|
|
@@ -1159,12 +1060,12 @@
|
|
|
1159
1060
|
{@const hit_w = Math.abs(whx - wlx)}
|
|
1160
1061
|
{@const hit_h = Math.abs(why - wly)}
|
|
1161
1062
|
{@const [label_x, label_y] = vertical
|
|
1162
|
-
|
|
1163
|
-
|
|
1063
|
+
? [c_center, Math.min(v_wh, v_wl) - 6]
|
|
1064
|
+
: [Math.max(v_wh, v_wl) + 6, c_center]}
|
|
1164
1065
|
{@const violin_half = Math.abs(
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1066
|
+
cat_scale(box_item.slot + (box_item.series.violin_width ?? violin_width) / 2) -
|
|
1067
|
+
c_center,
|
|
1068
|
+
)}
|
|
1168
1069
|
{@const max_density = kde ? (violin_max_density.get(box_item.idx) ?? 0) : 0}
|
|
1169
1070
|
<!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events -->
|
|
1170
1071
|
<g
|
|
@@ -1175,7 +1076,7 @@
|
|
|
1175
1076
|
aria-label={`box ${box_item.idx + 1}: ${box_item.series.label ?? ``}`}
|
|
1176
1077
|
style:cursor={on_box_click ? `pointer` : undefined}
|
|
1177
1078
|
opacity={hovered_legend_series_idx !== null &&
|
|
1178
|
-
|
|
1079
|
+
hovered_legend_series_idx !== box_item.idx
|
|
1179
1080
|
? 0.25
|
|
1180
1081
|
: 1}
|
|
1181
1082
|
onmousemove={handle_box_hover(box_item, color)}
|
|
@@ -1184,7 +1085,8 @@
|
|
|
1184
1085
|
change(null)
|
|
1185
1086
|
on_box_hover?.(null)
|
|
1186
1087
|
}}
|
|
1187
|
-
onclick={(evt) =>
|
|
1088
|
+
onclick={(evt) =>
|
|
1089
|
+
on_box_click?.({ ...get_box_data(box_item, color), event: evt })}
|
|
1188
1090
|
onkeydown={(evt) => {
|
|
1189
1091
|
if (evt.key === `Enter` || evt.key === ` `) {
|
|
1190
1092
|
evt.preventDefault()
|
|
@@ -1231,7 +1133,12 @@
|
|
|
1231
1133
|
stroke-width={box_state.stroke_width}
|
|
1232
1134
|
/>
|
|
1233
1135
|
<!-- median (solid) and mean (dashed) -->
|
|
1234
|
-
{@render seg(
|
|
1136
|
+
{@render seg(
|
|
1137
|
+
pt(c_lo, v_med),
|
|
1138
|
+
pt(c_hi, v_med),
|
|
1139
|
+
median_state.color,
|
|
1140
|
+
median_state.width,
|
|
1141
|
+
)}
|
|
1235
1142
|
{#if show_mean}
|
|
1236
1143
|
{@render seg(
|
|
1237
1144
|
pt(c_lo, v_mean),
|
|
@@ -1287,19 +1194,33 @@
|
|
|
1287
1194
|
|
|
1288
1195
|
{@render ref_lines_layer(ref_lines_by_z.below_points)}
|
|
1289
1196
|
{@render ref_lines_layer(ref_lines_by_z.above_all)}
|
|
1197
|
+
|
|
1198
|
+
<!-- Marginal distribution strips -->
|
|
1199
|
+
<PlotMarginals
|
|
1200
|
+
marginals={resolved_marginals}
|
|
1201
|
+
series={marginal_series}
|
|
1202
|
+
{width}
|
|
1203
|
+
{height}
|
|
1204
|
+
{pad}
|
|
1205
|
+
has_axis={marginal_has_axis}
|
|
1206
|
+
axes={{
|
|
1207
|
+
x1: marginal_axis(scales.x, ranges.current.x, x_axis),
|
|
1208
|
+
x2: marginal_axis(scales.x2, ranges.current.x2, x2_axis),
|
|
1209
|
+
y1: marginal_axis(scales.y, ranges.current.y, y_axis),
|
|
1210
|
+
y2: marginal_axis(scales.y2, ranges.current.y2, y2_axis),
|
|
1211
|
+
}}
|
|
1212
|
+
id={clip_path_id}
|
|
1213
|
+
/>
|
|
1290
1214
|
</svg>
|
|
1291
1215
|
|
|
1292
1216
|
{#if legend && should_show_legend}
|
|
1293
|
-
{@const
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
: legend_placement
|
|
1301
|
-
? tweened_legend_coords.current.y
|
|
1302
|
-
: pad.t + 10}
|
|
1217
|
+
{@const legend_pos = placed_coords(
|
|
1218
|
+
legend_auto_outside,
|
|
1219
|
+
{ x: legend_outside_x, y: legend_outside_y },
|
|
1220
|
+
legend_placement,
|
|
1221
|
+
legend_tween.coords.current,
|
|
1222
|
+
{ x: pad.l + 10, y: pad.t + 10 },
|
|
1223
|
+
)}
|
|
1303
1224
|
<PlotLegend
|
|
1304
1225
|
bind:root_element={legend_element}
|
|
1305
1226
|
{...legend}
|
|
@@ -1307,13 +1228,12 @@
|
|
|
1307
1228
|
on_toggle={legend?.on_toggle ?? legend_vis.on_toggle}
|
|
1308
1229
|
on_group_toggle={legend?.on_group_toggle ?? legend_vis.on_group_toggle}
|
|
1309
1230
|
on_double_click={legend?.on_double_click ?? legend_vis.on_double_click}
|
|
1310
|
-
on_hover_change={
|
|
1231
|
+
on_hover_change={legend_tween.set_locked}
|
|
1311
1232
|
on_item_hover={(item) =>
|
|
1312
|
-
(hovered_legend_series_idx =
|
|
1313
|
-
? item.series_idx
|
|
1314
|
-
: null)}
|
|
1233
|
+
(hovered_legend_series_idx =
|
|
1234
|
+
item != null && item.series_idx >= 0 ? item.series_idx : null)}
|
|
1315
1235
|
active_series_idx={hover_info?.series_idx ?? hovered_legend_series_idx}
|
|
1316
|
-
style={`position: absolute; left: ${
|
|
1236
|
+
style={`position: absolute; left: ${legend_pos.x}px; top: ${legend_pos.y}px; pointer-events: auto; ${
|
|
1317
1237
|
legend?.style || ``
|
|
1318
1238
|
}`}
|
|
1319
1239
|
/>
|
|
@@ -1331,7 +1251,7 @@
|
|
|
1331
1251
|
{#if tooltip}
|
|
1332
1252
|
{@render tooltip({ ...hover_info, fullscreen })}
|
|
1333
1253
|
{:else}
|
|
1334
|
-
{@const fmt =
|
|
1254
|
+
{@const fmt = orientation === `vertical` ? y_axis.format : x_axis.format}
|
|
1335
1255
|
{@const stat = hover_info.stats}
|
|
1336
1256
|
{@const rows = [
|
|
1337
1257
|
[`max`, stat.whisker_high],
|
|
@@ -1345,7 +1265,7 @@
|
|
|
1345
1265
|
<div><strong>{hover_info.category_label}</strong></div>
|
|
1346
1266
|
{/if}
|
|
1347
1267
|
{#each rows as [label, value] (label)}
|
|
1348
|
-
<div>{label}: {
|
|
1268
|
+
<div>{label}: {format_value_or_num(value, fmt)}</div>
|
|
1349
1269
|
{/each}
|
|
1350
1270
|
{#if show_outliers && stat.outliers.length > 0}
|
|
1351
1271
|
<div>outliers: {stat.outliers.length}</div>
|
|
@@ -1376,12 +1296,12 @@
|
|
|
1376
1296
|
bind:y_axis
|
|
1377
1297
|
bind:y2_axis={y2_axis_prop}
|
|
1378
1298
|
bind:display
|
|
1379
|
-
auto_x_range={auto_ranges.x
|
|
1380
|
-
auto_x2_range={auto_ranges.x2
|
|
1381
|
-
auto_y_range={auto_ranges.y
|
|
1382
|
-
auto_y2_range={auto_ranges.y2
|
|
1383
|
-
has_x2_points={
|
|
1384
|
-
has_y2_points={
|
|
1299
|
+
auto_x_range={auto_ranges.x}
|
|
1300
|
+
auto_x2_range={auto_ranges.x2}
|
|
1301
|
+
auto_y_range={auto_ranges.y}
|
|
1302
|
+
auto_y2_range={auto_ranges.y2}
|
|
1303
|
+
has_x2_points={show_x2}
|
|
1304
|
+
has_y2_points={show_y2}
|
|
1385
1305
|
children={controls_extra}
|
|
1386
1306
|
/>
|
|
1387
1307
|
{/if}
|
|
@@ -1438,7 +1358,9 @@
|
|
|
1438
1358
|
.box-plot :global(.pane-toggle),
|
|
1439
1359
|
.box-plot .header-controls {
|
|
1440
1360
|
opacity: 0;
|
|
1441
|
-
transition:
|
|
1361
|
+
transition:
|
|
1362
|
+
opacity 0.2s,
|
|
1363
|
+
background-color 0.2s;
|
|
1442
1364
|
}
|
|
1443
1365
|
.box-plot:hover :global(.pane-toggle),
|
|
1444
1366
|
.box-plot:hover .header-controls,
|