matterviz 0.3.7 → 0.4.1
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/Icon.svelte +7 -4
- package/dist/MillerIndexInput.svelte +1 -1
- package/dist/api/optimade.js +32 -26
- package/dist/app.css +0 -3
- package/dist/brillouin/BrillouinZone.svelte +76 -148
- package/dist/brillouin/BrillouinZone.svelte.d.ts +6 -14
- package/dist/brillouin/BrillouinZoneExportPane.svelte +43 -96
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +9 -32
- package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
- package/dist/brillouin/BrillouinZoneScene.svelte +97 -205
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +4 -23
- package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
- 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 +89 -90
- 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 +14 -13
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +109 -203
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +180 -470
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
- package/dist/chempot-diagram/async-compute.svelte.js +3 -1
- package/dist/chempot-diagram/chempot-worker.js +2 -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 +4 -4
- package/dist/chempot-diagram/compute.js +20 -20
- 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.js +8 -7
- package/dist/composition/FormulaFilter.svelte +18 -11
- package/dist/composition/PieChart.svelte +11 -10
- package/dist/composition/chem-sys.d.ts +8 -0
- package/dist/composition/chem-sys.js +86 -0
- package/dist/composition/format.js +7 -4
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/index.js +1 -0
- package/dist/composition/parse.d.ts +0 -1
- package/dist/composition/parse.js +41 -31
- package/dist/controls.d.ts +1 -0
- package/dist/controls.js +0 -1
- package/dist/convex-hull/ConvexHull.svelte +8 -10
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
- package/dist/convex-hull/ConvexHull2D.svelte +106 -185
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +179 -683
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +183 -687
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +268 -0
- package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
- package/dist/convex-hull/ConvexHullControls.svelte +88 -7
- 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 +36 -175
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +11 -2
- package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
- package/dist/convex-hull/GasPressureControls.svelte +4 -4
- package/dist/convex-hull/TemperatureSlider.svelte +2 -2
- 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 +278 -0
- package/dist/convex-hull/demo-temperature.d.ts +1 -1
- package/dist/convex-hull/demo-temperature.js +20 -22
- package/dist/convex-hull/gas-thermodynamics.d.ts +2 -2
- package/dist/convex-hull/gas-thermodynamics.js +22 -30
- package/dist/convex-hull/helpers.d.ts +42 -7
- package/dist/convex-hull/helpers.js +171 -78
- 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 +10 -8
- package/dist/convex-hull/index.js +7 -2
- package/dist/convex-hull/thermodynamics.js +136 -960
- package/dist/convex-hull/types.d.ts +13 -5
- package/dist/convex-hull/types.js +12 -0
- package/dist/coordination/CoordinationBarPlot.svelte +27 -34
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/element/BohrAtom.svelte +2 -1
- package/dist/element/index.d.ts +4 -0
- package/dist/element/index.js +18 -0
- package/dist/feedback/DragOverlay.svelte +3 -1
- package/dist/feedback/DragOverlay.svelte.d.ts +1 -0
- package/dist/feedback/StatusMessage.svelte +13 -3
- package/dist/fermi-surface/FermiSlice.svelte +13 -5
- package/dist/fermi-surface/FermiSurface.svelte +78 -151
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -14
- package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +72 -221
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
- package/dist/fermi-surface/compute.js +67 -66
- package/dist/fermi-surface/export.js +6 -16
- 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 +71 -79
- package/dist/fermi-surface/types.d.ts +3 -2
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +69 -52
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +4 -3
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +3 -2
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
- package/dist/heatmap-matrix/index.d.ts +3 -2
- package/dist/heatmap-matrix/index.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/io/ExportPane.svelte +166 -0
- package/dist/io/ExportPane.svelte.d.ts +17 -0
- package/dist/io/decompress.js +5 -4
- package/dist/io/export.d.ts +9 -5
- package/dist/io/export.js +77 -51
- package/dist/io/fetch.d.ts +2 -1
- package/dist/io/fetch.js +5 -1
- package/dist/io/file-drop.d.ts +8 -1
- package/dist/io/file-drop.js +48 -36
- package/dist/io/index.d.ts +2 -0
- package/dist/io/index.js +10 -0
- package/dist/io/types.d.ts +13 -0
- package/dist/io/url-drop.js +64 -33
- package/dist/isosurface/parse.js +52 -51
- package/dist/isosurface/slice.js +5 -4
- package/dist/isosurface/types.js +1 -1
- package/dist/keyboard.d.ts +3 -0
- package/dist/keyboard.js +23 -0
- package/dist/labels.d.ts +1 -1
- package/dist/labels.js +9 -8
- package/dist/layout/FullscreenButton.svelte +33 -0
- package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
- package/dist/layout/FullscreenToggle.svelte +8 -14
- package/dist/layout/PropertyFilter.svelte +3 -2
- package/dist/layout/SettingsSection.svelte +1 -1
- package/dist/layout/ViewerChrome.svelte +116 -0
- package/dist/layout/ViewerChrome.svelte.d.ts +17 -0
- package/dist/layout/fullscreen.d.ts +4 -0
- package/dist/layout/fullscreen.svelte.d.ts +8 -0
- package/dist/layout/fullscreen.svelte.js +37 -0
- package/dist/layout/index.d.ts +3 -0
- package/dist/layout/index.js +3 -0
- package/dist/layout/json-tree/JsonNode.svelte +1 -1
- package/dist/layout/json-tree/JsonTree.svelte +2 -2
- package/dist/layout/json-tree/utils.js +5 -4
- package/dist/marching-cubes.js +8 -13
- package/dist/math.d.ts +12 -4
- package/dist/math.js +42 -30
- package/dist/overlays/DraggablePane.svelte +4 -4
- package/dist/overlays/index.d.ts +4 -0
- package/dist/periodic-table/PeriodicTable.svelte +27 -15
- package/dist/periodic-table/PropertySelect.svelte +1 -0
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +9 -3
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramControls.svelte +3 -2
- 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 +47 -132
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
- package/dist/phase-diagram/build-diagram.js +2 -2
- package/dist/phase-diagram/colors.js +1 -1
- package/dist/phase-diagram/parse.d.ts +2 -1
- package/dist/phase-diagram/parse.js +6 -5
- package/dist/phase-diagram/types.d.ts +1 -1
- package/dist/phase-diagram/utils.d.ts +3 -3
- package/dist/phase-diagram/utils.js +8 -12
- package/dist/plot/{BarPlot.svelte → bar/BarPlot.svelte} +246 -841
- package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +8 -16
- package/dist/plot/{BarPlotControls.svelte → bar/BarPlotControls.svelte} +6 -5
- package/dist/plot/{BarPlotControls.svelte.d.ts → bar/BarPlotControls.svelte.d.ts} +3 -3
- package/dist/plot/{SpacegroupBarPlot.svelte → bar/SpacegroupBarPlot.svelte} +8 -7
- package/dist/plot/{SpacegroupBarPlot.svelte.d.ts → bar/SpacegroupBarPlot.svelte.d.ts} +1 -1
- package/dist/plot/bar/data.d.ts +40 -0
- package/dist/plot/bar/data.js +154 -0
- package/dist/plot/bar/geometry.d.ts +39 -0
- package/dist/plot/bar/geometry.js +60 -0
- package/dist/plot/bar/index.d.ts +3 -0
- package/dist/plot/bar/index.js +3 -0
- package/dist/plot/box/BoxPlot.svelte +1292 -0
- package/dist/plot/box/BoxPlot.svelte.d.ts +95 -0
- package/dist/plot/box/BoxPlotControls.svelte +109 -0
- package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
- package/dist/plot/box/Violin.svelte +14 -0
- package/dist/plot/box/Violin.svelte.d.ts +70 -0
- package/dist/plot/box/box-plot.d.ts +56 -0
- package/dist/plot/box/box-plot.js +129 -0
- package/dist/plot/box/index.d.ts +5 -0
- package/dist/plot/box/index.js +5 -0
- package/dist/plot/box/kde.d.ts +17 -0
- package/dist/plot/box/kde.js +160 -0
- package/dist/plot/box/quantile.d.ts +3 -0
- package/dist/plot/box/quantile.js +53 -0
- package/dist/plot/{auto-place.d.ts → core/auto-place.d.ts} +1 -1
- package/dist/plot/{auto-place.js → core/auto-place.js} +6 -3
- package/dist/plot/core/axis-utils.d.ts +46 -0
- package/dist/plot/core/axis-utils.js +110 -0
- package/dist/plot/{AxisLabel.svelte → core/components/AxisLabel.svelte} +2 -2
- package/dist/plot/{AxisLabel.svelte.d.ts → core/components/AxisLabel.svelte.d.ts} +1 -1
- package/dist/plot/{ColorBar.svelte → core/components/ColorBar.svelte} +41 -38
- package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +7 -6
- package/dist/plot/{ColorScaleSelect.svelte → core/components/ColorScaleSelect.svelte} +4 -3
- package/dist/plot/{ColorScaleSelect.svelte.d.ts → core/components/ColorScaleSelect.svelte.d.ts} +2 -2
- package/dist/plot/core/components/ControlPane.svelte +46 -0
- package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
- package/dist/plot/{FillArea.svelte → core/components/FillArea.svelte} +17 -6
- package/dist/plot/{FillArea.svelte.d.ts → core/components/FillArea.svelte.d.ts} +1 -1
- package/dist/plot/{InteractiveAxisLabel.svelte → core/components/InteractiveAxisLabel.svelte} +3 -3
- package/dist/plot/{InteractiveAxisLabel.svelte.d.ts → core/components/InteractiveAxisLabel.svelte.d.ts} +2 -2
- package/dist/plot/{Line.svelte → core/components/Line.svelte} +33 -15
- package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +3 -2
- package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +9 -6
- package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +5 -3
- package/dist/plot/{PlotControls.svelte → core/components/PlotControls.svelte} +17 -29
- package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
- package/dist/plot/{PlotLegend.svelte → core/components/PlotLegend.svelte} +21 -10
- package/dist/plot/{PlotLegend.svelte.d.ts → core/components/PlotLegend.svelte.d.ts} +3 -2
- package/dist/plot/{PlotTooltip.svelte → core/components/PlotTooltip.svelte} +17 -1
- package/dist/plot/{PlotTooltip.svelte.d.ts → core/components/PlotTooltip.svelte.d.ts} +8 -0
- package/dist/plot/{PortalSelect.svelte → core/components/PortalSelect.svelte} +11 -7
- package/dist/plot/{ReferenceLine.svelte → core/components/ReferenceLine.svelte} +3 -3
- package/dist/plot/{ReferenceLine.svelte.d.ts → core/components/ReferenceLine.svelte.d.ts} +1 -1
- package/dist/plot/{ReferenceLine3D.svelte → core/components/ReferenceLine3D.svelte} +5 -5
- package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +5 -5
- package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +8 -8
- package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +5 -5
- package/dist/plot/{ZeroLines.svelte → core/components/ZeroLines.svelte} +3 -3
- package/dist/plot/{ZeroLines.svelte.d.ts → core/components/ZeroLines.svelte.d.ts} +3 -3
- package/dist/plot/{ZoomRect.svelte → core/components/ZoomRect.svelte} +1 -1
- package/dist/plot/{ZoomRect.svelte.d.ts → core/components/ZoomRect.svelte.d.ts} +1 -1
- package/dist/plot/core/components/index.d.ts +17 -0
- package/dist/plot/core/components/index.js +17 -0
- package/dist/plot/{data-cleaning.d.ts → core/data-cleaning.d.ts} +71 -1
- package/dist/plot/{data-cleaning.js → core/data-cleaning.js} +21 -23
- package/dist/plot/{data-transform.d.ts → core/data-transform.d.ts} +2 -2
- package/dist/plot/{data-transform.js → core/data-transform.js} +3 -3
- package/dist/plot/core/fill-utils.d.ts +34 -0
- package/dist/plot/core/fill-utils.js +391 -0
- package/dist/plot/core/index.d.ts +10 -0
- package/dist/plot/core/index.js +11 -0
- package/dist/plot/core/interactions.d.ts +39 -0
- package/dist/plot/core/interactions.js +209 -0
- package/dist/plot/{layout.d.ts → core/layout.d.ts} +1 -0
- package/dist/plot/{layout.js → core/layout.js} +16 -8
- 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/{reference-line.d.ts → core/reference-line.d.ts} +11 -11
- package/dist/plot/{reference-line.js → core/reference-line.js} +29 -42
- package/dist/plot/core/scales.d.ts +40 -0
- package/dist/plot/{scales.js → core/scales.js} +94 -93
- package/dist/plot/core/svg.d.ts +3 -0
- package/dist/plot/core/svg.js +41 -0
- package/dist/plot/{types.d.ts → core/types.d.ts} +36 -85
- package/dist/plot/{types.js → core/types.js} +1 -1
- package/dist/plot/{utils → core/utils}/label-placement.d.ts +3 -3
- package/dist/plot/{utils → core/utils}/label-placement.js +3 -3
- package/dist/plot/core/utils/series-visibility.d.ts +26 -0
- package/dist/plot/{utils → core/utils}/series-visibility.js +29 -2
- package/dist/plot/core/utils.d.ts +12 -0
- package/dist/plot/core/utils.js +27 -0
- package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +174 -551
- package/dist/plot/{Histogram.svelte.d.ts → histogram/Histogram.svelte.d.ts} +2 -2
- package/dist/plot/{HistogramControls.svelte → histogram/HistogramControls.svelte} +6 -6
- package/dist/plot/{HistogramControls.svelte.d.ts → histogram/HistogramControls.svelte.d.ts} +4 -4
- package/dist/plot/histogram/index.d.ts +2 -0
- package/dist/plot/histogram/index.js +2 -0
- package/dist/plot/index.d.ts +8 -41
- package/dist/plot/index.js +10 -39
- package/dist/plot/sankey/Sankey.svelte +697 -0
- package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
- package/dist/plot/sankey/SankeyControls.svelte +98 -0
- package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
- package/dist/plot/sankey/index.d.ts +4 -0
- package/dist/plot/sankey/index.js +3 -0
- package/dist/plot/sankey/sankey-types.d.ts +42 -0
- package/dist/plot/sankey/sankey-types.js +4 -0
- package/dist/plot/sankey/sankey.d.ts +52 -0
- package/dist/plot/sankey/sankey.js +189 -0
- package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +64 -64
- package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +6 -6
- package/dist/plot/{ElementScatter.svelte → scatter/ElementScatter.svelte} +6 -6
- package/dist/plot/{ElementScatter.svelte.d.ts → scatter/ElementScatter.svelte.d.ts} +2 -2
- package/dist/plot/{ScatterPlot.svelte → scatter/ScatterPlot.svelte} +297 -1008
- package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +10 -18
- package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
- package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +2 -2
- package/dist/plot/{ScatterPoint.svelte → scatter/ScatterPoint.svelte} +7 -7
- package/dist/plot/{ScatterPoint.svelte.d.ts → scatter/ScatterPoint.svelte.d.ts} +3 -3
- package/dist/plot/{adaptive-density.d.ts → scatter/adaptive-density.d.ts} +14 -4
- package/dist/plot/{adaptive-density.js → scatter/adaptive-density.js} +46 -20
- package/dist/plot/{binned-scatter-types.d.ts → scatter/binned-scatter-types.d.ts} +5 -12
- package/dist/plot/scatter/index.d.ts +7 -0
- package/dist/plot/scatter/index.js +5 -0
- package/dist/plot/scatter/scatter-data.d.ts +19 -0
- package/dist/plot/scatter/scatter-data.js +212 -0
- package/dist/plot/{ScatterPlot3D.svelte → scatter-3d/ScatterPlot3D.svelte} +25 -34
- package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +9 -17
- package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +14 -14
- package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +6 -6
- package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +129 -128
- package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +6 -15
- package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +7 -6
- package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +5 -4
- package/dist/plot/scatter-3d/index.d.ts +4 -0
- package/dist/plot/scatter-3d/index.js +4 -0
- package/dist/plot/sunburst/Sunburst.svelte +1041 -0
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +97 -0
- package/dist/plot/sunburst/SunburstControls.svelte +200 -0
- package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
- package/dist/plot/sunburst/index.d.ts +4 -0
- package/dist/plot/sunburst/index.js +4 -0
- package/dist/plot/sunburst/render.d.ts +34 -0
- package/dist/plot/sunburst/render.js +122 -0
- package/dist/plot/sunburst/sunburst.d.ts +62 -0
- package/dist/plot/sunburst/sunburst.js +269 -0
- package/dist/rdf/RdfPlot.svelte +2 -1
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/calc-rdf.js +11 -24
- 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 +14 -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 +79 -3
- package/dist/settings.js +321 -1
- package/dist/spectral/Bands.svelte +47 -36
- package/dist/spectral/Bands.svelte.d.ts +6 -6
- package/dist/spectral/BandsAndDos.svelte +23 -25
- package/dist/spectral/BrillouinBandsDos.svelte +42 -30
- package/dist/spectral/Dos.svelte +15 -23
- package/dist/spectral/Dos.svelte.d.ts +4 -3
- package/dist/spectral/helpers.d.ts +8 -6
- package/dist/spectral/helpers.js +137 -65
- package/dist/state.svelte.d.ts +0 -7
- package/dist/state.svelte.js +0 -6
- package/dist/structure/Arrow.svelte +2 -4
- package/dist/structure/AtomLegend.svelte +8 -9
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/CanvasTooltip.svelte +1 -0
- package/dist/structure/CellSelect.svelte +12 -5
- package/dist/structure/CellSelect.svelte.d.ts +2 -1
- package/dist/structure/Cylinder.svelte +12 -8
- package/dist/structure/Cylinder.svelte.d.ts +4 -1
- package/dist/structure/Lattice.svelte +2 -2
- package/dist/structure/Structure.svelte +365 -423
- package/dist/structure/Structure.svelte.d.ts +5 -15
- package/dist/structure/StructureControls.svelte +217 -2
- package/dist/structure/StructureControls.svelte.d.ts +5 -3
- package/dist/structure/StructureExportPane.svelte +54 -156
- package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
- package/dist/structure/StructureInfoPane.svelte +10 -9
- package/dist/structure/StructureInfoPane.svelte.d.ts +5 -5
- package/dist/structure/StructureScene.svelte +376 -208
- package/dist/structure/StructureScene.svelte.d.ts +22 -20
- package/dist/structure/{label-placement.d.ts → atom-label-placement.d.ts} +3 -3
- package/dist/structure/{label-placement.js → atom-label-placement.js} +15 -5
- package/dist/structure/atom-properties.d.ts +1 -1
- package/dist/structure/atom-properties.js +17 -22
- package/dist/structure/bond-order-perception.js +3 -5
- package/dist/structure/bonding.d.ts +4 -0
- package/dist/structure/bonding.js +134 -63
- package/dist/structure/export.d.ts +24 -4
- package/dist/structure/export.js +89 -143
- package/dist/structure/index.d.ts +4 -4
- package/dist/structure/index.js +3 -3
- package/dist/structure/measure.d.ts +3 -2
- package/dist/structure/measure.js +6 -5
- package/dist/structure/parse.d.ts +3 -2
- package/dist/structure/parse.js +419 -438
- package/dist/structure/partial-occupancy.d.ts +0 -1
- package/dist/structure/partial-occupancy.js +1 -1
- package/dist/structure/pbc.d.ts +1 -1
- package/dist/structure/pbc.js +190 -13
- package/dist/structure/polyhedra.d.ts +41 -0
- package/dist/structure/polyhedra.js +602 -0
- package/dist/structure/site.d.ts +4 -0
- package/dist/structure/site.js +1 -0
- package/dist/structure/supercell.js +3 -2
- 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 +354 -0
- package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
- package/dist/symmetry/SymmetryStats.svelte +113 -8
- package/dist/symmetry/WyckoffTable.svelte +68 -7
- package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
- package/dist/symmetry/cell-transform.js +7 -14
- package/dist/symmetry/index.d.ts +14 -4
- package/dist/symmetry/index.js +291 -72
- package/dist/symmetry/spacegroups.d.ts +12 -1
- package/dist/symmetry/spacegroups.js +63 -14
- 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 +66 -25
- package/dist/table/HeatmapTable.svelte.d.ts +1 -1
- package/dist/table/index.d.ts +1 -3
- package/dist/table/index.js +1 -1
- package/dist/theme/index.js +8 -8
- package/dist/tooltip/KCoords.svelte +45 -0
- package/dist/tooltip/KCoords.svelte.d.ts +8 -0
- package/dist/tooltip/index.d.ts +1 -0
- package/dist/tooltip/index.js +1 -0
- package/dist/trajectory/Trajectory.svelte +123 -100
- package/dist/trajectory/Trajectory.svelte.d.ts +11 -22
- package/dist/trajectory/TrajectoryExportPane.svelte +17 -25
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
- package/dist/trajectory/TrajectoryInfoPane.svelte +5 -3
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
- package/dist/trajectory/constants.js +6 -2
- package/dist/trajectory/extract.js +17 -37
- package/dist/trajectory/format-detect.d.ts +1 -1
- package/dist/trajectory/format-detect.js +27 -19
- package/dist/trajectory/frame-reader.d.ts +0 -1
- package/dist/trajectory/frame-reader.js +63 -162
- package/dist/trajectory/helpers.d.ts +10 -2
- package/dist/trajectory/helpers.js +56 -36
- package/dist/trajectory/index.js +1 -1
- 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/hdf5.js +1 -1
- package/dist/trajectory/parse/index.d.ts +1 -1
- package/dist/trajectory/parse/index.js +65 -105
- package/dist/trajectory/parse/lammps.d.ts +0 -2
- package/dist/trajectory/parse/lammps.js +8 -6
- package/dist/trajectory/parse/pymatgen.d.ts +2 -0
- package/dist/trajectory/parse/pymatgen.js +74 -0
- package/dist/trajectory/parse/vasp.js +38 -18
- package/dist/trajectory/parse/xyz.d.ts +13 -1
- package/dist/trajectory/parse/xyz.js +102 -94
- package/dist/trajectory/plotting.d.ts +1 -2
- package/dist/trajectory/plotting.js +16 -113
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +7 -5
- package/dist/xrd/XrdPlot.svelte +16 -30
- package/dist/xrd/broadening.d.ts +2 -1
- package/dist/xrd/calc-xrd.js +18 -20
- package/dist/xrd/index.d.ts +2 -2
- package/dist/xrd/parse.js +2 -2
- package/package.json +43 -26
- 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/PlotControls.svelte.d.ts +0 -4
- package/dist/plot/axis-utils.d.ts +0 -19
- package/dist/plot/axis-utils.js +0 -78
- package/dist/plot/defaults.d.ts +0 -19
- package/dist/plot/defaults.js +0 -9
- package/dist/plot/fill-utils.d.ts +0 -46
- package/dist/plot/fill-utils.js +0 -322
- package/dist/plot/hover-lock.svelte.d.ts +0 -14
- package/dist/plot/hover-lock.svelte.js +0 -46
- package/dist/plot/interactions.d.ts +0 -12
- package/dist/plot/interactions.js +0 -101
- package/dist/plot/scales.d.ts +0 -48
- package/dist/plot/svg.d.ts +0 -1
- package/dist/plot/svg.js +0 -11
- package/dist/plot/utils/series-visibility.d.ts +0 -15
- package/dist/plot/utils.d.ts +0 -1
- package/dist/plot/utils.js +0 -14
- /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
- /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { format_value } from '
|
|
3
|
-
import { FullscreenToggle, set_fullscreen_bg } from '
|
|
2
|
+
import { format_value } from '../../labels'
|
|
3
|
+
import { FullscreenToggle, set_fullscreen_bg } from '../../layout'
|
|
4
4
|
import type {
|
|
5
5
|
AxisLoadError,
|
|
6
6
|
BarStyle,
|
|
@@ -9,70 +9,67 @@
|
|
|
9
9
|
PanConfig,
|
|
10
10
|
RefLine,
|
|
11
11
|
RefLineEvent,
|
|
12
|
-
} from '
|
|
12
|
+
} from '..'
|
|
13
13
|
import {
|
|
14
14
|
compute_element_placement,
|
|
15
15
|
HistogramControls,
|
|
16
16
|
PlotAxis,
|
|
17
17
|
PlotLegend,
|
|
18
18
|
ReferenceLine,
|
|
19
|
-
} from '
|
|
20
|
-
import type { AxisChangeState } from '
|
|
21
|
-
import {
|
|
22
|
-
import { extract_series_color, prepare_legend_data } from '
|
|
23
|
-
import {
|
|
19
|
+
} from '..'
|
|
20
|
+
import type { AxisChangeState } from '../core/axis-utils'
|
|
21
|
+
import { AXIS_DEFAULTS, create_axis_loader } from '../core/axis-utils'
|
|
22
|
+
import { extract_series_color, prepare_legend_data } from '../core/data-transform'
|
|
23
|
+
import { create_placed_tween } from '../core/placed-tween.svelte'
|
|
24
|
+
import { create_pan_zoom } from '../core/pan-zoom.svelte'
|
|
25
|
+
import { create_legend_visibility } from '../core/utils/series-visibility'
|
|
24
26
|
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
get_relative_coords,
|
|
30
|
-
pan_range,
|
|
31
|
-
PINCH_ZOOM_THRESHOLD,
|
|
32
|
-
pixels_to_data_delta,
|
|
33
|
-
} from './interactions'
|
|
27
|
+
invert_rect_range,
|
|
28
|
+
resolve_axis_ranges,
|
|
29
|
+
vec2_equal,
|
|
30
|
+
} from '../core/interactions'
|
|
34
31
|
import {
|
|
35
32
|
calc_auto_padding,
|
|
36
|
-
constrain_tooltip_position,
|
|
37
33
|
filter_padding,
|
|
38
34
|
LABEL_GAP_DEFAULT,
|
|
35
|
+
y2_axis_label_x,
|
|
39
36
|
measure_max_tick_width,
|
|
40
|
-
} from '
|
|
37
|
+
} from '../core/layout'
|
|
41
38
|
import {
|
|
42
39
|
build_obstacles_norm,
|
|
43
40
|
clip_bar,
|
|
44
41
|
has_explicit_position,
|
|
45
42
|
measured_footprint,
|
|
46
43
|
place_decorations,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
import {
|
|
44
|
+
placed_coords,
|
|
45
|
+
} from '../core/auto-place'
|
|
46
|
+
import type { IndexedRefLine } from '../core/reference-line'
|
|
47
|
+
import { group_ref_lines_by_z, index_ref_lines } from '../core/reference-line'
|
|
50
48
|
import {
|
|
51
49
|
create_scale,
|
|
52
50
|
generate_ticks,
|
|
53
51
|
get_nice_data_range,
|
|
54
52
|
get_tick_label,
|
|
55
|
-
} from '
|
|
53
|
+
} from '../core/scales'
|
|
56
54
|
import type {
|
|
57
55
|
BasePlotProps,
|
|
58
56
|
DataSeries,
|
|
59
|
-
InitialRanges,
|
|
60
57
|
LegendConfig,
|
|
61
58
|
PlotConfig,
|
|
62
59
|
ScaleType,
|
|
63
|
-
} from '
|
|
64
|
-
import { get_scale_type_name } from '
|
|
65
|
-
import ZeroLines from '
|
|
66
|
-
import ZoomRect from '
|
|
67
|
-
import { DEFAULTS } from '
|
|
60
|
+
} from '../core/types'
|
|
61
|
+
import { get_scale_type_name } from '../core/types'
|
|
62
|
+
import ZeroLines from '../core/components/ZeroLines.svelte'
|
|
63
|
+
import ZoomRect from '../core/components/ZoomRect.svelte'
|
|
64
|
+
import { DEFAULTS } from '../../settings'
|
|
68
65
|
import { bin, max } from 'd3-array'
|
|
69
66
|
import type { Snippet } from 'svelte'
|
|
70
|
-
import { untrack } from 'svelte'
|
|
67
|
+
import { onDestroy, untrack } from 'svelte'
|
|
71
68
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
72
|
-
import {
|
|
73
|
-
import
|
|
74
|
-
import
|
|
75
|
-
import {
|
|
69
|
+
import type { Vec2 } from '../../math'
|
|
70
|
+
import PlotTooltip from '../core/components/PlotTooltip.svelte'
|
|
71
|
+
import { bar_path } from '../core/svg'
|
|
72
|
+
import { unique_id } from '../core/utils'
|
|
76
73
|
|
|
77
74
|
let {
|
|
78
75
|
series = $bindable([]),
|
|
@@ -81,10 +78,6 @@
|
|
|
81
78
|
y_axis: y_axis_init = {},
|
|
82
79
|
y2_axis: y2_axis_init = {},
|
|
83
80
|
display: display_init = DEFAULTS.histogram.display,
|
|
84
|
-
x_range = [null, null],
|
|
85
|
-
x2_range = [null, null],
|
|
86
|
-
y_range = [null, null],
|
|
87
|
-
y2_range = [null, null],
|
|
88
81
|
range_padding = 0.05,
|
|
89
82
|
padding = { t: 20, b: 60, l: 60, r: 20 },
|
|
90
83
|
bins = $bindable(100),
|
|
@@ -173,10 +166,10 @@
|
|
|
173
166
|
...x2_axis_init,
|
|
174
167
|
})))
|
|
175
168
|
let y_axis = $state(untrack(() => ({ ...axis_state_defaults, ...y_axis_init })))
|
|
176
|
-
// y2
|
|
169
|
+
// y2 title stays vertically centered; its x position is computed by y2_axis_label_x
|
|
177
170
|
let y2_axis = $state(untrack(() => ({
|
|
178
171
|
...axis_state_defaults,
|
|
179
|
-
label_shift: { x: 0, y:
|
|
172
|
+
label_shift: { x: 0, y: 0 },
|
|
180
173
|
...y2_axis_init,
|
|
181
174
|
})))
|
|
182
175
|
let display = $state(
|
|
@@ -194,7 +187,7 @@
|
|
|
194
187
|
let [width, height] = $state([0, 0])
|
|
195
188
|
let wrapper: HTMLDivElement | undefined = $state()
|
|
196
189
|
let svg_element: SVGElement | null = $state(null)
|
|
197
|
-
|
|
190
|
+
const clip_path_id = unique_id(`histogram-clip`) // stable, collision-resistant (see unique_id)
|
|
198
191
|
let hover_info = $state<HistogramHandlerProps | null>(null)
|
|
199
192
|
|
|
200
193
|
// Reference line hover state
|
|
@@ -206,32 +199,10 @@
|
|
|
206
199
|
// Compute ref_lines with index and group by z-index (using shared utilities)
|
|
207
200
|
let indexed_ref_lines = $derived(index_ref_lines(ref_lines))
|
|
208
201
|
let ref_lines_by_z = $derived(group_ref_lines_by_z(indexed_ref_lines))
|
|
209
|
-
let tooltip_el = $state<HTMLDivElement | undefined>()
|
|
210
|
-
let drag_state = $state<{
|
|
211
|
-
start: { x: number; y: number } | null
|
|
212
|
-
current: { x: number; y: number } | null
|
|
213
|
-
bounds: DOMRect | null
|
|
214
|
-
}>({ start: null, current: null, bounds: null })
|
|
215
|
-
|
|
216
|
-
// Pan state
|
|
217
|
-
let is_focused = $state(false)
|
|
218
|
-
let shift_held = $state(false)
|
|
219
|
-
let pan_drag_state = $state<
|
|
220
|
-
InitialRanges & { start: { x: number; y: number } } | null
|
|
221
|
-
>(null)
|
|
222
|
-
let touch_state = $state<
|
|
223
|
-
InitialRanges & { start_touches: { x: number; y: number }[] } | null
|
|
224
|
-
>(null)
|
|
225
202
|
|
|
226
203
|
// Legend placement stability state
|
|
227
204
|
let legend_element = $state<HTMLDivElement | undefined>()
|
|
228
205
|
let hovered_legend_series_idx = $state<number | null>(null)
|
|
229
|
-
const legend_hover = create_hover_lock()
|
|
230
|
-
const dim_tracker = create_dimension_tracker()
|
|
231
|
-
let has_initial_legend_placement = $state(false)
|
|
232
|
-
|
|
233
|
-
// Clear pending hover lock timeout on unmount
|
|
234
|
-
$effect(() => () => legend_hover.cleanup())
|
|
235
206
|
|
|
236
207
|
// Derived data
|
|
237
208
|
type IndexedSeries = { series_data: DataSeries; series_idx: number }
|
|
@@ -270,11 +241,12 @@
|
|
|
270
241
|
)
|
|
271
242
|
|
|
272
243
|
let auto_ranges = $derived.by(() => {
|
|
273
|
-
|
|
244
|
+
// Only x1 series contribute to the x1 auto-range (x2 series get their own domain below)
|
|
245
|
+
const x1_values = selected_series.flatMap((srs) => srs.x_axis === `x2` ? [] : srs.y)
|
|
274
246
|
const auto_x = get_nice_data_range(
|
|
275
|
-
|
|
247
|
+
x1_values.map((val) => ({ x: val, y: 0 })),
|
|
276
248
|
({ x }) => x,
|
|
277
|
-
|
|
249
|
+
final_x_axis.range ?? [null, null],
|
|
278
250
|
final_x_axis.scale_type ?? `linear`,
|
|
279
251
|
range_padding,
|
|
280
252
|
false,
|
|
@@ -285,7 +257,7 @@
|
|
|
285
257
|
? get_nice_data_range(
|
|
286
258
|
x2_values.map((val) => ({ x: val, y: 0 })),
|
|
287
259
|
({ x }) => x,
|
|
288
|
-
|
|
260
|
+
final_x2_axis.range ?? [null, null],
|
|
289
261
|
final_x2_axis.scale_type ?? `linear`,
|
|
290
262
|
range_padding,
|
|
291
263
|
false,
|
|
@@ -295,20 +267,22 @@
|
|
|
295
267
|
// Calculate y-range for a specific set of series
|
|
296
268
|
const calc_y_range = (
|
|
297
269
|
series_list: typeof selected_series,
|
|
298
|
-
y_limit:
|
|
270
|
+
y_limit: [number | null, number | null],
|
|
299
271
|
scale_type: ScaleType,
|
|
300
272
|
): Vec2 => {
|
|
301
273
|
const type_name = get_scale_type_name(scale_type)
|
|
302
|
-
if (
|
|
274
|
+
if (series_list.length === 0) {
|
|
303
275
|
const fallback = type_name === `log` ? 1 : 0
|
|
304
276
|
return [fallback, 1]
|
|
305
277
|
}
|
|
306
|
-
|
|
278
|
+
// Bin each series over the domain of the x-axis it renders on (d3 bin() drops
|
|
279
|
+
// out-of-domain values, so binning x2 series over the x1 domain skews max_count)
|
|
307
280
|
const max_count = Math.max(
|
|
308
281
|
0,
|
|
309
|
-
...series_list.map((srs: DataSeries) =>
|
|
310
|
-
|
|
311
|
-
|
|
282
|
+
...series_list.map((srs: DataSeries) => {
|
|
283
|
+
const hist = bin().domain(srs.x_axis === `x2` ? auto_x2 : auto_x).thresholds(bins)
|
|
284
|
+
return max(hist(srs.y), (data) => data.length) || 0
|
|
285
|
+
}),
|
|
312
286
|
)
|
|
313
287
|
|
|
314
288
|
// If there's effectively no data, avoid log-range issues (counts can't be <= 0 on log)
|
|
@@ -333,12 +307,12 @@
|
|
|
333
307
|
|
|
334
308
|
const y1_range = calc_y_range(
|
|
335
309
|
y1_series,
|
|
336
|
-
|
|
310
|
+
final_y_axis.range ?? [null, null],
|
|
337
311
|
final_y_axis.scale_type ?? `linear`,
|
|
338
312
|
)
|
|
339
313
|
const y2_auto_range = calc_y_range(
|
|
340
314
|
y2_series,
|
|
341
|
-
|
|
315
|
+
final_y2_axis.range ?? [null, null],
|
|
342
316
|
final_y2_axis.scale_type ?? `linear`,
|
|
343
317
|
)
|
|
344
318
|
|
|
@@ -362,47 +336,21 @@
|
|
|
362
336
|
})
|
|
363
337
|
|
|
364
338
|
$effect(() => {
|
|
365
|
-
//
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
final_y_axis.range[0] ?? auto_ranges.y[0],
|
|
381
|
-
final_y_axis.range[1] ?? auto_ranges.y[1],
|
|
382
|
-
]
|
|
383
|
-
: auto_ranges.y
|
|
384
|
-
const new_y2: [number, number] = final_y2_axis.range
|
|
385
|
-
? [
|
|
386
|
-
final_y2_axis.range[0] ?? auto_ranges.y2[0],
|
|
387
|
-
final_y2_axis.range[1] ?? auto_ranges.y2[1],
|
|
388
|
-
]
|
|
389
|
-
: auto_ranges.y2
|
|
390
|
-
|
|
391
|
-
// Only update if the initial (data-driven) ranges changed, not when user pans
|
|
392
|
-
// Comparing against initial preserves user's pan/zoom state
|
|
393
|
-
const x_changed = new_x[0] !== ranges.initial.x[0] ||
|
|
394
|
-
new_x[1] !== ranges.initial.x[1]
|
|
395
|
-
const x2_changed = new_x2[0] !== ranges.initial.x2[0] ||
|
|
396
|
-
new_x2[1] !== ranges.initial.x2[1]
|
|
397
|
-
const y_changed = new_y[0] !== ranges.initial.y[0] ||
|
|
398
|
-
new_y[1] !== ranges.initial.y[1]
|
|
399
|
-
const y2_changed = new_y2[0] !== ranges.initial.y2[0] ||
|
|
400
|
-
new_y2[1] !== ranges.initial.y2[1]
|
|
401
|
-
|
|
402
|
-
if (x_changed) [ranges.initial.x, ranges.current.x] = [new_x, new_x]
|
|
403
|
-
if (x2_changed) [ranges.initial.x2, ranges.current.x2] = [new_x2, new_x2]
|
|
404
|
-
if (y_changed) [ranges.initial.y, ranges.current.y] = [new_y, new_y]
|
|
405
|
-
if (y2_changed) [ranges.initial.y2, ranges.current.y2] = [new_y2, new_y2]
|
|
339
|
+
// Supports one-sided range pinning (null bounds fall back to auto); returns null
|
|
340
|
+
// for transient non-finite bounds (skip: writing NaN breaks scales and loops here)
|
|
341
|
+
const next = resolve_axis_ranges(
|
|
342
|
+
{ x: final_x_axis, x2: final_x2_axis, y: final_y_axis, y2: final_y2_axis },
|
|
343
|
+
auto_ranges,
|
|
344
|
+
)
|
|
345
|
+
if (!next) return
|
|
346
|
+
// Update only changed axes (preserving each unchanged axis's panned current view).
|
|
347
|
+
// untrack the reads of `ranges` so the writes below can't re-trigger this effect
|
|
348
|
+
// (reading + writing the same state otherwise causes effect_update_depth_exceeded).
|
|
349
|
+
const init = untrack(() => ranges.initial)
|
|
350
|
+
if (!vec2_equal(init.x, next.x)) [ranges.initial.x, ranges.current.x] = [next.x, next.x]
|
|
351
|
+
if (!vec2_equal(init.x2, next.x2)) [ranges.initial.x2, ranges.current.x2] = [next.x2, next.x2]
|
|
352
|
+
if (!vec2_equal(init.y, next.y)) [ranges.initial.y, ranges.current.y] = [next.y, next.y]
|
|
353
|
+
if (!vec2_equal(init.y2, next.y2)) [ranges.initial.y2, ranges.current.y2] = [next.y2, next.y2]
|
|
406
354
|
})
|
|
407
355
|
|
|
408
356
|
// Layout: dynamic padding based on tick label widths
|
|
@@ -416,7 +364,7 @@
|
|
|
416
364
|
const current_ticks_y = untrack(() => ticks.y)
|
|
417
365
|
const current_ticks_y2 = untrack(() => ticks.y2)
|
|
418
366
|
|
|
419
|
-
const new_pad = width && height && current_ticks_y.length
|
|
367
|
+
const new_pad = width && height && current_ticks_y.length > 0
|
|
420
368
|
? calc_auto_padding({
|
|
421
369
|
padding,
|
|
422
370
|
default_padding,
|
|
@@ -428,7 +376,7 @@
|
|
|
428
376
|
|
|
429
377
|
// Add y2 axis label space (calc_auto_padding only accounts for tick labels)
|
|
430
378
|
if (
|
|
431
|
-
width && height && y2_series.length && current_ticks_y2.length &&
|
|
379
|
+
width && height && y2_series.length > 0 && current_ticks_y2.length > 0 &&
|
|
432
380
|
final_y2_axis.label
|
|
433
381
|
) {
|
|
434
382
|
const inside = final_y2_axis.tick?.label?.inside ?? false
|
|
@@ -444,7 +392,7 @@
|
|
|
444
392
|
|
|
445
393
|
// Add x2 axis label space (mirroring y2 logic for top padding)
|
|
446
394
|
if (
|
|
447
|
-
width && height && x2_series.length && current_ticks_x2.length &&
|
|
395
|
+
width && height && x2_series.length > 0 && current_ticks_x2.length > 0 &&
|
|
448
396
|
final_x2_axis.label
|
|
449
397
|
) {
|
|
450
398
|
const inside = final_x2_axis.tick?.label?.inside ?? false
|
|
@@ -472,7 +420,7 @@
|
|
|
472
420
|
// vertical segment (top -> baseline) so the legend can't hide inside a tall bar. Built from
|
|
473
421
|
// histogram_bins (pad-independent) + ranges so the crowding decision can't see its own reservation.
|
|
474
422
|
const obstacles_norm = $derived.by(() => {
|
|
475
|
-
if (!width || !height ||
|
|
423
|
+
if (!width || !height || histogram_bins.length === 0) return []
|
|
476
424
|
const base_w = width - base_pad.l - base_pad.r
|
|
477
425
|
const base_h = height - base_pad.t - base_pad.b
|
|
478
426
|
if (base_w <= 0 || base_h <= 0) return []
|
|
@@ -540,7 +488,7 @@
|
|
|
540
488
|
|
|
541
489
|
// Pad-independent binning (no pixel scales) so the auto-place obstacle field can reuse it
|
|
542
490
|
let histogram_bins = $derived.by(() => {
|
|
543
|
-
if (
|
|
491
|
+
if (selected_series.length === 0 || !width || !height) return []
|
|
544
492
|
const hist_generator = bin()
|
|
545
493
|
.domain([ranges.current.x[0], ranges.current.x[1]])
|
|
546
494
|
.thresholds(bins)
|
|
@@ -625,7 +573,7 @@
|
|
|
625
573
|
|
|
626
574
|
// Collect histogram bar positions for legend placement
|
|
627
575
|
let hist_points_for_placement = $derived.by(() => {
|
|
628
|
-
if (!width || !height ||
|
|
576
|
+
if (!width || !height || histogram_data.length === 0) return []
|
|
629
577
|
|
|
630
578
|
const points: { x: number; y: number }[] = []
|
|
631
579
|
|
|
@@ -666,339 +614,59 @@
|
|
|
666
614
|
return result
|
|
667
615
|
})
|
|
668
616
|
|
|
669
|
-
// Tweened legend coordinates
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
{
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
// Update legend position with stability checks
|
|
677
|
-
$effect(() => {
|
|
678
|
-
if (!width || !height || !legend_placement) return
|
|
679
|
-
|
|
680
|
-
// Track dimensions for resize detection
|
|
681
|
-
const dims_changed = dim_tracker.has_changed(width, height)
|
|
682
|
-
if (dims_changed) dim_tracker.update(width, height)
|
|
683
|
-
|
|
684
|
-
// Only update if: resize occurred, OR (not hover-locked AND (responsive OR not yet initially placed))
|
|
685
|
-
const is_responsive = legend?.responsive ?? false
|
|
686
|
-
const should_update = dims_changed || (!legend_hover.is_locked.current &&
|
|
687
|
-
(is_responsive || !has_initial_legend_placement))
|
|
688
|
-
|
|
689
|
-
if (should_update) {
|
|
690
|
-
tweened_legend_coords.set(
|
|
691
|
-
{ x: legend_placement.x, y: legend_placement.y },
|
|
692
|
-
// Skip animation on initial placement to avoid jump from (0, 0)
|
|
693
|
-
has_initial_legend_placement ? undefined : { duration: 0 },
|
|
694
|
-
)
|
|
695
|
-
// Only lock position after we have actual measured size
|
|
696
|
-
if (legend_element) {
|
|
697
|
-
has_initial_legend_placement = true
|
|
698
|
-
}
|
|
699
|
-
}
|
|
617
|
+
// Tweened legend coordinates with shared placement stability gating
|
|
618
|
+
const legend_tween = create_placed_tween({
|
|
619
|
+
placement: () => legend_placement,
|
|
620
|
+
dims: () => ({ width, height }),
|
|
621
|
+
responsive: () => legend?.responsive ?? false,
|
|
622
|
+
element: () => legend_element,
|
|
623
|
+
tween: () => legend?.tween,
|
|
700
624
|
})
|
|
701
625
|
|
|
702
|
-
//
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
const end_x2 = scales.x2.invert(drag_state.current.x)
|
|
709
|
-
const start_y = scales.y.invert(drag_state.start.y)
|
|
710
|
-
const end_y = scales.y.invert(drag_state.current.y)
|
|
711
|
-
const start_y2 = scales.y2.invert(drag_state.start.y)
|
|
712
|
-
const end_y2 = scales.y2.invert(drag_state.current.y)
|
|
713
|
-
|
|
714
|
-
if (typeof start_x === `number` && typeof end_x === `number`) {
|
|
715
|
-
const dx = Math.abs(drag_state.start.x - drag_state.current.x)
|
|
716
|
-
const dy = Math.abs(drag_state.start.y - drag_state.current.y)
|
|
717
|
-
if (dx > 5 && dy > 5) {
|
|
718
|
-
// Update axis ranges to trigger reactivity and prevent effect from overriding
|
|
719
|
-
x_axis = {
|
|
720
|
-
...x_axis,
|
|
721
|
-
range: [Math.min(start_x, end_x), Math.max(start_x, end_x)],
|
|
722
|
-
}
|
|
723
|
-
if (x2_series.length > 0) {
|
|
724
|
-
x2_axis = {
|
|
725
|
-
...x2_axis,
|
|
726
|
-
range: [Math.min(start_x2, end_x2), Math.max(start_x2, end_x2)],
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
y_axis = {
|
|
730
|
-
...y_axis,
|
|
731
|
-
range: [Math.min(start_y, end_y), Math.max(start_y, end_y)],
|
|
732
|
-
}
|
|
733
|
-
y2_axis = {
|
|
734
|
-
...y2_axis,
|
|
735
|
-
range: [Math.min(start_y2, end_y2), Math.max(start_y2, end_y2)],
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
const on_window_mouse_move = (evt: MouseEvent) => {
|
|
742
|
-
if (!drag_state.start || !drag_state.bounds) return
|
|
743
|
-
drag_state.current = {
|
|
744
|
-
x: evt.clientX - drag_state.bounds.left,
|
|
745
|
-
y: evt.clientY - drag_state.bounds.top,
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
const on_window_mouse_up = () => {
|
|
750
|
-
handle_zoom()
|
|
751
|
-
drag_state = { start: null, current: null, bounds: null }
|
|
752
|
-
window.removeEventListener(`mousemove`, on_window_mouse_move)
|
|
753
|
-
window.removeEventListener(`mouseup`, on_window_mouse_up)
|
|
754
|
-
document.body.style.cursor = `default`
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// Pan drag handlers
|
|
758
|
-
const on_pan_move = (evt: MouseEvent) => {
|
|
759
|
-
if (!pan_drag_state) return
|
|
760
|
-
const dx = evt.clientX - pan_drag_state.start.x
|
|
761
|
-
const dy = evt.clientY - pan_drag_state.start.y
|
|
762
|
-
|
|
763
|
-
// Convert pixel delta to data delta (note: drag direction is inverted for natural pan feel)
|
|
764
|
-
const plot_width = width - pad.l - pad.r
|
|
765
|
-
const plot_height = height - pad.t - pad.b
|
|
766
|
-
const sensitivity = pan?.drag_sensitivity ?? 1
|
|
767
|
-
|
|
768
|
-
const x_delta = pixels_to_data_delta(
|
|
769
|
-
-dx * sensitivity,
|
|
770
|
-
pan_drag_state.initial_x_range,
|
|
771
|
-
plot_width,
|
|
772
|
-
)
|
|
773
|
-
const x2_delta = pixels_to_data_delta(
|
|
774
|
-
-dx * sensitivity,
|
|
775
|
-
pan_drag_state.initial_x2_range,
|
|
776
|
-
plot_width,
|
|
777
|
-
)
|
|
778
|
-
const y_delta = pixels_to_data_delta(
|
|
779
|
-
dy * sensitivity,
|
|
780
|
-
pan_drag_state.initial_y_range,
|
|
781
|
-
plot_height,
|
|
782
|
-
)
|
|
783
|
-
const y2_delta = pixels_to_data_delta(
|
|
784
|
-
dy * sensitivity,
|
|
785
|
-
pan_drag_state.initial_y2_range,
|
|
786
|
-
plot_height,
|
|
787
|
-
)
|
|
788
|
-
|
|
789
|
-
ranges.current.x = pan_range(pan_drag_state.initial_x_range, x_delta)
|
|
790
|
-
ranges.current.x2 = pan_range(pan_drag_state.initial_x2_range, x2_delta)
|
|
791
|
-
ranges.current.y = pan_range(pan_drag_state.initial_y_range, y_delta)
|
|
792
|
-
ranges.current.y2 = pan_range(pan_drag_state.initial_y2_range, y2_delta)
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
const on_pan_end = () => {
|
|
796
|
-
pan_drag_state = null
|
|
797
|
-
document.body.style.cursor = ``
|
|
798
|
-
window.removeEventListener(`mousemove`, on_pan_move)
|
|
799
|
-
window.removeEventListener(`mouseup`, on_pan_end)
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
function handle_mouse_down(evt: MouseEvent) {
|
|
803
|
-
const coords = get_relative_coords(evt)
|
|
804
|
-
if (!coords || !svg_element) return
|
|
805
|
-
|
|
806
|
-
// Check if pan is enabled and shift is held for pan mode
|
|
807
|
-
const pan_enabled = pan?.enabled !== false
|
|
808
|
-
if (pan_enabled && evt.shiftKey) {
|
|
809
|
-
evt.preventDefault()
|
|
810
|
-
pan_drag_state = {
|
|
811
|
-
start: { x: evt.clientX, y: evt.clientY },
|
|
812
|
-
initial_x_range: [...ranges.current.x] as [number, number],
|
|
813
|
-
initial_x2_range: [...ranges.current.x2] as [number, number],
|
|
814
|
-
initial_y_range: [...ranges.current.y] as [number, number],
|
|
815
|
-
initial_y2_range: [...ranges.current.y2] as [number, number],
|
|
816
|
-
}
|
|
817
|
-
document.body.style.cursor = `grabbing`
|
|
818
|
-
window.addEventListener(`mousemove`, on_pan_move)
|
|
819
|
-
window.addEventListener(`mouseup`, on_pan_end)
|
|
820
|
-
return
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
drag_state = {
|
|
824
|
-
start: coords,
|
|
825
|
-
current: coords,
|
|
826
|
-
bounds: svg_element.getBoundingClientRect(),
|
|
827
|
-
}
|
|
828
|
-
window.addEventListener(`mousemove`, on_window_mouse_move)
|
|
829
|
-
window.addEventListener(`mouseup`, on_window_mouse_up)
|
|
830
|
-
evt.preventDefault()
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
// Wheel handler for pan (requires focus and shift)
|
|
834
|
-
function handle_wheel(evt: WheelEvent) {
|
|
835
|
-
const pan_enabled = pan?.enabled !== false
|
|
836
|
-
// Only capture wheel when focused AND Shift is held
|
|
837
|
-
// Use shift_held state (tracked via keydown/keyup) for compatibility with synthetic events
|
|
838
|
-
if (!pan_enabled || !is_focused || !shift_held) return
|
|
839
|
-
|
|
840
|
-
evt.preventDefault()
|
|
841
|
-
|
|
626
|
+
// Shared pan/zoom/touch/drag-rect interaction controller
|
|
627
|
+
const pan_zoom = create_pan_zoom({
|
|
628
|
+
ranges: () => ranges.current,
|
|
629
|
+
scale_type: (axis) =>
|
|
630
|
+
({ x: final_x_axis, x2: final_x2_axis, y: final_y_axis, y2: final_y2_axis })[axis]
|
|
631
|
+
.scale_type,
|
|
842
632
|
// Clamp to at least 1 to avoid Infinity deltas when padding equals container size
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
ranges
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
const touch_enabled = pan?.enabled !== false && pan?.touch_enabled !== false
|
|
881
|
-
if (!touch_enabled || evt.touches.length !== 2) return
|
|
882
|
-
|
|
883
|
-
evt.preventDefault()
|
|
884
|
-
const touches = Array.from(evt.touches)
|
|
885
|
-
touch_state = {
|
|
886
|
-
start_touches: touches.map((touch) => ({ x: touch.clientX, y: touch.clientY })),
|
|
887
|
-
initial_x_range: [...ranges.current.x] as [number, number],
|
|
888
|
-
initial_x2_range: [...ranges.current.x2] as [number, number],
|
|
889
|
-
initial_y_range: [...ranges.current.y] as [number, number],
|
|
890
|
-
initial_y2_range: [...ranges.current.y2] as [number, number],
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
function handle_touch_move(evt: TouchEvent) {
|
|
895
|
-
if (!touch_state || evt.touches.length !== 2) return
|
|
896
|
-
evt.preventDefault()
|
|
897
|
-
|
|
898
|
-
const [t1, t2] = Array.from(evt.touches)
|
|
899
|
-
const [s1, s2] = touch_state.start_touches
|
|
900
|
-
|
|
901
|
-
// Calculate center movement for pan
|
|
902
|
-
const start_center = { x: (s1.x + s2.x) / 2, y: (s1.y + s2.y) / 2 }
|
|
903
|
-
const curr_center = {
|
|
904
|
-
x: (t1.clientX + t2.clientX) / 2,
|
|
905
|
-
y: (t1.clientY + t2.clientY) / 2,
|
|
906
|
-
}
|
|
907
|
-
const dx = curr_center.x - start_center.x
|
|
908
|
-
const dy = curr_center.y - start_center.y
|
|
909
|
-
|
|
910
|
-
// Calculate pinch scale (curr/start so spread = zoom out, pinch = zoom in)
|
|
911
|
-
const start_dist = Math.hypot(s2.x - s1.x, s2.y - s1.y)
|
|
912
|
-
// Guard against zero-distance pinch to avoid Infinity scale
|
|
913
|
-
if (start_dist < Number.EPSILON) return
|
|
914
|
-
const curr_dist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY)
|
|
915
|
-
const scale = curr_dist / start_dist
|
|
916
|
-
|
|
917
|
-
// Clamp to at least 1 to avoid Infinity deltas when padding equals container size
|
|
918
|
-
const plot_width = Math.max(1, width - pad.l - pad.r)
|
|
919
|
-
const plot_height = Math.max(1, height - pad.t - pad.b)
|
|
920
|
-
|
|
921
|
-
// If scale changed significantly, treat as pinch-zoom
|
|
922
|
-
// Also guard against scale being too small to avoid division by zero
|
|
923
|
-
if (Math.abs(scale - 1) > PINCH_ZOOM_THRESHOLD && scale > Number.EPSILON) {
|
|
924
|
-
// Pinch zoom centered on gesture center
|
|
925
|
-
// Divide by scale so spread (scale > 1) = smaller span (zoom in)
|
|
926
|
-
const x_span = touch_state.initial_x_range[1] - touch_state.initial_x_range[0]
|
|
927
|
-
const x2_span = touch_state.initial_x2_range[1] -
|
|
928
|
-
touch_state.initial_x2_range[0]
|
|
929
|
-
const y_span = touch_state.initial_y_range[1] - touch_state.initial_y_range[0]
|
|
930
|
-
const y2_span = touch_state.initial_y2_range[1] -
|
|
931
|
-
touch_state.initial_y2_range[0]
|
|
932
|
-
const x_center =
|
|
933
|
-
(touch_state.initial_x_range[0] + touch_state.initial_x_range[1]) / 2
|
|
934
|
-
const x2_center =
|
|
935
|
-
(touch_state.initial_x2_range[0] + touch_state.initial_x2_range[1]) / 2
|
|
936
|
-
const y_center =
|
|
937
|
-
(touch_state.initial_y_range[0] + touch_state.initial_y_range[1]) / 2
|
|
938
|
-
const y2_center =
|
|
939
|
-
(touch_state.initial_y2_range[0] + touch_state.initial_y2_range[1]) / 2
|
|
940
|
-
|
|
941
|
-
ranges.current.x = [
|
|
942
|
-
x_center - x_span / scale / 2,
|
|
943
|
-
x_center + x_span / scale / 2,
|
|
944
|
-
]
|
|
945
|
-
ranges.current.x2 = [
|
|
946
|
-
x2_center - x2_span / scale / 2,
|
|
947
|
-
x2_center + x2_span / scale / 2,
|
|
948
|
-
]
|
|
949
|
-
ranges.current.y = [
|
|
950
|
-
y_center - y_span / scale / 2,
|
|
951
|
-
y_center + y_span / scale / 2,
|
|
952
|
-
]
|
|
953
|
-
ranges.current.y2 = [
|
|
954
|
-
y2_center - y2_span / scale / 2,
|
|
955
|
-
y2_center + y2_span / scale / 2,
|
|
956
|
-
]
|
|
957
|
-
} else {
|
|
958
|
-
// Pan
|
|
959
|
-
const x_delta = pixels_to_data_delta(
|
|
960
|
-
-dx,
|
|
961
|
-
touch_state.initial_x_range,
|
|
962
|
-
plot_width,
|
|
963
|
-
)
|
|
964
|
-
const x2_delta = pixels_to_data_delta(
|
|
965
|
-
-dx,
|
|
966
|
-
touch_state.initial_x2_range,
|
|
967
|
-
plot_width,
|
|
968
|
-
)
|
|
969
|
-
const y_delta = pixels_to_data_delta(
|
|
970
|
-
dy,
|
|
971
|
-
touch_state.initial_y_range,
|
|
972
|
-
plot_height,
|
|
973
|
-
)
|
|
974
|
-
const y2_delta = pixels_to_data_delta(
|
|
975
|
-
dy,
|
|
976
|
-
touch_state.initial_y2_range,
|
|
977
|
-
plot_height,
|
|
978
|
-
)
|
|
979
|
-
ranges.current.x = pan_range(touch_state.initial_x_range, x_delta)
|
|
980
|
-
ranges.current.x2 = pan_range(touch_state.initial_x2_range, x2_delta)
|
|
981
|
-
ranges.current.y = pan_range(touch_state.initial_y_range, y_delta)
|
|
982
|
-
ranges.current.y2 = pan_range(touch_state.initial_y2_range, y2_delta)
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
function handle_touch_end() {
|
|
987
|
-
touch_state = null
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
function handle_double_click() {
|
|
991
|
-
// Reset zoom to initial ranges (undo any pan/zoom)
|
|
992
|
-
ranges.current.x = [...ranges.initial.x] as [number, number]
|
|
993
|
-
ranges.current.x2 = [...ranges.initial.x2] as [number, number]
|
|
994
|
-
ranges.current.y = [...ranges.initial.y] as [number, number]
|
|
995
|
-
ranges.current.y2 = [...ranges.initial.y2] as [number, number]
|
|
996
|
-
// Also reset axis props so future data changes recalculate auto ranges
|
|
997
|
-
x_axis = { ...x_axis, range: [null, null] }
|
|
998
|
-
x2_axis = { ...x2_axis, range: [null, null] }
|
|
999
|
-
y_axis = { ...y_axis, range: [null, null] }
|
|
1000
|
-
y2_axis = { ...y2_axis, range: [null, null] }
|
|
1001
|
-
}
|
|
633
|
+
plot_dims: () => ({
|
|
634
|
+
width: Math.max(1, width - pad.l - pad.r),
|
|
635
|
+
height: Math.max(1, height - pad.t - pad.b),
|
|
636
|
+
}),
|
|
637
|
+
pan: () => pan,
|
|
638
|
+
set_range: (axis, range) => (ranges.current[axis] = range),
|
|
639
|
+
svg: () => svg_element,
|
|
640
|
+
on_rect_zoom: (start, current) => {
|
|
641
|
+
// Update axis ranges to trigger reactivity and prevent effect from overriding
|
|
642
|
+
const next_x = invert_rect_range(scales.x, start.x, current.x)
|
|
643
|
+
if (!next_x) return
|
|
644
|
+
x_axis = { ...x_axis, range: next_x }
|
|
645
|
+
// gate x2/y2 on series presence: their scales are [0, 1] sentinels otherwise,
|
|
646
|
+
// so inverting would store a phantom range in the bindable prop
|
|
647
|
+
const next_x2 = x2_series.length > 0 ? invert_rect_range(scales.x2, start.x, current.x) : null
|
|
648
|
+
if (next_x2) x2_axis = { ...x2_axis, range: next_x2 }
|
|
649
|
+
const next_y = invert_rect_range(scales.y, start.y, current.y)
|
|
650
|
+
if (next_y) y_axis = { ...y_axis, range: next_y }
|
|
651
|
+
const next_y2 = y2_series.length > 0 ? invert_rect_range(scales.y2, start.y, current.y) : null
|
|
652
|
+
if (next_y2) y2_axis = { ...y2_axis, range: next_y2 }
|
|
653
|
+
},
|
|
654
|
+
on_reset: () => {
|
|
655
|
+
// Reset zoom to initial ranges (undo any pan/zoom)
|
|
656
|
+
ranges.current = {
|
|
657
|
+
x: [...ranges.initial.x] as Vec2,
|
|
658
|
+
x2: [...ranges.initial.x2] as Vec2,
|
|
659
|
+
y: [...ranges.initial.y] as Vec2,
|
|
660
|
+
y2: [...ranges.initial.y2] as Vec2,
|
|
661
|
+
}
|
|
662
|
+
// Also reset axis props so future data changes recalculate auto ranges
|
|
663
|
+
x_axis = { ...x_axis, range: [null, null] }
|
|
664
|
+
x2_axis = { ...x2_axis, range: [null, null] }
|
|
665
|
+
y_axis = { ...y_axis, range: [null, null] }
|
|
666
|
+
y2_axis = { ...y2_axis, range: [null, null] }
|
|
667
|
+
},
|
|
668
|
+
})
|
|
669
|
+
onDestroy(() => pan_zoom.destroy())
|
|
1002
670
|
|
|
1003
671
|
function handle_mouse_move(
|
|
1004
672
|
evt: MouseEvent,
|
|
@@ -1030,16 +698,7 @@
|
|
|
1030
698
|
on_bar_hover?.({ value, count, property, event: evt })
|
|
1031
699
|
}
|
|
1032
700
|
|
|
1033
|
-
|
|
1034
|
-
if (series_idx >= 0 && series_idx < series.length) {
|
|
1035
|
-
// Toggle series visibility
|
|
1036
|
-
series = series.map((srs: DataSeries, idx: number) => {
|
|
1037
|
-
if (idx === series_idx) return { ...srs, visible: !(srs.visible ?? true) }
|
|
1038
|
-
return srs
|
|
1039
|
-
})
|
|
1040
|
-
;(legend?.on_toggle || on_series_toggle)(series_idx)
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
701
|
+
const legend_vis = create_legend_visibility(() => series, (next) => (series = next))
|
|
1043
702
|
|
|
1044
703
|
// Set theme-aware background when entering fullscreen
|
|
1045
704
|
$effect(() => {
|
|
@@ -1067,32 +726,12 @@
|
|
|
1067
726
|
set_loading: (axis) => (axis_loading = axis),
|
|
1068
727
|
}
|
|
1069
728
|
|
|
1070
|
-
//
|
|
1071
|
-
|
|
1072
|
-
const handle_axis_change = $derived(create_axis_change_handler(
|
|
729
|
+
// Shared handler + one-shot auto-load bound to this component's state
|
|
730
|
+
const { handle_axis_change, try_auto_load } = create_axis_loader(
|
|
1073
731
|
axis_state,
|
|
1074
|
-
data_loader,
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
))
|
|
1078
|
-
|
|
1079
|
-
let auto_load_attempted = false // prevent infinite retries on failure
|
|
1080
|
-
|
|
1081
|
-
// Auto-load data if series is empty but options exist (runs once)
|
|
1082
|
-
$effect(() => {
|
|
1083
|
-
if (series.length === 0 && data_loader && !auto_load_attempted) {
|
|
1084
|
-
// Check x-axis first, then y-axis
|
|
1085
|
-
if (x_axis.options?.length) {
|
|
1086
|
-
auto_load_attempted = true
|
|
1087
|
-
const first_key = x_axis.selected_key ?? x_axis.options[0].key
|
|
1088
|
-
handle_axis_change(`x`, first_key).catch(() => {})
|
|
1089
|
-
} else if (y_axis.options?.length) {
|
|
1090
|
-
auto_load_attempted = true
|
|
1091
|
-
const first_key = y_axis.selected_key ?? y_axis.options[0].key
|
|
1092
|
-
handle_axis_change(`y`, first_key).catch(() => {})
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
})
|
|
732
|
+
() => ({ data_loader, on_axis_change, on_error }),
|
|
733
|
+
)
|
|
734
|
+
$effect(try_auto_load)
|
|
1096
735
|
</script>
|
|
1097
736
|
|
|
1098
737
|
{#snippet ref_lines_layer(lines: IndexedRefLine[])}
|
|
@@ -1129,11 +768,9 @@
|
|
|
1129
768
|
evt.preventDefault()
|
|
1130
769
|
fullscreen = false
|
|
1131
770
|
}
|
|
1132
|
-
|
|
1133
|
-
}}
|
|
1134
|
-
onkeyup={(evt) => {
|
|
1135
|
-
if (evt.key === `Shift`) shift_held = false
|
|
771
|
+
pan_zoom.on_window_key_down(evt)
|
|
1136
772
|
}}
|
|
773
|
+
onkeyup={pan_zoom.on_window_key_up}
|
|
1137
774
|
/>
|
|
1138
775
|
|
|
1139
776
|
<div
|
|
@@ -1161,34 +798,23 @@
|
|
|
1161
798
|
([final_x_axis.label, final_y_axis.label].filter(Boolean).join(` vs `) ||
|
|
1162
799
|
`Histogram`)}
|
|
1163
800
|
tabindex="0"
|
|
1164
|
-
onfocusin={() => (
|
|
1165
|
-
onfocusout={() => (
|
|
801
|
+
onfocusin={() => pan_zoom.set_focused(true)}
|
|
802
|
+
onfocusout={() => pan_zoom.set_focused(false)}
|
|
1166
803
|
onmouseenter={() => (hovered = true)}
|
|
1167
|
-
onmousedown={
|
|
804
|
+
onmousedown={pan_zoom.on_mouse_down}
|
|
1168
805
|
onmouseleave={() => {
|
|
1169
806
|
hovered = false
|
|
1170
807
|
hover_info = null
|
|
1171
808
|
on_bar_hover?.(null)
|
|
1172
809
|
}}
|
|
1173
|
-
ondblclick={
|
|
1174
|
-
onwheel={
|
|
1175
|
-
ontouchstart={
|
|
1176
|
-
ontouchmove={
|
|
1177
|
-
ontouchend={
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
? `grab`
|
|
1182
|
-
: `crosshair`}
|
|
1183
|
-
onkeydown={(event) => {
|
|
1184
|
-
if (event.key === `Escape` && drag_state.start) {
|
|
1185
|
-
drag_state = { start: null, current: null, bounds: null }
|
|
1186
|
-
}
|
|
1187
|
-
if ([`Enter`, ` `].includes(event.key)) {
|
|
1188
|
-
event.preventDefault()
|
|
1189
|
-
handle_double_click()
|
|
1190
|
-
}
|
|
1191
|
-
}}
|
|
810
|
+
ondblclick={pan_zoom.reset_view}
|
|
811
|
+
onwheel={pan_zoom.on_wheel}
|
|
812
|
+
ontouchstart={pan_zoom.on_touch_start}
|
|
813
|
+
ontouchmove={pan_zoom.on_touch_move}
|
|
814
|
+
ontouchend={pan_zoom.on_touch_end}
|
|
815
|
+
ontouchcancel={pan_zoom.on_touch_end}
|
|
816
|
+
style:cursor={pan_zoom.cursor}
|
|
817
|
+
onkeydown={pan_zoom.on_key_down}
|
|
1192
818
|
>
|
|
1193
819
|
<!-- Define clip path for chart area -->
|
|
1194
820
|
<defs>
|
|
@@ -1205,7 +831,7 @@
|
|
|
1205
831
|
<!-- Reference lines: below grid (must render first to appear behind grid) -->
|
|
1206
832
|
{@render ref_lines_layer(ref_lines_by_z.below_grid)}
|
|
1207
833
|
|
|
1208
|
-
<ZoomRect start={
|
|
834
|
+
<ZoomRect start={pan_zoom.drag_start} current={pan_zoom.drag_current} />
|
|
1209
835
|
|
|
1210
836
|
<ZeroLines
|
|
1211
837
|
{display}
|
|
@@ -1240,6 +866,7 @@
|
|
|
1240
866
|
ticks={ticks.x as number[]}
|
|
1241
867
|
place={scales.x}
|
|
1242
868
|
axis={final_x_axis}
|
|
869
|
+
domain={ranges.current.x as Vec2}
|
|
1243
870
|
{pad}
|
|
1244
871
|
{width}
|
|
1245
872
|
{height}
|
|
@@ -1258,6 +885,7 @@
|
|
|
1258
885
|
ticks={ticks.x2 as number[]}
|
|
1259
886
|
place={scales.x2}
|
|
1260
887
|
axis={final_x2_axis}
|
|
888
|
+
domain={ranges.current.x2 as Vec2}
|
|
1261
889
|
{pad}
|
|
1262
890
|
{width}
|
|
1263
891
|
{height}
|
|
@@ -1276,6 +904,7 @@
|
|
|
1276
904
|
ticks={ticks.y as number[]}
|
|
1277
905
|
place={scales.y}
|
|
1278
906
|
axis={final_y_axis}
|
|
907
|
+
domain={ranges.current.y as Vec2}
|
|
1279
908
|
{pad}
|
|
1280
909
|
{width}
|
|
1281
910
|
{height}
|
|
@@ -1293,21 +922,18 @@
|
|
|
1293
922
|
|
|
1294
923
|
<!-- Y2-axis (Right) -->
|
|
1295
924
|
{#if y2_series.length > 0}
|
|
1296
|
-
{@const y2_inside = final_y2_axis.tick?.label?.inside ?? false}
|
|
1297
|
-
{@const y2_tick_shift = y2_inside ? 0 : (final_y2_axis.tick?.label?.shift?.x ?? 0) + 8}
|
|
1298
|
-
{@const y2_tick_width = y2_inside ? 0 : tick_label_widths.y2_max}
|
|
1299
925
|
<PlotAxis
|
|
1300
926
|
side="y2"
|
|
1301
927
|
ticks={ticks.y2 as number[]}
|
|
1302
928
|
place={scales.y2}
|
|
1303
929
|
axis={final_y2_axis}
|
|
930
|
+
domain={ranges.current.y2 as Vec2}
|
|
1304
931
|
{pad}
|
|
1305
932
|
{width}
|
|
1306
933
|
{height}
|
|
1307
934
|
show_grid={display.y2_grid}
|
|
1308
935
|
tick_label={(tick) => get_tick_label(tick, final_y2_axis.ticks)}
|
|
1309
|
-
label_x={width
|
|
1310
|
-
(final_y2_axis.label_shift?.x ?? 0)}
|
|
936
|
+
label_x={y2_axis_label_x(final_y2_axis, width, pad.r, tick_label_widths.y2_max)}
|
|
1311
937
|
label_y={pad.t + (height - pad.t - pad.b) / 2 + (final_y2_axis.label_shift?.y ?? 0)}
|
|
1312
938
|
axis_loading={axis_loading === `y2`}
|
|
1313
939
|
on_axis_change={(key) => handle_axis_change(`y2`, key)}
|
|
@@ -1323,6 +949,7 @@
|
|
|
1323
949
|
<g
|
|
1324
950
|
class="histogram-series"
|
|
1325
951
|
data-series-idx={series_idx}
|
|
952
|
+
clip-path="url(#{clip_path_id})"
|
|
1326
953
|
opacity={hovered_legend_series_idx !== null &&
|
|
1327
954
|
hovered_legend_series_idx !== series_idx
|
|
1328
955
|
? 0.25
|
|
@@ -1389,20 +1016,12 @@
|
|
|
1389
1016
|
{@const { value, count, property, active_y_axis, active_x_axis } = hover_info}
|
|
1390
1017
|
{@const tooltip_x = (active_x_axis === `x2` ? scales.x2 : scales.x)(value)}
|
|
1391
1018
|
{@const tooltip_y = (active_y_axis === `y2` ? scales.y2 : scales.y)(count)}
|
|
1392
|
-
{@const tooltip_pos = constrain_tooltip_position(
|
|
1393
|
-
tooltip_x,
|
|
1394
|
-
tooltip_y,
|
|
1395
|
-
tooltip_el?.offsetWidth ?? 120,
|
|
1396
|
-
tooltip_el?.offsetHeight ?? (mode === `overlay` ? 60 : 40),
|
|
1397
|
-
width,
|
|
1398
|
-
height,
|
|
1399
|
-
{ offset_x: 5, offset_y: -10 },
|
|
1400
|
-
)}
|
|
1401
1019
|
<PlotTooltip
|
|
1402
|
-
x={
|
|
1403
|
-
y={
|
|
1404
|
-
offset={{ x:
|
|
1405
|
-
|
|
1020
|
+
x={tooltip_x}
|
|
1021
|
+
y={tooltip_y}
|
|
1022
|
+
offset={{ x: 5, y: -10 }}
|
|
1023
|
+
constrain_to={{ width, height }}
|
|
1024
|
+
fallback_size={{ width: 120, height: mode === `overlay` ? 60 : 40 }}
|
|
1406
1025
|
>
|
|
1407
1026
|
{#if tooltip}
|
|
1408
1027
|
{@render tooltip({ ...hover_info, fullscreen })}
|
|
@@ -1447,31 +1066,33 @@
|
|
|
1447
1066
|
{/if}
|
|
1448
1067
|
|
|
1449
1068
|
{#if show_legend && legend != null && series.length > 1}
|
|
1450
|
-
{@const
|
|
1451
|
-
|
|
1452
|
-
:
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
{
|
|
1456
|
-
|
|
1457
|
-
: legend_placement
|
|
1458
|
-
? tweened_legend_coords.current.y
|
|
1459
|
-
: pad.t + 10}
|
|
1069
|
+
{@const legend_pos = placed_coords(
|
|
1070
|
+
legend_auto_outside,
|
|
1071
|
+
{ x: legend_outside_x, y: legend_outside_y },
|
|
1072
|
+
legend_placement,
|
|
1073
|
+
legend_tween.coords.current,
|
|
1074
|
+
{ x: pad.l + 10, y: pad.t + 10 },
|
|
1075
|
+
)}
|
|
1460
1076
|
<PlotLegend
|
|
1461
1077
|
bind:root_element={legend_element}
|
|
1462
1078
|
{...legend}
|
|
1463
1079
|
series_data={legend_data}
|
|
1464
|
-
on_toggle={legend?.on_toggle
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
(
|
|
1468
|
-
|
|
1080
|
+
on_toggle={legend?.on_toggle ?? ((series_idx: number) => {
|
|
1081
|
+
if (series_idx < 0 || series_idx >= series.length) return
|
|
1082
|
+
legend_vis.on_toggle(series_idx)
|
|
1083
|
+
on_series_toggle(series_idx)
|
|
1084
|
+
})}
|
|
1085
|
+
on_double_click={legend?.on_double_click ?? legend_vis.on_double_click}
|
|
1086
|
+
on_hover_change={legend_tween.set_locked}
|
|
1087
|
+
on_item_hover={(item) =>
|
|
1088
|
+
(hovered_legend_series_idx = item != null && item.series_idx >= 0
|
|
1089
|
+
? item.series_idx
|
|
1469
1090
|
: null)}
|
|
1470
1091
|
active_series_idx={hover_info?.series_idx ?? hovered_legend_series_idx}
|
|
1471
1092
|
style={`
|
|
1472
1093
|
position: absolute;
|
|
1473
|
-
left: ${
|
|
1474
|
-
top: ${
|
|
1094
|
+
left: ${legend_pos.x}px;
|
|
1095
|
+
top: ${legend_pos.y}px;
|
|
1475
1096
|
pointer-events: auto;
|
|
1476
1097
|
${legend?.style || ``}
|
|
1477
1098
|
`}
|
|
@@ -1509,8 +1130,10 @@
|
|
|
1509
1130
|
background: var(--histogram-fullscreen-bg, var(--histogram-bg, var(--plot-bg)));
|
|
1510
1131
|
max-height: none !important;
|
|
1511
1132
|
overflow: hidden;
|
|
1512
|
-
/*
|
|
1513
|
-
|
|
1133
|
+
/* border-top (not padding-top): bind:clientHeight includes padding but excludes
|
|
1134
|
+
borders - padding made the chart overflow + clip its bottom 2em (x-axis title) */
|
|
1135
|
+
border-top: var(--plot-fullscreen-padding-top, 2em) solid
|
|
1136
|
+
var(--histogram-fullscreen-bg, var(--histogram-bg, var(--plot-bg, transparent)));
|
|
1514
1137
|
box-sizing: border-box;
|
|
1515
1138
|
}
|
|
1516
1139
|
.header-controls {
|