matterviz 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EmptyState.svelte +10 -4
- package/dist/FilePicker.svelte +12 -14
- package/dist/Icon.svelte +7 -4
- package/dist/MillerIndexInput.svelte +2 -2
- package/dist/app.css +53 -0
- package/dist/brillouin/BrillouinZone.svelte +75 -85
- package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
- package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
- package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
- package/dist/brillouin/BrillouinZoneScene.svelte +26 -39
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +62 -74
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +511 -547
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/async-compute.svelte.js +1 -1
- package/dist/chempot-diagram/controls-state.svelte.js +1 -1
- package/dist/colors/index.d.ts +0 -4
- package/dist/colors/index.js +19 -20
- package/dist/composition/BarChart.svelte +37 -31
- package/dist/composition/BubbleChart.svelte +17 -17
- package/dist/composition/Composition.svelte +7 -11
- package/dist/composition/Formula.svelte +18 -25
- package/dist/composition/FormulaFilter.svelte +92 -95
- package/dist/composition/PieChart.svelte +55 -41
- package/dist/composition/format.js +1 -1
- package/dist/composition/index.d.ts +2 -0
- package/dist/composition/index.js +14 -0
- package/dist/composition/parse.d.ts +2 -2
- package/dist/composition/parse.js +11 -10
- package/dist/constants.js +11 -9
- package/dist/convex-hull/ConvexHull.svelte +12 -15
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +93 -92
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +109 -140
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +75 -94
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
- package/dist/convex-hull/ConvexHullControls.svelte +46 -48
- package/dist/convex-hull/ConvexHullStats.svelte +193 -195
- package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
- package/dist/convex-hull/GasPressureControls.svelte +5 -12
- package/dist/convex-hull/StructurePopup.svelte +17 -21
- package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
- package/dist/convex-hull/TemperatureSlider.svelte +4 -10
- package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
- package/dist/convex-hull/helpers.d.ts +8 -10
- package/dist/convex-hull/helpers.js +36 -36
- package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
- package/dist/convex-hull/thermodynamics.js +18 -17
- package/dist/coordination/CoordinationBarPlot.svelte +38 -33
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/coordination/calc-coordination.d.ts +1 -1
- package/dist/coordination/calc-coordination.js +28 -25
- package/dist/element/BohrAtom.svelte +5 -8
- package/dist/element/ElementHeading.svelte +4 -1
- package/dist/element/ElementPhoto.svelte +11 -9
- package/dist/element/ElementStats.svelte +12 -10
- package/dist/element/ElementTile.svelte +24 -29
- package/dist/element/Nucleus.svelte +4 -2
- package/dist/element/data.d.ts +1 -2
- package/dist/element/helpers.d.ts +4 -0
- package/dist/element/helpers.js +18 -0
- package/dist/element/index.d.ts +1 -4
- package/dist/element/index.js +3 -18
- package/dist/feedback/DragOverlay.svelte +5 -5
- package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
- package/dist/feedback/StatusMessage.svelte +7 -4
- package/dist/fermi-surface/FermiSlice.svelte +21 -18
- package/dist/fermi-surface/FermiSurface.svelte +14 -22
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -7
- package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +37 -64
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
- package/dist/fermi-surface/compute.js +3 -3
- package/dist/fermi-surface/parse.js +22 -24
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +109 -148
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
- package/dist/heatmap-matrix/index.d.ts +5 -0
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +4 -0
- package/dist/io/ExportPane.svelte +10 -6
- package/dist/io/decompress.d.ts +2 -1
- package/dist/io/decompress.js +22 -35
- package/dist/io/export.d.ts +4 -0
- package/dist/io/export.js +5 -1
- package/dist/io/fetch.d.ts +0 -3
- package/dist/io/fetch.js +0 -11
- package/dist/io/index.d.ts +0 -1
- package/dist/io/index.js +2 -9
- package/dist/io/is-binary.d.ts +9 -0
- package/dist/io/is-binary.js +45 -1
- package/dist/io/url-drop.js +13 -25
- package/dist/isosurface/Isosurface.svelte +17 -23
- package/dist/isosurface/IsosurfaceControls.svelte +37 -42
- package/dist/isosurface/parse-vaspwave.d.ts +3 -0
- package/dist/isosurface/parse-vaspwave.js +138 -0
- package/dist/isosurface/parse.js +6 -6
- package/dist/labels.d.ts +6 -2
- package/dist/labels.js +43 -13
- package/dist/layout/FullscreenButton.svelte +2 -1
- package/dist/layout/FullscreenToggle.svelte +10 -4
- package/dist/layout/InfoCard.svelte +7 -18
- package/dist/layout/InfoTag.svelte +1 -3
- package/dist/layout/NumberRangeInput.svelte +46 -0
- package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
- package/dist/layout/PropertyFilter.svelte +2 -6
- package/dist/layout/SettingsSection.svelte +21 -17
- package/dist/layout/SubpageGrid.svelte +3 -1
- package/dist/layout/ViewerChrome.svelte +9 -10
- package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
- package/dist/layout/fullscreen.js +3 -5
- package/dist/layout/fullscreen.svelte.js +1 -2
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/layout/json-tree/JsonNode.svelte +8 -11
- package/dist/layout/json-tree/JsonTree.svelte +53 -77
- package/dist/layout/json-tree/JsonValue.svelte +7 -15
- package/dist/layout/json-tree/utils.js +14 -23
- package/dist/math.d.ts +2 -0
- package/dist/math.js +19 -0
- package/dist/overlays/ContextMenu.svelte +4 -2
- package/dist/overlays/CopyButton.svelte +11 -5
- package/dist/overlays/DragControlTab.svelte +6 -1
- package/dist/overlays/DraggablePane.svelte +81 -26
- package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
- package/dist/overlays/GlassChip.svelte +30 -0
- package/dist/overlays/GlassChip.svelte.d.ts +8 -0
- package/dist/overlays/InfoPaneCards.svelte +11 -23
- package/dist/overlays/index.d.ts +7 -0
- package/dist/overlays/index.js +26 -0
- package/dist/overlays/portal.d.ts +2 -0
- package/dist/overlays/portal.js +14 -0
- package/dist/periodic-table/PeriodicTable.svelte +113 -145
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
- package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
- package/dist/periodic-table/TableInset.svelte +9 -4
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
- package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
- package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
- package/dist/phase-diagram/build-diagram.js +3 -3
- package/dist/phase-diagram/diagram-input.d.ts +1 -2
- package/dist/phase-diagram/parse.js +15 -15
- package/dist/phase-diagram/svg-to-diagram.js +21 -15
- package/dist/phase-diagram/utils.js +2 -3
- package/dist/plot/bar/BarPlot.svelte +430 -391
- package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
- package/dist/plot/bar/BarPlotControls.svelte +1 -3
- package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
- package/dist/plot/bar/SpacegroupBarPlot.svelte +29 -36
- package/dist/plot/bar/data.d.ts +5 -4
- package/dist/plot/bar/data.js +2 -1
- package/dist/plot/box/BoxPlot.svelte +301 -209
- package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
- package/dist/plot/box/Violin.svelte.d.ts +1 -0
- package/dist/plot/box/box-plot.js +1 -1
- package/dist/plot/core/auto-place.js +1 -1
- package/dist/plot/core/axis-utils.d.ts +12 -7
- package/dist/plot/core/axis-utils.js +48 -48
- package/dist/plot/core/components/AxisLabel.svelte +82 -20
- package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
- package/dist/plot/core/components/ColorBar.svelte +101 -106
- package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
- package/dist/plot/core/components/FillArea.svelte +10 -17
- package/dist/plot/core/components/HierarchyControls.svelte +249 -0
- package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
- package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
- package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/core/components/Line.svelte +18 -9
- package/dist/plot/core/components/Line.svelte.d.ts +2 -0
- package/dist/plot/core/components/PlotAxis.svelte +40 -17
- package/dist/plot/core/components/PlotControls.svelte +65 -41
- package/dist/plot/core/components/PlotLegend.svelte +31 -35
- package/dist/plot/core/components/PlotMarginals.svelte +616 -0
- package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
- package/dist/plot/core/components/PlotTooltip.svelte +1 -1
- package/dist/plot/core/components/PortalSelect.svelte +4 -8
- package/dist/plot/core/components/ReferenceLine.svelte +27 -24
- package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
- package/dist/plot/core/components/ReferencePlane.svelte +7 -8
- package/dist/plot/core/components/ZeroLines.svelte +4 -8
- package/dist/plot/core/components/ZoomRect.svelte +1 -2
- package/dist/plot/core/components/index.d.ts +1 -0
- package/dist/plot/core/components/index.js +1 -0
- package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
- package/dist/plot/core/data-cleaning-signal.js +467 -0
- package/dist/plot/core/data-cleaning.d.ts +2 -42
- package/dist/plot/core/data-cleaning.js +27 -474
- package/dist/plot/core/data-transform.js +9 -5
- package/dist/plot/core/fill-utils.d.ts +3 -1
- package/dist/plot/core/fill-utils.js +28 -6
- package/dist/plot/core/index.d.ts +1 -0
- package/dist/plot/core/index.js +1 -0
- package/dist/plot/core/interactions.js +0 -2
- package/dist/plot/core/layout.d.ts +3 -1
- package/dist/plot/core/layout.js +22 -13
- package/dist/plot/core/marginals.d.ts +170 -0
- package/dist/plot/core/marginals.js +436 -0
- package/dist/plot/core/reference-line.js +1 -1
- package/dist/plot/core/scales.d.ts +23 -0
- package/dist/plot/core/scales.js +39 -13
- package/dist/plot/core/types/fills.d.ts +101 -0
- package/dist/plot/core/types/fills.js +15 -0
- package/dist/plot/core/types/plot-3d.d.ts +87 -0
- package/dist/plot/core/types/plot-3d.js +4 -0
- package/dist/plot/core/types/reference-lines.d.ts +140 -0
- package/dist/plot/core/types/reference-lines.js +9 -0
- package/dist/plot/core/types.d.ts +29 -324
- package/dist/plot/core/types.js +23 -20
- package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
- package/dist/plot/core/utils/hierarchy-chart.js +179 -0
- package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
- package/dist/plot/core/utils/hierarchy-labels.js +99 -0
- package/dist/plot/core/utils/label-placement.js +2 -2
- package/dist/plot/histogram/Histogram.svelte +304 -325
- package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
- package/dist/plot/histogram/HistogramControls.svelte +30 -28
- package/dist/plot/histogram/histogram.d.ts +31 -0
- package/dist/plot/histogram/histogram.js +70 -0
- package/dist/plot/histogram/index.d.ts +1 -0
- package/dist/plot/histogram/index.js +1 -0
- package/dist/plot/index.d.ts +1 -0
- package/dist/plot/index.js +1 -0
- package/dist/plot/sankey/Sankey.svelte +78 -69
- package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
- package/dist/plot/sankey/SankeyControls.svelte +22 -16
- package/dist/plot/scatter/BinnedScatterPlot.svelte +263 -109
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
- package/dist/plot/scatter/ElementScatter.svelte +4 -1
- package/dist/plot/scatter/ScatterPlot.svelte +477 -385
- package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
- package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
- package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/scatter/ScatterPoint.svelte +16 -9
- package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
- package/dist/plot/scatter/binned-scatter-types.js +6 -1
- package/dist/plot/scatter/scatter-data.d.ts +1 -1
- package/dist/plot/scatter/scatter-data.js +8 -7
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
- package/dist/plot/sunburst/Sunburst.svelte +251 -329
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
- package/dist/plot/sunburst/index.d.ts +1 -1
- package/dist/plot/sunburst/index.js +2 -1
- package/dist/plot/sunburst/render.d.ts +2 -2
- package/dist/plot/sunburst/render.js +47 -22
- package/dist/plot/sunburst/sunburst.d.ts +5 -1
- package/dist/plot/sunburst/sunburst.js +10 -3
- package/dist/plot/treemap/Treemap.svelte +907 -0
- package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
- package/dist/plot/treemap/index.d.ts +3 -0
- package/dist/plot/treemap/index.js +4 -0
- package/dist/plot/treemap/treemap.d.ts +26 -0
- package/dist/plot/treemap/treemap.js +99 -0
- package/dist/rdf/RdfPlot.svelte +22 -26
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/calc-rdf.js +4 -8
- package/dist/sanitize.js +1 -1
- package/dist/scene/bind-renderer.svelte.js +14 -6
- package/dist/settings.d.ts +19 -9
- package/dist/settings.js +77 -50
- package/dist/spectral/Bands.svelte +223 -230
- package/dist/spectral/BandsAndDos.svelte +11 -9
- package/dist/spectral/BrillouinBandsDos.svelte +19 -27
- package/dist/spectral/Dos.svelte +70 -73
- package/dist/spectral/helpers.d.ts +3 -3
- package/dist/spectral/helpers.js +25 -35
- package/dist/state.svelte.js +5 -18
- package/dist/structure/Arrow.svelte +5 -18
- package/dist/structure/ArrowInstances.svelte +160 -0
- package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
- package/dist/structure/AtomLegend.svelte +115 -75
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/Bond.svelte +31 -23
- package/dist/structure/CanvasTooltip.svelte +15 -3
- package/dist/structure/CellSelect.svelte +11 -26
- package/dist/structure/Cylinder.svelte +24 -40
- package/dist/structure/InstancedAtoms.svelte +114 -0
- package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
- package/dist/structure/Lattice.svelte +85 -149
- package/dist/structure/SiteLabels.svelte +122 -0
- package/dist/structure/SiteLabels.svelte.d.ts +18 -0
- package/dist/structure/Structure.svelte +473 -419
- package/dist/structure/Structure.svelte.d.ts +4 -2
- package/dist/structure/StructureCarousel.svelte +630 -0
- package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
- package/dist/structure/StructureControls.svelte +157 -399
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureExportPane.svelte +17 -21
- package/dist/structure/StructureInfoPane.svelte +72 -66
- package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
- package/dist/structure/StructureScene.svelte +467 -476
- package/dist/structure/StructureScene.svelte.d.ts +3 -1
- package/dist/structure/StructureViewport.svelte +386 -0
- package/dist/structure/StructureViewport.svelte.d.ts +63 -0
- package/dist/structure/atom-label-placement.d.ts +16 -12
- package/dist/structure/atom-label-placement.js +70 -37
- package/dist/structure/atom-properties.d.ts +2 -0
- package/dist/structure/atom-properties.js +104 -38
- package/dist/structure/bonding.d.ts +10 -3
- package/dist/structure/bonding.js +84 -28
- package/dist/structure/edit-history.d.ts +6 -0
- package/dist/structure/edit-history.js +27 -0
- package/dist/structure/export.d.ts +1 -0
- package/dist/structure/export.js +39 -31
- package/dist/structure/format-detect.d.ts +1 -0
- package/dist/structure/format-detect.js +22 -0
- package/dist/structure/geometry.d.ts +9 -0
- package/dist/structure/geometry.js +27 -0
- package/dist/structure/index.d.ts +16 -1
- package/dist/structure/index.js +13 -2
- package/dist/structure/measure.d.ts +1 -1
- package/dist/structure/measure.js +6 -12
- package/dist/structure/parse.d.ts +2 -1
- package/dist/structure/parse.js +243 -222
- package/dist/structure/partial-occupancy.js +4 -2
- package/dist/structure/pbc.js +78 -98
- package/dist/structure/polyhedra.d.ts +0 -1
- package/dist/structure/polyhedra.js +3 -18
- package/dist/structure/supercell.d.ts +1 -2
- package/dist/structure/supercell.js +7 -13
- package/dist/symmetry/SymmetryElements.svelte +11 -15
- package/dist/symmetry/SymmetryStats.svelte +56 -68
- package/dist/symmetry/WyckoffTable.svelte +5 -24
- package/dist/symmetry/cell-transform.js +1 -0
- package/dist/symmetry/index.d.ts +1 -0
- package/dist/symmetry/index.js +8 -2
- package/dist/symmetry/spacegroups.js +3 -2
- package/dist/table/HeatmapTable.svelte +1102 -365
- package/dist/table/HeatmapTable.svelte.d.ts +12 -2
- package/dist/table/ToggleMenu.svelte +5 -12
- package/dist/table/index.d.ts +21 -6
- package/dist/table/index.js +34 -21
- package/dist/theme/ThemeControl.svelte +16 -8
- package/dist/theme/index.d.ts +1 -5
- package/dist/theme/index.js +4 -10
- package/dist/theme/themes.mjs +14 -7
- package/dist/tooltip/KCoords.svelte +4 -1
- package/dist/tooltip/TooltipContent.svelte +2 -5
- package/dist/trajectory/Trajectory.svelte +515 -308
- package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
- package/dist/trajectory/TrajectoryError.svelte +11 -8
- package/dist/trajectory/TrajectoryExportPane.svelte +14 -31
- package/dist/trajectory/TrajectoryInfoPane.svelte +85 -97
- package/dist/trajectory/extract.js +56 -34
- package/dist/trajectory/format-detect.js +11 -9
- package/dist/trajectory/frame-reader.d.ts +2 -0
- package/dist/trajectory/frame-reader.js +33 -29
- package/dist/trajectory/helpers.d.ts +2 -0
- package/dist/trajectory/helpers.js +18 -7
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +3 -0
- package/dist/trajectory/parse/h5-utils.d.ts +13 -0
- package/dist/trajectory/parse/h5-utils.js +109 -0
- package/dist/trajectory/parse/hdf5.d.ts +1 -1
- package/dist/trajectory/parse/hdf5.js +116 -106
- package/dist/trajectory/parse/index.d.ts +2 -3
- package/dist/trajectory/parse/index.js +17 -20
- package/dist/trajectory/parse/lammps.js +8 -12
- package/dist/trajectory/parse/vasp.js +10 -7
- package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
- package/dist/trajectory/parse/vaspout-electronic.js +207 -0
- package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
- package/dist/trajectory/parse/vaspout-h5.js +284 -0
- package/dist/trajectory/parse/xyz.js +11 -7
- package/dist/trajectory/plotting.d.ts +8 -9
- package/dist/trajectory/plotting.js +99 -27
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +7 -0
- package/dist/xrd/XrdPlot.svelte +47 -61
- package/dist/xrd/broadening.js +2 -1
- package/dist/xrd/calc-xrd.js +2 -4
- package/dist/xrd/parse.d.ts +0 -1
- package/dist/xrd/parse.js +56 -73
- package/package.json +61 -33
- package/dist/api/mp.d.ts +0 -6
- package/dist/api/mp.js +0 -22
- package/dist/plot/sunburst/SunburstControls.svelte +0 -200
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
generics="Metadata extends Record<string, unknown> = Record<string, unknown>"
|
|
4
4
|
>
|
|
5
5
|
import type { D3InterpolateName } from '../../colors'
|
|
6
|
-
import {
|
|
6
|
+
import { format_value_or_num } from '../../labels'
|
|
7
7
|
import { sanitize_html } from '../../sanitize'
|
|
8
8
|
import { FullscreenToggle, set_fullscreen_bg } from '../../layout'
|
|
9
9
|
import type { Point2D, Vec2 } from '../../math'
|
|
@@ -33,11 +33,19 @@
|
|
|
33
33
|
compute_element_placement,
|
|
34
34
|
PlotAxis,
|
|
35
35
|
PlotLegend,
|
|
36
|
+
PlotMarginals,
|
|
36
37
|
ReferenceLine,
|
|
37
38
|
ScatterPoint,
|
|
38
39
|
} from '..'
|
|
39
|
-
import type {
|
|
40
|
-
import {
|
|
40
|
+
import type { MarginalSeriesInput, MarginalsProp } from '../core/marginals'
|
|
41
|
+
import {
|
|
42
|
+
add_sides,
|
|
43
|
+
marginal_axis,
|
|
44
|
+
marginal_axis_presence,
|
|
45
|
+
normalize_marginals,
|
|
46
|
+
reserve_marginal_pad,
|
|
47
|
+
} from '../core/marginals'
|
|
48
|
+
import { type AxisChangeState, create_axis_loader } from '../core/axis-utils'
|
|
41
49
|
import { create_placed_tween } from '../core/placed-tween.svelte'
|
|
42
50
|
import { create_pan_zoom } from '../core/pan-zoom.svelte'
|
|
43
51
|
import { create_legend_visibility } from '../core/utils/series-visibility'
|
|
@@ -49,13 +57,13 @@
|
|
|
49
57
|
import type { IndexedRefLine } from '../core/reference-line'
|
|
50
58
|
import { group_ref_lines_by_z, index_ref_lines } from '../core/reference-line'
|
|
51
59
|
import {
|
|
60
|
+
create_axis_scales,
|
|
52
61
|
create_color_scale,
|
|
53
|
-
create_scale,
|
|
54
62
|
create_size_scale,
|
|
55
63
|
generate_ticks,
|
|
56
64
|
get_tick_label,
|
|
57
65
|
} from '../core/scales'
|
|
58
|
-
import { DEFAULT_MARKERS } from '../core/types'
|
|
66
|
+
import { DEFAULT_MARKERS, SCALE_DEFAULTS } from '../core/types'
|
|
59
67
|
import { DEFAULTS } from '../../settings'
|
|
60
68
|
import { extent } from 'd3-array'
|
|
61
69
|
import type { Snippet } from 'svelte'
|
|
@@ -71,7 +79,9 @@
|
|
|
71
79
|
placed_coords,
|
|
72
80
|
} from '../core/auto-place'
|
|
73
81
|
import {
|
|
82
|
+
AXIS_TITLE_OFFSET,
|
|
74
83
|
calc_auto_padding,
|
|
84
|
+
DEFAULT_PLOT_PADDING,
|
|
75
85
|
filter_padding,
|
|
76
86
|
LABEL_GAP_DEFAULT,
|
|
77
87
|
y2_axis_label_x,
|
|
@@ -108,8 +118,8 @@
|
|
|
108
118
|
y_axis = $bindable({}),
|
|
109
119
|
y2_axis: y2_axis_prop = $bindable({}),
|
|
110
120
|
display = $bindable(DEFAULTS.bar.display),
|
|
111
|
-
range_padding = 0
|
|
112
|
-
padding =
|
|
121
|
+
range_padding = 0,
|
|
122
|
+
padding = DEFAULT_PLOT_PADDING,
|
|
113
123
|
legend = {},
|
|
114
124
|
show_legend,
|
|
115
125
|
bar = {},
|
|
@@ -121,12 +131,8 @@
|
|
|
121
131
|
on_bar_click,
|
|
122
132
|
on_bar_hover,
|
|
123
133
|
// Line marker props (matching ScatterPlot)
|
|
124
|
-
color_scale =
|
|
125
|
-
|
|
126
|
-
scheme: `interpolateViridis`,
|
|
127
|
-
value_range: undefined,
|
|
128
|
-
},
|
|
129
|
-
size_scale = { type: `linear`, radius_range: [2, 10], value_range: undefined },
|
|
134
|
+
color_scale = SCALE_DEFAULTS.color,
|
|
135
|
+
size_scale = SCALE_DEFAULTS.size,
|
|
130
136
|
point_tween,
|
|
131
137
|
on_point_click,
|
|
132
138
|
on_point_hover,
|
|
@@ -146,61 +152,65 @@
|
|
|
146
152
|
on_axis_change,
|
|
147
153
|
on_error,
|
|
148
154
|
pan = {},
|
|
155
|
+
marginals = false,
|
|
149
156
|
...rest
|
|
150
|
-
}: HTMLAttributes<HTMLDivElement> &
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
[
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
157
|
+
}: HTMLAttributes<HTMLDivElement> &
|
|
158
|
+
BasePlotProps &
|
|
159
|
+
PlotConfig & {
|
|
160
|
+
series?: BarSeries<Metadata>[]
|
|
161
|
+
// Component-specific props
|
|
162
|
+
orientation?: Orientation
|
|
163
|
+
mode?: BarMode
|
|
164
|
+
legend?: LegendConfig | null
|
|
165
|
+
show_legend?: boolean
|
|
166
|
+
bar?: BarStyle
|
|
167
|
+
line?: LineStyle
|
|
168
|
+
tooltip?: Snippet<[BarHandlerProps<Metadata>]>
|
|
169
|
+
user_content?: Snippet<[UserContentProps]>
|
|
170
|
+
header_controls?: Snippet<[{ height: number; width: number; fullscreen: boolean }]>
|
|
171
|
+
controls_extra?: Snippet<
|
|
172
|
+
[{ orientation: Orientation; mode: BarMode } & Required<PlotConfig>]
|
|
173
|
+
>
|
|
174
|
+
change?: (data: BarHandlerProps<Metadata> | null) => void
|
|
175
|
+
on_bar_click?: (
|
|
176
|
+
data: BarHandlerProps<Metadata> & { event: MouseEvent | KeyboardEvent },
|
|
177
|
+
) => void
|
|
178
|
+
on_bar_hover?: (
|
|
179
|
+
data:
|
|
180
|
+
| (BarHandlerProps<Metadata> & { event: MouseEvent | FocusEvent | KeyboardEvent })
|
|
181
|
+
| null,
|
|
182
|
+
) => void
|
|
183
|
+
// Line marker props (matching ScatterPlot)
|
|
184
|
+
// Note: For line series with markers, BOTH on_bar_* AND on_point_* events fire.
|
|
185
|
+
// Use on_point_* for marker-specific data (includes `point` with InternalPoint details)
|
|
186
|
+
// or on_bar_* for backward compatibility with bar-style event handling.
|
|
187
|
+
color_scale?: ColorScaleConfig | D3InterpolateName
|
|
188
|
+
size_scale?: SizeScaleConfig
|
|
189
|
+
point_tween?: TweenOptions<Point2D>
|
|
190
|
+
on_point_click?: (
|
|
191
|
+
data: LineMarkerHandlerProps & { event: MouseEvent | KeyboardEvent },
|
|
192
|
+
) => void
|
|
193
|
+
on_point_hover?: (
|
|
194
|
+
data:
|
|
195
|
+
| (LineMarkerHandlerProps & {
|
|
196
|
+
event: MouseEvent | FocusEvent | KeyboardEvent
|
|
197
|
+
})
|
|
198
|
+
| null,
|
|
199
|
+
) => void
|
|
200
|
+
ref_lines?: RefLine[]
|
|
201
|
+
on_ref_line_click?: (event: RefLineEvent) => void
|
|
202
|
+
on_ref_line_hover?: (event: RefLineEvent | null) => void
|
|
203
|
+
// Interactive axis props
|
|
204
|
+
data_loader?: DataLoaderFn<Metadata, BarSeries<Metadata>>
|
|
205
|
+
on_axis_change?: (
|
|
206
|
+
axis: `x` | `x2` | `y` | `y2`,
|
|
207
|
+
key: string,
|
|
208
|
+
new_series: BarSeries<Metadata>[],
|
|
209
|
+
) => void
|
|
210
|
+
on_error?: (error: AxisLoadError) => void
|
|
211
|
+
pan?: PanConfig
|
|
212
|
+
marginals?: MarginalsProp
|
|
213
|
+
} = $props()
|
|
204
214
|
|
|
205
215
|
// Initialize bar, line, y2_axis with defaults - using $derived for reactivity
|
|
206
216
|
let bar_state = $derived({ ...DEFAULTS.bar.bar, ...bar })
|
|
@@ -220,7 +230,7 @@
|
|
|
220
230
|
format: ``,
|
|
221
231
|
scale_type: `linear`,
|
|
222
232
|
ticks: 5,
|
|
223
|
-
label_shift: { x: 0, y:
|
|
233
|
+
label_shift: { x: 0, y: AXIS_TITLE_OFFSET },
|
|
224
234
|
tick: { label: { shift: { x: 0, y: 0 } } },
|
|
225
235
|
range: [null, null],
|
|
226
236
|
...x2_axis_prop,
|
|
@@ -238,8 +248,7 @@
|
|
|
238
248
|
let axis_loading = $state<`x` | `x2` | `y` | `y2` | null>(null)
|
|
239
249
|
|
|
240
250
|
// Compute ref_lines with index and group by z-index (using shared utilities)
|
|
241
|
-
let
|
|
242
|
-
let ref_lines_by_z = $derived(group_ref_lines_by_z(indexed_ref_lines))
|
|
251
|
+
let ref_lines_by_z = $derived(group_ref_lines_by_z(index_ref_lines(ref_lines)))
|
|
243
252
|
|
|
244
253
|
// === Categorical Normalization (string x values -> integer indices, see ./data) ===
|
|
245
254
|
let cat_norm = $derived(normalize_categorical(series, x_axis.categories))
|
|
@@ -257,48 +266,45 @@
|
|
|
257
266
|
const axis_px = (orientation === `horizontal` ? height : width) || 0
|
|
258
267
|
const max_ticks = Math.max(1, Math.floor(axis_px / 28)) // ~28px per category label
|
|
259
268
|
const step = Math.ceil(category_indices.length / max_ticks)
|
|
260
|
-
return step <= 1
|
|
261
|
-
? category_indices
|
|
262
|
-
: category_indices.filter((_, idx) => idx % step === 0)
|
|
269
|
+
return step <= 1 ? category_indices : category_indices.filter((_, idx) => idx % step === 0)
|
|
263
270
|
})
|
|
264
271
|
|
|
265
272
|
// Compute auto ranges from visible series
|
|
266
|
-
let visible_series = $derived(
|
|
267
|
-
internal_series.filter((srs) => srs?.visible ?? true),
|
|
268
|
-
)
|
|
273
|
+
let visible_series = $derived(internal_series.filter((srs) => srs?.visible ?? true))
|
|
269
274
|
|
|
270
275
|
// Separate series by y-axis
|
|
271
|
-
let y1_series = $derived(
|
|
272
|
-
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
)
|
|
277
|
-
let
|
|
278
|
-
|
|
276
|
+
let y1_series = $derived(visible_series.filter((srs) => (srs.y_axis ?? `y1`) === `y1`))
|
|
277
|
+
let y2_series = $derived(visible_series.filter((srs) => srs.y_axis === `y2`))
|
|
278
|
+
let x2_series = $derived(visible_series.filter((srs) => srs.x_axis === `x2`))
|
|
279
|
+
// Whether the secondary x2 (top) / y2 (right) axis actually renders: BarPlot only supports
|
|
280
|
+
// them in vertical orientation. Derive once so ticks, padding, axis rendering, and marginal
|
|
281
|
+
// placement stay in sync. (Data-existence checks below use the bare `*_series.length` instead.)
|
|
282
|
+
let show_x2 = $derived(x2_series.length > 0 && orientation === `vertical`)
|
|
283
|
+
let show_y2 = $derived(y2_series.length > 0 && orientation === `vertical`)
|
|
284
|
+
|
|
285
|
+
let auto_ranges = $derived(
|
|
286
|
+
compute_bar_auto_ranges({
|
|
287
|
+
visible_series,
|
|
288
|
+
y1_series,
|
|
289
|
+
y2_series,
|
|
290
|
+
x2_series,
|
|
291
|
+
mode,
|
|
292
|
+
orientation,
|
|
293
|
+
range_padding,
|
|
294
|
+
category_count: category_list.length,
|
|
295
|
+
x_range: x_axis.range ?? [null, null],
|
|
296
|
+
x_scale_type: x_axis.scale_type ?? `linear`,
|
|
297
|
+
x_is_time: x_axis.format?.startsWith(`%`) || false,
|
|
298
|
+
x2_range: x2_axis.range ?? [null, null],
|
|
299
|
+
x2_scale_type: x2_axis.scale_type ?? `linear`,
|
|
300
|
+
x2_is_time: x2_axis.format?.startsWith(`%`) || false,
|
|
301
|
+
y_range: y_axis.range ?? [null, null],
|
|
302
|
+
y_scale_type: y_axis.scale_type ?? `linear`,
|
|
303
|
+
y2_range: y2_axis.range ?? [null, null],
|
|
304
|
+
y2_scale_type: y2_axis.scale_type ?? `linear`,
|
|
305
|
+
}),
|
|
279
306
|
)
|
|
280
307
|
|
|
281
|
-
let auto_ranges = $derived(compute_bar_auto_ranges({
|
|
282
|
-
visible_series,
|
|
283
|
-
y1_series,
|
|
284
|
-
y2_series,
|
|
285
|
-
x2_series,
|
|
286
|
-
mode,
|
|
287
|
-
orientation,
|
|
288
|
-
range_padding,
|
|
289
|
-
category_count: category_list.length,
|
|
290
|
-
x_range: x_axis.range ?? [null, null],
|
|
291
|
-
x_scale_type: x_axis.scale_type ?? `linear`,
|
|
292
|
-
x_is_time: x_axis.format?.startsWith(`%`) || false,
|
|
293
|
-
x2_range: x2_axis.range ?? [null, null],
|
|
294
|
-
x2_scale_type: x2_axis.scale_type ?? `linear`,
|
|
295
|
-
x2_is_time: x2_axis.format?.startsWith(`%`) || false,
|
|
296
|
-
y_range: y_axis.range ?? [null, null],
|
|
297
|
-
y_scale_type: y_axis.scale_type ?? `linear`,
|
|
298
|
-
y2_range: y2_axis.range ?? [null, null],
|
|
299
|
-
y2_scale_type: y2_axis.scale_type ?? `linear`,
|
|
300
|
-
}))
|
|
301
|
-
|
|
302
308
|
// Initialize and current ranges
|
|
303
309
|
let ranges = $state<{
|
|
304
310
|
initial: { x: Vec2; x2: Vec2; y: Vec2; y2: Vec2 }
|
|
@@ -308,10 +314,14 @@
|
|
|
308
314
|
current: { x: [0, 1], x2: [0, 1], y: [0, 1], y2: [0, 1] },
|
|
309
315
|
})
|
|
310
316
|
|
|
311
|
-
$effect(() => {
|
|
317
|
+
$effect(() => {
|
|
318
|
+
// handle x_axis.range / x2_axis.range / y_axis.range / y2_axis.range changes
|
|
312
319
|
// resolve_axis_ranges returns null for transient non-finite bounds (skip: writing
|
|
313
320
|
// NaN breaks scales and, since NaN !== NaN, loops the effect)
|
|
314
|
-
const next = resolve_axis_ranges(
|
|
321
|
+
const next = resolve_axis_ranges(
|
|
322
|
+
{ x: x_axis, x2: x2_axis, y: y_axis, y2: y2_axis },
|
|
323
|
+
auto_ranges,
|
|
324
|
+
)
|
|
315
325
|
if (!next) return
|
|
316
326
|
// Only update if the initial (data-driven) ranges changed, not when user pans.
|
|
317
327
|
// untrack the read of `ranges` so the assignment below can't re-trigger this effect
|
|
@@ -323,42 +333,33 @@
|
|
|
323
333
|
})
|
|
324
334
|
|
|
325
335
|
// Layout: dynamic padding based on tick label widths
|
|
326
|
-
const default_padding = { t: 20, b: 60, l: 60, r: 20 }
|
|
327
336
|
// base_pad reserves space for tick labels/axis titles; pad (below) adds decoration reservations
|
|
328
|
-
let base_pad = $derived(filter_padding(padding,
|
|
337
|
+
let base_pad = $derived(filter_padding(padding, DEFAULT_PLOT_PADDING))
|
|
329
338
|
|
|
330
339
|
// Update padding when format or ticks change
|
|
331
340
|
$effect(() => {
|
|
332
|
-
const new_pad =
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
+
const new_pad =
|
|
342
|
+
width && height && ticks.y.length > 0
|
|
343
|
+
? calc_auto_padding({
|
|
344
|
+
padding,
|
|
345
|
+
default_padding: DEFAULT_PLOT_PADDING,
|
|
346
|
+
x2_axis: { ...x2_axis, tick_values: ticks.x2 },
|
|
347
|
+
y_axis: { ...y_axis, tick_values: ticks.y },
|
|
348
|
+
y2_axis: { ...y2_axis, tick_values: ticks.y2 },
|
|
349
|
+
})
|
|
350
|
+
: filter_padding(padding, DEFAULT_PLOT_PADDING)
|
|
341
351
|
// Expand right padding if y2 ticks are shown (only for vertical orientation)
|
|
342
|
-
if (
|
|
343
|
-
width && height && y2_series.length > 0 && ticks.y2.length > 0 &&
|
|
344
|
-
orientation === `vertical`
|
|
345
|
-
) {
|
|
352
|
+
if (width && height && show_y2 && ticks.y2.length > 0) {
|
|
346
353
|
// Need space for: tick shift + tick width + gap (30px) + label space (20px if present)
|
|
347
354
|
// When ticks are inside, they don't contribute to padding
|
|
348
355
|
const inside = y2_axis.tick?.label?.inside ?? false
|
|
349
356
|
const tick_shift = inside ? 0 : (y2_axis.tick?.label?.shift?.x ?? 0) + 8
|
|
350
357
|
const tick_width_contribution = inside ? 0 : tick_label_widths.y2_max
|
|
351
358
|
const label_space = y2_axis.label ? 20 : 0
|
|
352
|
-
new_pad.r = Math.max(
|
|
353
|
-
new_pad.r,
|
|
354
|
-
tick_shift + tick_width_contribution + 30 + label_space,
|
|
355
|
-
)
|
|
359
|
+
new_pad.r = Math.max(new_pad.r, tick_shift + tick_width_contribution + 30 + label_space)
|
|
356
360
|
}
|
|
357
361
|
// Expand top padding if x2 ticks are shown (only for vertical orientation)
|
|
358
|
-
if (
|
|
359
|
-
width && height && x2_series.length > 0 && ticks.x2.length > 0 &&
|
|
360
|
-
orientation === `vertical`
|
|
361
|
-
) {
|
|
362
|
+
if (width && height && show_x2 && ticks.x2.length > 0) {
|
|
362
363
|
const inside = x2_axis.tick?.label?.inside ?? false
|
|
363
364
|
const tick_shift = inside ? 0 : Math.abs(x2_axis.tick?.label?.shift?.y ?? 0) + 5
|
|
364
365
|
const tick_height = inside ? 0 : 16
|
|
@@ -368,13 +369,18 @@
|
|
|
368
369
|
|
|
369
370
|
// Only update if padding actually changed (prevents infinite loop)
|
|
370
371
|
if (
|
|
371
|
-
base_pad.t !== new_pad.t ||
|
|
372
|
-
base_pad.
|
|
373
|
-
|
|
372
|
+
base_pad.t !== new_pad.t ||
|
|
373
|
+
base_pad.b !== new_pad.b ||
|
|
374
|
+
base_pad.l !== new_pad.l ||
|
|
375
|
+
base_pad.r !== new_pad.r
|
|
376
|
+
)
|
|
377
|
+
base_pad = new_pad
|
|
374
378
|
})
|
|
375
379
|
|
|
376
380
|
let legend_element = $state<HTMLDivElement | undefined>()
|
|
377
|
-
const legend_footprint = $derived(
|
|
381
|
+
const legend_footprint = $derived(
|
|
382
|
+
measured_footprint(legend_element, { width: 120, height: 60 }),
|
|
383
|
+
)
|
|
378
384
|
const legend_has_explicit_pos = $derived(has_explicit_position(legend?.style))
|
|
379
385
|
|
|
380
386
|
// Obstacle field in normalized [0,1] plot coords (y=0 at top). Each bar is modeled as a segment
|
|
@@ -403,8 +409,18 @@
|
|
|
403
409
|
const value = base + srs.y[bar_idx]
|
|
404
410
|
// vertical: category on x, value rises on y (inverted). horizontal: category on y, value on x
|
|
405
411
|
const seg = vertical
|
|
406
|
-
? clip_bar(
|
|
407
|
-
|
|
412
|
+
? clip_bar(
|
|
413
|
+
true,
|
|
414
|
+
(x_val - ax0) / x_span,
|
|
415
|
+
1 - (value - vy0) / y_span,
|
|
416
|
+
1 - (base - vy0) / y_span,
|
|
417
|
+
)
|
|
418
|
+
: clip_bar(
|
|
419
|
+
false,
|
|
420
|
+
1 - (x_val - cy0) / cy_span,
|
|
421
|
+
(value - ax0) / x_span,
|
|
422
|
+
(base - ax0) / x_span,
|
|
423
|
+
)
|
|
408
424
|
if (seg) bars.push(seg)
|
|
409
425
|
})
|
|
410
426
|
})
|
|
@@ -419,39 +435,58 @@
|
|
|
419
435
|
height,
|
|
420
436
|
obstacles_norm,
|
|
421
437
|
// gate on legend_element (the render signal) not legend_data, whose entries can read pad
|
|
422
|
-
legend:
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
438
|
+
legend:
|
|
439
|
+
legend != null &&
|
|
440
|
+
(show_legend !== undefined ? show_legend : series.length > 1) &&
|
|
441
|
+
legend_element != null &&
|
|
442
|
+
!legend_has_explicit_pos
|
|
443
|
+
? { footprint: legend_footprint, clearance: legend?.axis_clearance }
|
|
444
|
+
: null,
|
|
445
|
+
}),
|
|
428
446
|
)
|
|
429
|
-
|
|
447
|
+
// Resolve marginals: a cumulative/Pareto CDF over the CATEGORY axis weighted by bar height.
|
|
448
|
+
// Categories sit on x (vertical) or y (horizontal), so the default side and the value array
|
|
449
|
+
// flip with orientation. The value axis carries no marginal (a bar's height isn't a sample).
|
|
450
|
+
const marginal_is_vertical = $derived(orientation === `vertical`)
|
|
451
|
+
const resolved_marginals = $derived(
|
|
452
|
+
normalize_marginals(
|
|
453
|
+
marginals,
|
|
454
|
+
marginal_is_vertical ? { top: { type: `cdf` } } : { right: { type: `cdf` } },
|
|
455
|
+
),
|
|
456
|
+
)
|
|
457
|
+
const pad = $derived(add_sides(decor.pad, reserve_marginal_pad(resolved_marginals)))
|
|
458
|
+
const marginal_series = $derived<MarginalSeriesInput[]>(
|
|
459
|
+
internal_series.map((srs) => ({
|
|
460
|
+
x: marginal_is_vertical ? (srs?.x ?? []) : undefined,
|
|
461
|
+
y: marginal_is_vertical ? undefined : (srs?.x ?? []),
|
|
462
|
+
// magnitude weights so negative bars still yield a monotonic cumulative (CDF) marginal
|
|
463
|
+
weight: srs?.y?.map((value) => Math.abs(value)) ?? [],
|
|
464
|
+
color:
|
|
465
|
+
srs?.color ??
|
|
466
|
+
(srs?.render_mode === `line` ? line_state.color : bar_state.color) ??
|
|
467
|
+
`steelblue`,
|
|
468
|
+
label: srs?.label,
|
|
469
|
+
visible: srs?.visible ?? true,
|
|
470
|
+
x_axis: srs?.x_axis,
|
|
471
|
+
y_axis: srs?.y_axis,
|
|
472
|
+
})),
|
|
473
|
+
)
|
|
474
|
+
const marginal_has_axis = $derived(marginal_axis_presence(show_x2, show_y2))
|
|
430
475
|
const legend_auto_outside = $derived(decor.legend_outside)
|
|
431
476
|
const legend_outside_x = $derived(decor.legend_pos.x)
|
|
432
477
|
const legend_outside_y = $derived(decor.legend_pos.y)
|
|
433
478
|
const chart_width = $derived(Math.max(1, width - pad.l - pad.r))
|
|
434
479
|
const chart_height = $derived(Math.max(1, height - pad.t - pad.b))
|
|
435
480
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
]),
|
|
446
|
-
y: create_scale(y_axis.scale_type ?? `linear`, ranges.current.y, [
|
|
447
|
-
height - pad.b,
|
|
448
|
-
pad.t,
|
|
449
|
-
]),
|
|
450
|
-
y2: create_scale(y2_axis.scale_type ?? `linear`, ranges.current.y2, [
|
|
451
|
-
height - pad.b,
|
|
452
|
-
pad.t,
|
|
453
|
-
]),
|
|
454
|
-
})
|
|
481
|
+
let scales = $derived(
|
|
482
|
+
create_axis_scales(
|
|
483
|
+
{ x: x_axis, x2: x2_axis, y: y_axis, y2: y2_axis },
|
|
484
|
+
ranges.current,
|
|
485
|
+
pad,
|
|
486
|
+
width,
|
|
487
|
+
height,
|
|
488
|
+
),
|
|
489
|
+
)
|
|
455
490
|
|
|
456
491
|
// Compute plot center for point tweening origin
|
|
457
492
|
let plot_center_x = $derived(pad.l + (width - pad.r - pad.l) / 2)
|
|
@@ -462,9 +497,7 @@
|
|
|
462
497
|
visible_series
|
|
463
498
|
.filter((srs: BarSeries<Metadata>) => srs.render_mode === `line`)
|
|
464
499
|
.flatMap((srs: BarSeries<Metadata>) =>
|
|
465
|
-
(srs.color_values ?? []).filter(
|
|
466
|
-
(val): val is number => typeof val === `number`,
|
|
467
|
-
)
|
|
500
|
+
(srs.color_values ?? []).filter((val): val is number => typeof val === `number`),
|
|
468
501
|
),
|
|
469
502
|
)
|
|
470
503
|
|
|
@@ -480,9 +513,7 @@
|
|
|
480
513
|
visible_series
|
|
481
514
|
.filter((srs: BarSeries<Metadata>) => srs.render_mode === `line`)
|
|
482
515
|
.flatMap((srs: BarSeries<Metadata>) =>
|
|
483
|
-
[...(srs.size_values ?? [])].filter(
|
|
484
|
-
(val): val is number => typeof val === `number`,
|
|
485
|
-
)
|
|
516
|
+
[...(srs.size_values ?? [])].filter((val): val is number => typeof val === `number`),
|
|
486
517
|
),
|
|
487
518
|
)
|
|
488
519
|
|
|
@@ -500,57 +531,37 @@
|
|
|
500
531
|
// Only respect user ticks when they're a Record (custom label mapping),
|
|
501
532
|
// not a number (tick count) or array (tick positions)
|
|
502
533
|
const user_ticks = cat_axis === `x` ? x_axis.ticks : y_axis.ticks
|
|
503
|
-
if (
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
) return user_ticks
|
|
507
|
-
return Object.fromEntries(
|
|
508
|
-
category_list.map((cat, idx) => [idx, cat]),
|
|
509
|
-
) as Record<number, string>
|
|
534
|
+
if (user_ticks != null && typeof user_ticks === `object` && !Array.isArray(user_ticks))
|
|
535
|
+
return user_ticks
|
|
536
|
+
return Object.fromEntries(category_list.map((cat, idx): [number, string] => [idx, cat]))
|
|
510
537
|
})
|
|
511
538
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
:
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
{
|
|
539
|
-
default_count: 6,
|
|
540
|
-
},
|
|
541
|
-
)
|
|
542
|
-
: [],
|
|
543
|
-
x2: width && height && x2_series.length > 0 && orientation === `vertical`
|
|
544
|
-
? generate_ticks(
|
|
545
|
-
ranges.current.x2,
|
|
546
|
-
x2_axis.scale_type ?? `linear`,
|
|
547
|
-
x2_axis.ticks,
|
|
548
|
-
scales.x2,
|
|
549
|
-
{
|
|
550
|
-
default_count: 8,
|
|
551
|
-
},
|
|
552
|
-
)
|
|
553
|
-
: [],
|
|
539
|
+
let ticks = $derived.by(() => {
|
|
540
|
+
const axis_ticks = (
|
|
541
|
+
axis: typeof x_axis,
|
|
542
|
+
range: Vec2,
|
|
543
|
+
scale: typeof scales.x,
|
|
544
|
+
default_count: number,
|
|
545
|
+
show = true,
|
|
546
|
+
) =>
|
|
547
|
+
width && height && show
|
|
548
|
+
? generate_ticks(range, axis.scale_type ?? `linear`, axis.ticks, scale, {
|
|
549
|
+
default_count,
|
|
550
|
+
})
|
|
551
|
+
: []
|
|
552
|
+
// categorical axes show one tick per category instead of generated numeric ticks
|
|
553
|
+
return {
|
|
554
|
+
x:
|
|
555
|
+
category_indices && cat_axis === `x` && width && height
|
|
556
|
+
? cat_tick_indices
|
|
557
|
+
: axis_ticks(x_axis, ranges.current.x, scales.x, 8),
|
|
558
|
+
y:
|
|
559
|
+
category_indices && cat_axis === `y` && width && height
|
|
560
|
+
? cat_tick_indices
|
|
561
|
+
: axis_ticks(y_axis, ranges.current.y, scales.y, 6),
|
|
562
|
+
y2: axis_ticks(y2_axis, ranges.current.y2, scales.y2, 6, show_y2),
|
|
563
|
+
x2: axis_ticks(x2_axis, ranges.current.x2, scales.x2, 8, show_x2),
|
|
564
|
+
}
|
|
554
565
|
})
|
|
555
566
|
|
|
556
567
|
// Cache measured tick-label widths so expensive canvas text measurement
|
|
@@ -564,7 +575,8 @@
|
|
|
564
575
|
// Shared pan/zoom/touch/drag-rect interaction controller
|
|
565
576
|
const pan_zoom = create_pan_zoom({
|
|
566
577
|
ranges: () => ranges.current,
|
|
567
|
-
scale_type: (axis) =>
|
|
578
|
+
scale_type: (axis) =>
|
|
579
|
+
({ x: x_axis, x2: x2_axis, y: y_axis, y2: y2_axis })[axis].scale_type,
|
|
568
580
|
plot_dims: () => ({ width: chart_width, height: chart_height }),
|
|
569
581
|
pan: () => pan,
|
|
570
582
|
set_range: (axis, range) => (ranges.current[axis] = range),
|
|
@@ -574,13 +586,13 @@
|
|
|
574
586
|
const next_x = invert_rect_range(scales.x, start.x, current.x)
|
|
575
587
|
if (!next_x) return
|
|
576
588
|
x_axis = { ...x_axis, range: next_x }
|
|
577
|
-
// gate x2/y2 on
|
|
578
|
-
//
|
|
579
|
-
const next_x2 =
|
|
589
|
+
// gate x2/y2 on whether they actually render (show_x2/show_y2 also require vertical);
|
|
590
|
+
// otherwise their [0, 1] sentinel scales would store a phantom range in the bindable prop
|
|
591
|
+
const next_x2 = show_x2 ? invert_rect_range(scales.x2, start.x, current.x) : null
|
|
580
592
|
if (next_x2) x2_axis_prop = { ...x2_axis_prop, range: next_x2 }
|
|
581
593
|
const next_y = invert_rect_range(scales.y, start.y, current.y)
|
|
582
594
|
if (next_y) y_axis = { ...y_axis, range: next_y }
|
|
583
|
-
const next_y2 =
|
|
595
|
+
const next_y2 = show_y2 ? invert_rect_range(scales.y2, start.y, current.y) : null
|
|
584
596
|
if (next_y2) y2_axis_prop = { ...y2_axis_prop, range: next_y2 }
|
|
585
597
|
},
|
|
586
598
|
on_reset: () => {
|
|
@@ -606,8 +618,7 @@
|
|
|
606
618
|
const is_line = srs.render_mode === `line`
|
|
607
619
|
const series_markers = srs.markers ?? DEFAULT_MARKERS
|
|
608
620
|
const has_line = series_markers === `line` || series_markers === `line+points`
|
|
609
|
-
const has_points = series_markers === `points` ||
|
|
610
|
-
series_markers === `line+points`
|
|
621
|
+
const has_points = series_markers === `points` || series_markers === `line+points`
|
|
611
622
|
const series_color = srs.color ?? (is_line ? line_state.color : bar_state.color)
|
|
612
623
|
|
|
613
624
|
// Get point style for symbol color (handle array or single object)
|
|
@@ -615,9 +626,10 @@
|
|
|
615
626
|
? srs.point_style[0]
|
|
616
627
|
: srs.point_style
|
|
617
628
|
const first_color_value = srs.color_values?.[0]
|
|
618
|
-
const point_color =
|
|
619
|
-
|
|
620
|
-
|
|
629
|
+
const point_color =
|
|
630
|
+
first_color_value != null
|
|
631
|
+
? color_scale_fn(first_color_value)
|
|
632
|
+
: (first_point_style?.fill ?? series_color)
|
|
621
633
|
|
|
622
634
|
if (is_line) {
|
|
623
635
|
// Line series: show line and/or symbol based on markers
|
|
@@ -629,16 +641,15 @@
|
|
|
629
641
|
display_style: {
|
|
630
642
|
...(has_line
|
|
631
643
|
? {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
644
|
+
line_color: series_color,
|
|
645
|
+
line_dash: srs.line_style?.line_dash,
|
|
646
|
+
}
|
|
635
647
|
: {}),
|
|
636
648
|
...(has_points
|
|
637
649
|
? {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
}
|
|
650
|
+
symbol_type: first_point_style?.symbol_type ?? DEFAULTS.scatter.symbol_type,
|
|
651
|
+
symbol_color: point_color,
|
|
652
|
+
}
|
|
642
653
|
: {}),
|
|
643
654
|
},
|
|
644
655
|
}
|
|
@@ -654,10 +665,13 @@
|
|
|
654
665
|
symbol_color: series_color,
|
|
655
666
|
},
|
|
656
667
|
}
|
|
657
|
-
})
|
|
668
|
+
}),
|
|
658
669
|
)
|
|
659
670
|
|
|
660
|
-
const legend_vis = create_legend_visibility(
|
|
671
|
+
const legend_vis = create_legend_visibility(
|
|
672
|
+
() => series,
|
|
673
|
+
(next) => (series = next),
|
|
674
|
+
)
|
|
661
675
|
|
|
662
676
|
// Collect bar and line positions for legend placement
|
|
663
677
|
let bar_points_for_placement = $derived.by(() => {
|
|
@@ -674,12 +688,11 @@
|
|
|
674
688
|
return srs.x
|
|
675
689
|
.map((x_val, bar_idx) => {
|
|
676
690
|
const y_val = srs.y[bar_idx]
|
|
677
|
-
const base = !is_line && mode === `stacked`
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
: [x_scale_pl(base + y_val), scales.y(x_val)]
|
|
691
|
+
const base = !is_line && mode === `stacked` ? (series_offsets[bar_idx] ?? 0) : 0
|
|
692
|
+
const [bar_x, bar_y] =
|
|
693
|
+
orientation === `vertical`
|
|
694
|
+
? [x_scale_pl(x_val), y_scale(base + y_val)]
|
|
695
|
+
: [x_scale_pl(base + y_val), scales.y(x_val)]
|
|
683
696
|
return { x: bar_x, y: bar_y }
|
|
684
697
|
})
|
|
685
698
|
.filter(({ x, y }) => isFinite(x) && isFinite(y))
|
|
@@ -726,9 +739,7 @@
|
|
|
726
739
|
const srs = internal_series[series_idx]
|
|
727
740
|
const [x, y] = [srs.x[bar_idx], srs.y[bar_idx]]
|
|
728
741
|
const [orient_x, orient_y] = orientation === `horizontal` ? [y, x] : [x, y]
|
|
729
|
-
const metadata = Array.isArray(srs.metadata)
|
|
730
|
-
? srs.metadata[bar_idx]
|
|
731
|
-
: srs.metadata
|
|
742
|
+
const metadata = Array.isArray(srs.metadata) ? srs.metadata[bar_idx] : srs.metadata
|
|
732
743
|
const label = srs.labels?.[bar_idx] ?? null
|
|
733
744
|
const active_y_axis = srs.y_axis ?? `y1`
|
|
734
745
|
const active_x_axis = srs.x_axis ?? `x1`
|
|
@@ -783,7 +794,7 @@
|
|
|
783
794
|
const line_point_fill = (pt: LineSeriesPoint, series_color: string): string =>
|
|
784
795
|
pt.color_value != null
|
|
785
796
|
? color_scale_fn(pt.color_value)
|
|
786
|
-
: pt.point_style?.fill ?? series_color
|
|
797
|
+
: (pt.point_style?.fill ?? series_color)
|
|
787
798
|
|
|
788
799
|
const handle_bar_hover =
|
|
789
800
|
(series_idx: number, bar_idx: number, color: string) => (event: MouseEvent) => {
|
|
@@ -805,31 +816,31 @@
|
|
|
805
816
|
})
|
|
806
817
|
|
|
807
818
|
// State accessors for shared axis change handler
|
|
819
|
+
// Secondary axes read the merged $derived (x2_axis/y2_axis) but write the raw $bindable props
|
|
820
|
+
// (x2_axis_prop/y2_axis_prop) so library defaults aren't pushed into the parent's bound state
|
|
808
821
|
const axis_state: AxisChangeState<BarSeries<Metadata>> = {
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
822
|
+
axes: {
|
|
823
|
+
x: { get: () => x_axis, set: (config) => (x_axis = { ...x_axis, ...config }) },
|
|
824
|
+
x2: {
|
|
825
|
+
get: () => x2_axis,
|
|
826
|
+
set: (config) => (x2_axis_prop = { ...x2_axis_prop, ...config }),
|
|
827
|
+
},
|
|
828
|
+
y: { get: () => y_axis, set: (config) => (y_axis = { ...y_axis, ...config }) },
|
|
829
|
+
y2: {
|
|
830
|
+
get: () => y2_axis,
|
|
831
|
+
set: (config) => (y2_axis_prop = { ...y2_axis_prop, ...config }),
|
|
832
|
+
},
|
|
814
833
|
},
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
if (axis === `x`) x_axis = { ...x_axis, ...config }
|
|
818
|
-
else if (axis === `x2`) x2_axis_prop = { ...x2_axis_prop, ...config }
|
|
819
|
-
else if (axis === `y`) y_axis = { ...y_axis, ...config }
|
|
820
|
-
else y2_axis_prop = { ...y2_axis_prop, ...config }
|
|
821
|
-
},
|
|
822
|
-
get_series: () => series,
|
|
823
|
-
set_series: (new_series) => (series = new_series),
|
|
824
|
-
get_loading: () => axis_loading,
|
|
825
|
-
set_loading: (axis) => (axis_loading = axis),
|
|
834
|
+
series: { get: () => series, set: (next) => (series = next) },
|
|
835
|
+
loading: { get: () => axis_loading, set: (axis) => (axis_loading = axis) },
|
|
826
836
|
}
|
|
827
837
|
|
|
828
838
|
// Shared handler + one-shot auto-load bound to this component's state
|
|
829
|
-
const { handle_axis_change, try_auto_load } = create_axis_loader(
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
839
|
+
const { handle_axis_change, try_auto_load } = create_axis_loader(axis_state, () => ({
|
|
840
|
+
data_loader,
|
|
841
|
+
on_axis_change,
|
|
842
|
+
on_error,
|
|
843
|
+
}))
|
|
833
844
|
$effect(try_auto_load)
|
|
834
845
|
</script>
|
|
835
846
|
|
|
@@ -877,7 +888,7 @@
|
|
|
877
888
|
bind:clientWidth={width}
|
|
878
889
|
bind:clientHeight={height}
|
|
879
890
|
{...rest}
|
|
880
|
-
class=
|
|
891
|
+
class={[`bar-plot`, rest.class]}
|
|
881
892
|
class:fullscreen
|
|
882
893
|
>
|
|
883
894
|
{#if width && height}
|
|
@@ -893,7 +904,7 @@
|
|
|
893
904
|
bind:this={svg_element}
|
|
894
905
|
role="application"
|
|
895
906
|
aria-label={rest[`aria-label`] ??
|
|
896
|
-
|
|
907
|
+
([x_axis.label, y_axis.label].filter(Boolean).join(` vs `) || `Bar chart`)}
|
|
897
908
|
tabindex="0"
|
|
898
909
|
onfocusin={() => pan_zoom.set_focused(true)}
|
|
899
910
|
onfocusout={() => pan_zoom.set_focused(false)}
|
|
@@ -937,38 +948,38 @@
|
|
|
937
948
|
<!-- X-axis -->
|
|
938
949
|
<PlotAxis
|
|
939
950
|
side="x"
|
|
940
|
-
ticks={ticks.x
|
|
951
|
+
ticks={ticks.x}
|
|
941
952
|
place={scales.x}
|
|
942
953
|
axis={x_axis}
|
|
943
|
-
domain={ranges.current.x
|
|
954
|
+
domain={ranges.current.x}
|
|
944
955
|
{pad}
|
|
945
956
|
{width}
|
|
946
957
|
{height}
|
|
947
958
|
show_grid={display.x_grid}
|
|
948
959
|
tick_label={(tick) =>
|
|
949
|
-
|
|
960
|
+
get_tick_label(tick, cat_axis === `x` ? effective_cat_ticks : x_axis.ticks)}
|
|
950
961
|
label_x={pad.l + chart_width / 2 + (x_axis.label_shift?.x ?? 0)}
|
|
951
|
-
label_y={height - pad.b
|
|
962
|
+
label_y={height - pad.b + AXIS_TITLE_OFFSET + (x_axis.label_shift?.y ?? 0)}
|
|
952
963
|
axis_loading={axis_loading === `x`}
|
|
953
964
|
on_axis_change={(key) => handle_axis_change(`x`, key)}
|
|
954
965
|
/>
|
|
955
966
|
|
|
956
967
|
<!-- X2-axis (Top) -->
|
|
957
968
|
<!-- Note: x2 axis is only supported for vertical orientation -->
|
|
958
|
-
{#if
|
|
969
|
+
{#if show_x2}
|
|
959
970
|
<PlotAxis
|
|
960
971
|
side="x2"
|
|
961
|
-
ticks={ticks.x2
|
|
972
|
+
ticks={ticks.x2}
|
|
962
973
|
place={scales.x2}
|
|
963
974
|
axis={x2_axis}
|
|
964
|
-
domain={ranges.current.x2
|
|
975
|
+
domain={ranges.current.x2}
|
|
965
976
|
{pad}
|
|
966
977
|
{width}
|
|
967
978
|
{height}
|
|
968
979
|
show_grid={display.x2_grid}
|
|
969
980
|
tick_label={(tick) => get_tick_label(tick, x2_axis.ticks)}
|
|
970
981
|
label_x={pad.l + chart_width / 2 + (x2_axis.label_shift?.x ?? 0)}
|
|
971
|
-
label_y={Math.max(12, pad.t - (x2_axis.label_shift?.y ??
|
|
982
|
+
label_y={Math.max(12, pad.t - (x2_axis.label_shift?.y ?? AXIS_TITLE_OFFSET))}
|
|
972
983
|
axis_loading={axis_loading === `x2`}
|
|
973
984
|
on_axis_change={(key) => handle_axis_change(`x2`, key)}
|
|
974
985
|
/>
|
|
@@ -977,19 +988,20 @@
|
|
|
977
988
|
<!-- Y-axis -->
|
|
978
989
|
<PlotAxis
|
|
979
990
|
side="y"
|
|
980
|
-
ticks={ticks.y
|
|
991
|
+
ticks={ticks.y}
|
|
981
992
|
place={scales.y}
|
|
982
993
|
axis={y_axis}
|
|
983
|
-
domain={ranges.current.y
|
|
994
|
+
domain={ranges.current.y}
|
|
984
995
|
{pad}
|
|
985
996
|
{width}
|
|
986
997
|
{height}
|
|
987
998
|
show_grid={display.y_grid}
|
|
988
999
|
tick_label={(tick) =>
|
|
989
|
-
|
|
1000
|
+
get_tick_label(tick, cat_axis === `y` ? effective_cat_ticks : y_axis.ticks)}
|
|
990
1001
|
label_x={Math.max(
|
|
991
1002
|
12,
|
|
992
|
-
pad.l -
|
|
1003
|
+
pad.l -
|
|
1004
|
+
(y_axis.tick?.label?.inside ? 0 : tick_label_widths.y_max) -
|
|
993
1005
|
LABEL_GAP_DEFAULT,
|
|
994
1006
|
) + (y_axis.label_shift?.x ?? 0)}
|
|
995
1007
|
label_y={pad.t + chart_height / 2 + (y_axis.label_shift?.y ?? 0)}
|
|
@@ -999,13 +1011,13 @@
|
|
|
999
1011
|
|
|
1000
1012
|
<!-- Y2-axis (Right) -->
|
|
1001
1013
|
<!-- Note: y2 axis is only supported for vertical orientation. Implementing x2 for horizontal mode requires additional complexity. -->
|
|
1002
|
-
{#if
|
|
1014
|
+
{#if show_y2}
|
|
1003
1015
|
<PlotAxis
|
|
1004
1016
|
side="y2"
|
|
1005
|
-
ticks={ticks.y2
|
|
1017
|
+
ticks={ticks.y2}
|
|
1006
1018
|
place={scales.y2}
|
|
1007
1019
|
axis={y2_axis}
|
|
1008
|
-
domain={ranges.current.y2
|
|
1020
|
+
domain={ranges.current.y2}
|
|
1009
1021
|
{pad}
|
|
1010
1022
|
{width}
|
|
1011
1023
|
{height}
|
|
@@ -1046,8 +1058,8 @@
|
|
|
1046
1058
|
y2_scale_type={y2_axis.scale_type}
|
|
1047
1059
|
x_is_time={x_axis.format?.startsWith(`%`) ?? false}
|
|
1048
1060
|
x2_is_time={x2_axis.format?.startsWith(`%`) ?? false}
|
|
1049
|
-
has_x2={
|
|
1050
|
-
has_y2={
|
|
1061
|
+
has_x2={show_x2}
|
|
1062
|
+
has_y2={show_y2}
|
|
1051
1063
|
{width}
|
|
1052
1064
|
{height}
|
|
1053
1065
|
{pad}
|
|
@@ -1065,7 +1077,7 @@
|
|
|
1065
1077
|
class={is_line ? `line-series` : `bar-series`}
|
|
1066
1078
|
data-series-idx={series_idx}
|
|
1067
1079
|
opacity={hovered_legend_series_idx !== null &&
|
|
1068
|
-
|
|
1080
|
+
hovered_legend_series_idx !== series_idx
|
|
1069
1081
|
? 0.25
|
|
1070
1082
|
: 1}
|
|
1071
1083
|
>
|
|
@@ -1079,21 +1091,22 @@
|
|
|
1079
1091
|
{@const use_x2 = srs.x_axis === `x2`}
|
|
1080
1092
|
{@const x_scale = use_x2 ? scales.x2 : scales.x}
|
|
1081
1093
|
{@const series_markers = srs.markers ?? DEFAULT_MARKERS}
|
|
1082
|
-
{@const show_line =
|
|
1083
|
-
|
|
1084
|
-
{@const show_points =
|
|
1085
|
-
|
|
1094
|
+
{@const show_line =
|
|
1095
|
+
series_markers === `line` || series_markers === `line+points`}
|
|
1096
|
+
{@const show_points =
|
|
1097
|
+
series_markers === `points` || series_markers === `line+points`}
|
|
1086
1098
|
{@const points = compute_line_points({
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
{@const polyline_str =
|
|
1095
|
-
|
|
1096
|
-
|
|
1099
|
+
series: srs,
|
|
1100
|
+
series_idx,
|
|
1101
|
+
orientation,
|
|
1102
|
+
x_scale,
|
|
1103
|
+
y_scale,
|
|
1104
|
+
cat_y_scale: scales.y,
|
|
1105
|
+
})}
|
|
1106
|
+
{@const polyline_str =
|
|
1107
|
+
show_line && points.length > 1
|
|
1108
|
+
? points.map((pt) => `${pt.x},${pt.y}`).join(` `)
|
|
1109
|
+
: ``}
|
|
1097
1110
|
{#if polyline_str}
|
|
1098
1111
|
<polyline
|
|
1099
1112
|
points={polyline_str}
|
|
@@ -1142,44 +1155,41 @@
|
|
|
1142
1155
|
{#if show_points}
|
|
1143
1156
|
{@const clickable = on_bar_click || on_point_click}
|
|
1144
1157
|
{@const get_pt = (evt: Event) => {
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
}}
|
|
1158
|
+
const attr =
|
|
1159
|
+
evt.target instanceof Element
|
|
1160
|
+
? evt.target.closest(`[data-bar-idx]`)?.getAttribute(`data-bar-idx`)
|
|
1161
|
+
: null
|
|
1162
|
+
return points.find((pt) => pt.idx === parseInt(attr ?? ``, 10))
|
|
1163
|
+
}}
|
|
1152
1164
|
{@const set_hover = (
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
)
|
|
1169
|
-
}}
|
|
1165
|
+
pt: LineSeriesPoint | null,
|
|
1166
|
+
evt: MouseEvent | FocusEvent,
|
|
1167
|
+
) => {
|
|
1168
|
+
if (pt) {
|
|
1169
|
+
hovered = true
|
|
1170
|
+
const fill = line_point_fill(pt, color)
|
|
1171
|
+
hover_info = get_bar_data(series_idx, pt.idx, fill)
|
|
1172
|
+
change(hover_info)
|
|
1173
|
+
} else {
|
|
1174
|
+
change(null)
|
|
1175
|
+
hover_info = null
|
|
1176
|
+
}
|
|
1177
|
+
on_bar_hover?.(pt ? { ...hover_info!, event: evt } : null)
|
|
1178
|
+
on_point_hover?.(pt ? { ...hover_info!, event: evt, point: pt } : null)
|
|
1179
|
+
}}
|
|
1170
1180
|
{@const do_click = (
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1181
|
+
pt: LineSeriesPoint,
|
|
1182
|
+
evt: MouseEvent | KeyboardEvent,
|
|
1183
|
+
) => {
|
|
1184
|
+
const fill = line_point_fill(pt, color)
|
|
1185
|
+
const bar_data = get_bar_data(series_idx, pt.idx, fill)
|
|
1186
|
+
on_bar_click?.({ ...bar_data, event: evt })
|
|
1187
|
+
on_point_click?.({ ...bar_data, event: evt, point: pt })
|
|
1188
|
+
}}
|
|
1179
1189
|
{@const leaving = (evt: MouseEvent | FocusEvent) =>
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1190
|
+
(evt.relatedTarget instanceof Element
|
|
1191
|
+
? evt.relatedTarget.closest(`.line-points`)
|
|
1192
|
+
: null) !== evt.currentTarget}
|
|
1183
1193
|
<!-- svelte-ignore a11y_no_noninteractive_element_interactions, a11y_mouse_events_have_key_events -->
|
|
1184
1194
|
<g
|
|
1185
1195
|
class="line-points"
|
|
@@ -1213,11 +1223,13 @@
|
|
|
1213
1223
|
{#each points as pt (pt.idx)}
|
|
1214
1224
|
{@const sty = pt.point_style}
|
|
1215
1225
|
{@const fl = line_point_fill(pt, color)}
|
|
1216
|
-
{@const rad =
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1226
|
+
{@const rad =
|
|
1227
|
+
pt.size_value != null
|
|
1228
|
+
? size_scale_fn(pt.size_value)
|
|
1229
|
+
: (sty?.radius ?? 4)}
|
|
1230
|
+
{@const hov =
|
|
1231
|
+
hover_info?.series_idx === series_idx &&
|
|
1232
|
+
hover_info?.bar_idx === pt.idx}
|
|
1221
1233
|
<ScatterPoint
|
|
1222
1234
|
x={pt.x}
|
|
1223
1235
|
y={pt.y}
|
|
@@ -1248,31 +1260,30 @@
|
|
|
1248
1260
|
<!-- Render as bars -->
|
|
1249
1261
|
{#each srs.x as x_val, bar_idx (bar_idx)}
|
|
1250
1262
|
{@const y_val = srs.y[bar_idx]}
|
|
1251
|
-
{@const base =
|
|
1252
|
-
|
|
1253
|
-
: 0}
|
|
1263
|
+
{@const base =
|
|
1264
|
+
mode === `stacked` ? (stacked_offsets[series_idx]?.[bar_idx] ?? 0) : 0}
|
|
1254
1265
|
{@const color = srs.color ?? bar_state.color ?? `steelblue`}
|
|
1255
1266
|
{@const bar_width_val = Array.isArray(srs.bar_width)
|
|
1256
|
-
|
|
1257
|
-
|
|
1267
|
+
? (srs.bar_width[bar_idx] ?? 0.5)
|
|
1268
|
+
: (srs.bar_width ?? 0.5)}
|
|
1258
1269
|
{@const is_vertical = orientation === `vertical`}
|
|
1259
1270
|
{@const x_scale_bar = srs.x_axis === `x2` ? scales.x2 : scales.x}
|
|
1260
1271
|
{@const [cat_scale, val_scale] = is_vertical
|
|
1261
|
-
|
|
1262
|
-
|
|
1272
|
+
? [x_scale_bar, srs.y_axis === `y2` ? scales.y2 : scales.y]
|
|
1273
|
+
: [scales.y, x_scale_bar]}
|
|
1263
1274
|
{@const { c0, c1, v0, v1, rect_x, rect_y, rect_w, rect_h } =
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1275
|
+
compute_bar_rect({
|
|
1276
|
+
cat_val: x_val,
|
|
1277
|
+
val: y_val,
|
|
1278
|
+
base,
|
|
1279
|
+
bar_width_val,
|
|
1280
|
+
series_idx,
|
|
1281
|
+
mode,
|
|
1282
|
+
orientation,
|
|
1283
|
+
group_info,
|
|
1284
|
+
cat_scale,
|
|
1285
|
+
val_scale,
|
|
1286
|
+
})}
|
|
1276
1287
|
{#if (is_vertical ? rect_h : rect_w) > 0}
|
|
1277
1288
|
<path
|
|
1278
1289
|
d={bar_path(
|
|
@@ -1299,10 +1310,10 @@
|
|
|
1299
1310
|
on_bar_hover?.(null)
|
|
1300
1311
|
}}
|
|
1301
1312
|
onclick={(evt) =>
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1313
|
+
on_bar_click?.({
|
|
1314
|
+
...get_bar_data(series_idx, bar_idx, color),
|
|
1315
|
+
event: evt,
|
|
1316
|
+
})}
|
|
1306
1317
|
onkeydown={(evt) => {
|
|
1307
1318
|
if (evt.key === `Enter` || evt.key === ` `) {
|
|
1308
1319
|
evt.preventDefault()
|
|
@@ -1334,17 +1345,44 @@
|
|
|
1334
1345
|
|
|
1335
1346
|
{@render ref_lines_layer(ref_lines_by_z.below_points)}
|
|
1336
1347
|
{@render ref_lines_layer(ref_lines_by_z.above_all)}
|
|
1348
|
+
|
|
1349
|
+
<!-- Marginal distribution strips -->
|
|
1350
|
+
<PlotMarginals
|
|
1351
|
+
marginals={resolved_marginals}
|
|
1352
|
+
series={marginal_series}
|
|
1353
|
+
{width}
|
|
1354
|
+
{height}
|
|
1355
|
+
{pad}
|
|
1356
|
+
has_axis={marginal_has_axis}
|
|
1357
|
+
axes={{
|
|
1358
|
+
x1: marginal_axis(
|
|
1359
|
+
scales.x,
|
|
1360
|
+
ranges.current.x,
|
|
1361
|
+
x_axis,
|
|
1362
|
+
cat_axis === `x` ? (pos) => category_list[Math.round(pos)] : undefined,
|
|
1363
|
+
),
|
|
1364
|
+
x2: marginal_axis(scales.x2, ranges.current.x2, x2_axis),
|
|
1365
|
+
y1: marginal_axis(
|
|
1366
|
+
scales.y,
|
|
1367
|
+
ranges.current.y,
|
|
1368
|
+
y_axis,
|
|
1369
|
+
cat_axis === `y` ? (pos) => category_list[Math.round(pos)] : undefined,
|
|
1370
|
+
),
|
|
1371
|
+
y2: marginal_axis(scales.y2, ranges.current.y2, y2_axis),
|
|
1372
|
+
}}
|
|
1373
|
+
id={clip_path_id}
|
|
1374
|
+
/>
|
|
1337
1375
|
</svg>
|
|
1338
1376
|
|
|
1339
1377
|
<!-- Legend -->
|
|
1340
1378
|
{#if legend && (show_legend !== undefined ? show_legend : series.length > 1)}
|
|
1341
1379
|
{@const legend_pos = placed_coords(
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1380
|
+
legend_auto_outside,
|
|
1381
|
+
{ x: legend_outside_x, y: legend_outside_y },
|
|
1382
|
+
legend_placement,
|
|
1383
|
+
legend_tween.coords.current,
|
|
1384
|
+
{ x: pad.l + 10, y: pad.t + 10 },
|
|
1385
|
+
)}
|
|
1348
1386
|
<PlotLegend
|
|
1349
1387
|
bind:root_element={legend_element}
|
|
1350
1388
|
{...legend}
|
|
@@ -1354,9 +1392,8 @@
|
|
|
1354
1392
|
on_double_click={legend?.on_double_click ?? legend_vis.on_double_click}
|
|
1355
1393
|
on_hover_change={legend_tween.set_locked}
|
|
1356
1394
|
on_item_hover={(item) =>
|
|
1357
|
-
(hovered_legend_series_idx =
|
|
1358
|
-
? item.series_idx
|
|
1359
|
-
: null)}
|
|
1395
|
+
(hovered_legend_series_idx =
|
|
1396
|
+
item != null && item.series_idx >= 0 ? item.series_idx : null)}
|
|
1360
1397
|
active_series_idx={hover_info?.series_idx ?? hovered_legend_series_idx}
|
|
1361
1398
|
style={`
|
|
1362
1399
|
position: absolute;
|
|
@@ -1370,11 +1407,11 @@
|
|
|
1370
1407
|
|
|
1371
1408
|
{#if hover_info && hovered}
|
|
1372
1409
|
{@const cx = (hover_info.active_x_axis === `x2` ? scales.x2 : scales.x)(
|
|
1373
|
-
|
|
1374
|
-
|
|
1410
|
+
hover_info.orient_x,
|
|
1411
|
+
)}
|
|
1375
1412
|
{@const cy = (hover_info.active_y_axis === `y2` ? scales.y2 : scales.y)(
|
|
1376
|
-
|
|
1377
|
-
|
|
1413
|
+
hover_info.orient_y,
|
|
1414
|
+
)}
|
|
1378
1415
|
<PlotTooltip
|
|
1379
1416
|
x={cx}
|
|
1380
1417
|
y={cy}
|
|
@@ -1391,16 +1428,16 @@
|
|
|
1391
1428
|
<div><strong>{series_label}</strong></div>
|
|
1392
1429
|
{/if}
|
|
1393
1430
|
<div>
|
|
1394
|
-
{@html sanitize_html(hover_info.x_axis.label || `x`)}: {
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1431
|
+
{@html sanitize_html(hover_info.x_axis.label || `x`)}: {(cat_axis === `x`
|
|
1432
|
+
? hover_info.category_label
|
|
1433
|
+
: undefined) ??
|
|
1434
|
+
format_value_or_num(hover_info.orient_x, hover_info.x_axis.format)}
|
|
1398
1435
|
</div>
|
|
1399
1436
|
<div>
|
|
1400
|
-
{@html sanitize_html(hover_info.y_axis.label || `y`)}: {
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1437
|
+
{@html sanitize_html(hover_info.y_axis.label || `y`)}: {(cat_axis === `y`
|
|
1438
|
+
? hover_info.category_label
|
|
1439
|
+
: undefined) ??
|
|
1440
|
+
format_value_or_num(hover_info.orient_y, hover_info.y_axis.format)}
|
|
1404
1441
|
</div>
|
|
1405
1442
|
{/if}
|
|
1406
1443
|
</PlotTooltip>
|
|
@@ -1424,12 +1461,12 @@
|
|
|
1424
1461
|
bind:y_axis
|
|
1425
1462
|
bind:y2_axis={y2_axis_prop}
|
|
1426
1463
|
bind:display
|
|
1427
|
-
auto_x_range={auto_ranges.x
|
|
1428
|
-
auto_x2_range={auto_ranges.x2
|
|
1429
|
-
auto_y_range={auto_ranges.y
|
|
1430
|
-
auto_y2_range={auto_ranges.y2
|
|
1431
|
-
has_x2_points={
|
|
1432
|
-
has_y2_points={
|
|
1464
|
+
auto_x_range={auto_ranges.x}
|
|
1465
|
+
auto_x2_range={auto_ranges.x2}
|
|
1466
|
+
auto_y_range={auto_ranges.y}
|
|
1467
|
+
auto_y2_range={auto_ranges.y2}
|
|
1468
|
+
has_x2_points={show_x2}
|
|
1469
|
+
has_y2_points={show_y2}
|
|
1433
1470
|
children={controls_extra}
|
|
1434
1471
|
/>
|
|
1435
1472
|
{/if}
|
|
@@ -1489,7 +1526,9 @@
|
|
|
1489
1526
|
.bar-plot :global(.pane-toggle),
|
|
1490
1527
|
.bar-plot .header-controls {
|
|
1491
1528
|
opacity: 0;
|
|
1492
|
-
transition:
|
|
1529
|
+
transition:
|
|
1530
|
+
opacity 0.2s,
|
|
1531
|
+
background-color 0.2s;
|
|
1493
1532
|
}
|
|
1494
1533
|
.bar-plot:hover :global(.pane-toggle),
|
|
1495
1534
|
.bar-plot:hover .header-controls,
|