matterviz 0.3.7 → 0.4.0
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 +8 -3
- package/dist/brillouin/BrillouinZone.svelte.d.ts +2 -1
- package/dist/brillouin/BrillouinZoneScene.svelte +52 -6
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -0
- package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
- package/dist/brillouin/compute.js +10 -14
- package/dist/chempot-diagram/ChemPotDiagram.svelte +14 -13
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +12 -15
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +8 -10
- package/dist/chempot-diagram/async-compute.svelte.js +3 -1
- package/dist/chempot-diagram/chempot-worker.js +2 -1
- package/dist/chempot-diagram/compute.d.ts +1 -1
- package/dist/chempot-diagram/compute.js +17 -19
- package/dist/colors/index.js +6 -5
- package/dist/composition/FormulaFilter.svelte +12 -6
- package/dist/composition/PieChart.svelte +6 -5
- package/dist/composition/chem-sys.d.ts +8 -0
- package/dist/composition/chem-sys.js +85 -0
- package/dist/composition/format.js +4 -2
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/index.js +1 -0
- package/dist/composition/parse.js +25 -13
- package/dist/convex-hull/ConvexHull2D.svelte +12 -10
- package/dist/convex-hull/ConvexHull3D.svelte +5 -5
- package/dist/convex-hull/ConvexHull4D.svelte +5 -9
- package/dist/convex-hull/ConvexHullStats.svelte +12 -12
- package/dist/convex-hull/GasPressureControls.svelte +4 -4
- package/dist/convex-hull/TemperatureSlider.svelte +2 -2
- 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 +3 -0
- package/dist/convex-hull/helpers.js +17 -9
- package/dist/convex-hull/index.d.ts +1 -1
- package/dist/convex-hull/thermodynamics.js +83 -78
- package/dist/convex-hull/types.d.ts +1 -1
- package/dist/coordination/CoordinationBarPlot.svelte +23 -23
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/element/ElementTile.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSlice.svelte +13 -5
- package/dist/fermi-surface/FermiSurface.svelte +11 -5
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +3 -0
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
- package/dist/fermi-surface/compute.js +59 -59
- package/dist/fermi-surface/export.js +3 -2
- package/dist/fermi-surface/parse.js +7 -4
- package/dist/fermi-surface/types.d.ts +1 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +23 -21
- package/dist/heatmap-matrix/index.js +1 -1
- package/dist/io/decompress.js +4 -2
- package/dist/io/export.d.ts +4 -4
- package/dist/io/export.js +47 -25
- package/dist/io/fetch.js +5 -1
- package/dist/io/file-drop.d.ts +1 -1
- package/dist/io/file-drop.js +35 -36
- package/dist/io/url-drop.js +64 -33
- package/dist/isosurface/parse.js +6 -7
- 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 +8 -7
- package/dist/layout/PropertyFilter.svelte +3 -2
- package/dist/layout/SettingsSection.svelte +1 -1
- 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 +5 -1
- package/dist/math.js +24 -9
- package/dist/overlays/DraggablePane.svelte +4 -4
- package/dist/periodic-table/PeriodicTable.svelte +20 -9
- 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.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
- package/dist/phase-diagram/build-diagram.js +2 -2
- 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} +229 -587
- package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +5 -5
- 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} +6 -6
- 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 +1462 -0
- package/dist/plot/box/BoxPlot.svelte.d.ts +94 -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 +55 -0
- package/dist/plot/box/box-plot.js +126 -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 +16 -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.js → core/auto-place.js} +2 -2
- 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} +36 -33
- package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +2 -2
- 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} +30 -13
- package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +7 -5
- package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +3 -2
- 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} +4 -4
- package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +2 -2
- package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +7 -7
- package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +2 -2
- 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} +3 -5
- 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 +33 -0
- package/dist/plot/core/fill-utils.js +388 -0
- package/dist/plot/{hover-lock.svelte.js → core/hover-lock.svelte.js} +5 -6
- package/dist/plot/core/index.d.ts +10 -0
- package/dist/plot/core/index.js +11 -0
- package/dist/plot/core/interactions.d.ts +35 -0
- package/dist/plot/core/interactions.js +195 -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/{reference-line.d.ts → core/reference-line.d.ts} +1 -1
- package/dist/plot/{reference-line.js → core/reference-line.js} +23 -36
- package/dist/plot/{scales.d.ts → core/scales.d.ts} +2 -2
- package/dist/plot/{scales.js → core/scales.js} +84 -85
- package/dist/plot/core/svg.d.ts +2 -0
- package/dist/plot/core/svg.js +41 -0
- package/dist/plot/{types.d.ts → core/types.d.ts} +19 -79
- package/dist/plot/{types.js → core/types.js} +1 -1
- package/dist/plot/{utils → core/utils}/label-placement.d.ts +2 -2
- 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 +11 -0
- package/dist/plot/core/utils.js +27 -0
- package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +154 -294
- 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 +700 -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 +187 -0
- package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +61 -59
- package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +4 -4
- 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} +221 -642
- package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +7 -7
- package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
- package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +1 -1
- 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} +3 -3
- 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} +12 -10
- package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +7 -7
- package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +5 -4
- package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +2 -2
- package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +11 -11
- package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +3 -3
- package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +1 -1
- package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +1 -1
- 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 +1045 -0
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +96 -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 +266 -0
- package/dist/rdf/RdfPlot.svelte +2 -1
- package/dist/rdf/calc-rdf.js +11 -24
- package/dist/sanitize.js +1 -1
- package/dist/settings.d.ts +65 -1
- package/dist/settings.js +262 -0
- package/dist/spectral/Bands.svelte +39 -29
- package/dist/spectral/Bands.svelte.d.ts +3 -4
- package/dist/spectral/BandsAndDos.svelte +1 -1
- package/dist/spectral/BrillouinBandsDos.svelte +39 -27
- package/dist/spectral/Dos.svelte +10 -19
- package/dist/spectral/Dos.svelte.d.ts +2 -2
- package/dist/spectral/helpers.d.ts +3 -1
- package/dist/spectral/helpers.js +95 -29
- package/dist/structure/AtomLegend.svelte +8 -9
- package/dist/structure/CellSelect.svelte +1 -2
- package/dist/structure/Cylinder.svelte +12 -8
- package/dist/structure/Cylinder.svelte.d.ts +4 -1
- package/dist/structure/Structure.svelte +78 -72
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +5 -6
- package/dist/structure/StructureScene.svelte +11 -10
- package/dist/structure/atom-properties.js +6 -6
- package/dist/structure/bond-order-perception.js +1 -1
- package/dist/structure/bonding.d.ts +1 -0
- package/dist/structure/bonding.js +43 -15
- package/dist/structure/export.js +27 -23
- package/dist/structure/index.d.ts +2 -4
- package/dist/structure/index.js +1 -3
- package/dist/structure/label-placement.js +4 -4
- package/dist/structure/measure.d.ts +3 -2
- package/dist/structure/measure.js +6 -5
- package/dist/structure/parse.js +121 -103
- package/dist/structure/pbc.js +4 -0
- package/dist/symmetry/SymmetryStats.svelte +2 -2
- package/dist/symmetry/index.d.ts +1 -1
- package/dist/symmetry/index.js +22 -24
- package/dist/symmetry/spacegroups.d.ts +7 -0
- package/dist/symmetry/spacegroups.js +48 -13
- package/dist/table/HeatmapTable.svelte +63 -11
- 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 +66 -40
- package/dist/trajectory/Trajectory.svelte.d.ts +2 -1
- package/dist/trajectory/TrajectoryExportPane.svelte +2 -1
- package/dist/trajectory/TrajectoryInfoPane.svelte +2 -1
- package/dist/trajectory/format-detect.d.ts +1 -0
- package/dist/trajectory/format-detect.js +25 -11
- package/dist/trajectory/frame-reader.js +17 -50
- package/dist/trajectory/helpers.js +1 -1
- package/dist/trajectory/index.js +1 -1
- package/dist/trajectory/parse/hdf5.js +1 -1
- package/dist/trajectory/parse/index.js +14 -6
- package/dist/trajectory/parse/vasp.js +36 -17
- package/dist/trajectory/parse/xyz.d.ts +24 -0
- package/dist/trajectory/parse/xyz.js +102 -89
- package/dist/trajectory/plotting.d.ts +1 -1
- package/dist/trajectory/plotting.js +15 -15
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +6 -4
- package/dist/xrd/XrdPlot.svelte +2 -1
- package/dist/xrd/calc-xrd.js +15 -12
- package/dist/xrd/parse.js +2 -2
- package/package.json +22 -18
- 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/interactions.d.ts +0 -12
- package/dist/plot/interactions.js +0 -101
- 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/{auto-place.d.ts → core/auto-place.d.ts} +0 -0
- /package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +0 -0
- /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
- /package/dist/plot/{hover-lock.svelte.d.ts → core/hover-lock.svelte.d.ts} +0 -0
- /package/dist/plot/{utils → core/utils}/label-placement.js +0 -0
- /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { BasePlotProps, LegendConfig, SankeyData, SankeyHandlerProps, SankeyLinkColorMode, SankeyLinkHandlerProps, SankeyNodeAlign, SankeyNodeHandlerProps, SankeyOrientation } from '..';
|
|
2
|
+
import type { Sides } from '../core/layout';
|
|
3
|
+
import { type PositionedLink, type PositionedNode } from './sankey';
|
|
4
|
+
import { type Snippet } from 'svelte';
|
|
5
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
6
|
+
declare function $$render<Metadata extends Record<string, unknown> = Record<string, unknown>>(): {
|
|
7
|
+
props: HTMLAttributes<HTMLDivElement> & Omit<BasePlotProps, "change"> & {
|
|
8
|
+
data?: SankeyData<Metadata>;
|
|
9
|
+
orientation?: SankeyOrientation;
|
|
10
|
+
node_width?: number;
|
|
11
|
+
node_padding?: number;
|
|
12
|
+
node_align?: SankeyNodeAlign;
|
|
13
|
+
iterations?: number;
|
|
14
|
+
link_opacity?: number;
|
|
15
|
+
link_color_mode?: SankeyLinkColorMode;
|
|
16
|
+
show_node_labels?: boolean;
|
|
17
|
+
node_label?: (node: PositionedNode) => string;
|
|
18
|
+
value_format?: string;
|
|
19
|
+
padding?: Sides;
|
|
20
|
+
legend?: LegendConfig | null;
|
|
21
|
+
show_legend?: boolean;
|
|
22
|
+
tooltip?: Snippet<[SankeyHandlerProps<Metadata>]>;
|
|
23
|
+
node_content?: Snippet<[{
|
|
24
|
+
node: PositionedNode;
|
|
25
|
+
color: string;
|
|
26
|
+
}]>;
|
|
27
|
+
link_content?: Snippet<[{
|
|
28
|
+
link: PositionedLink;
|
|
29
|
+
color: string;
|
|
30
|
+
}]>;
|
|
31
|
+
change?: (data: SankeyHandlerProps<Metadata> | null) => void;
|
|
32
|
+
on_node_click?: (data: SankeyNodeHandlerProps<Metadata> & {
|
|
33
|
+
event: MouseEvent | KeyboardEvent;
|
|
34
|
+
}) => void;
|
|
35
|
+
on_node_hover?: (data: (SankeyNodeHandlerProps<Metadata> & {
|
|
36
|
+
event: MouseEvent | FocusEvent;
|
|
37
|
+
}) | null) => void;
|
|
38
|
+
on_link_click?: (data: SankeyLinkHandlerProps<Metadata> & {
|
|
39
|
+
event: MouseEvent | KeyboardEvent;
|
|
40
|
+
}) => void;
|
|
41
|
+
on_link_hover?: (data: (SankeyLinkHandlerProps<Metadata> & {
|
|
42
|
+
event: MouseEvent | FocusEvent;
|
|
43
|
+
}) | null) => void;
|
|
44
|
+
header_controls?: Snippet<[{
|
|
45
|
+
height: number;
|
|
46
|
+
width: number;
|
|
47
|
+
fullscreen: boolean;
|
|
48
|
+
}]>;
|
|
49
|
+
controls_extra?: Snippet<[{
|
|
50
|
+
orientation: SankeyOrientation;
|
|
51
|
+
}]>;
|
|
52
|
+
};
|
|
53
|
+
exports: {};
|
|
54
|
+
bindings: "data" | "orientation" | "show_controls" | "fullscreen" | "hovered" | "controls_open" | "node_align" | "node_width" | "node_padding" | "link_opacity" | "show_node_labels";
|
|
55
|
+
slots: {};
|
|
56
|
+
events: {};
|
|
57
|
+
};
|
|
58
|
+
declare class __sveltets_Render<Metadata extends Record<string, unknown> = Record<string, unknown>> {
|
|
59
|
+
props(): ReturnType<typeof $$render<Metadata>>['props'];
|
|
60
|
+
events(): ReturnType<typeof $$render<Metadata>>['events'];
|
|
61
|
+
slots(): ReturnType<typeof $$render<Metadata>>['slots'];
|
|
62
|
+
bindings(): "data" | "orientation" | "show_controls" | "fullscreen" | "hovered" | "controls_open" | "node_align" | "node_width" | "node_padding" | "link_opacity" | "show_node_labels";
|
|
63
|
+
exports(): {};
|
|
64
|
+
}
|
|
65
|
+
interface $$IsomorphicComponent {
|
|
66
|
+
new <Metadata extends Record<string, unknown> = Record<string, unknown>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Metadata>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Metadata>['props']>, ReturnType<__sveltets_Render<Metadata>['events']>, ReturnType<__sveltets_Render<Metadata>['slots']>> & {
|
|
67
|
+
$$bindings?: ReturnType<__sveltets_Render<Metadata>['bindings']>;
|
|
68
|
+
} & ReturnType<__sveltets_Render<Metadata>['exports']>;
|
|
69
|
+
<Metadata extends Record<string, unknown> = Record<string, unknown>>(internal: unknown, props: ReturnType<__sveltets_Render<Metadata>['props']> & {}): ReturnType<__sveltets_Render<Metadata>['exports']>;
|
|
70
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
71
|
+
}
|
|
72
|
+
declare const Sankey: $$IsomorphicComponent;
|
|
73
|
+
type Sankey<Metadata extends Record<string, unknown> = Record<string, unknown>> = InstanceType<typeof Sankey<Metadata>>;
|
|
74
|
+
export default Sankey;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { SettingsSection } from '../../layout'
|
|
3
|
+
import type { SankeyNodeAlign, SankeyOrientation } from '..'
|
|
4
|
+
import ControlPane from '../core/components/ControlPane.svelte'
|
|
5
|
+
import { DEFAULTS } from '../../settings'
|
|
6
|
+
import type { Snippet } from 'svelte'
|
|
7
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
show_controls = $bindable(true),
|
|
11
|
+
controls_open = $bindable(false),
|
|
12
|
+
orientation = $bindable(DEFAULTS.sankey.orientation),
|
|
13
|
+
node_width = $bindable(DEFAULTS.sankey.node_width),
|
|
14
|
+
node_padding = $bindable(DEFAULTS.sankey.node_padding),
|
|
15
|
+
node_align = $bindable(DEFAULTS.sankey.node_align),
|
|
16
|
+
link_opacity = $bindable(DEFAULTS.sankey.link_opacity),
|
|
17
|
+
show_node_labels = $bindable(DEFAULTS.sankey.show_node_labels),
|
|
18
|
+
toggle_props = {},
|
|
19
|
+
pane_props = {},
|
|
20
|
+
children,
|
|
21
|
+
}: {
|
|
22
|
+
show_controls?: boolean
|
|
23
|
+
controls_open?: boolean
|
|
24
|
+
orientation?: SankeyOrientation
|
|
25
|
+
node_width?: number
|
|
26
|
+
node_padding?: number
|
|
27
|
+
node_align?: SankeyNodeAlign
|
|
28
|
+
link_opacity?: number
|
|
29
|
+
show_node_labels?: boolean
|
|
30
|
+
toggle_props?: HTMLAttributes<HTMLButtonElement>
|
|
31
|
+
pane_props?: HTMLAttributes<HTMLDivElement>
|
|
32
|
+
children?: Snippet
|
|
33
|
+
} = $props()
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
{#if show_controls}
|
|
37
|
+
<ControlPane bind:controls_open controls_class="sankey" {toggle_props} {pane_props}>
|
|
38
|
+
{@render children?.()}
|
|
39
|
+
<SettingsSection
|
|
40
|
+
title="Sankey"
|
|
41
|
+
current_values={{
|
|
42
|
+
orientation,
|
|
43
|
+
node_align,
|
|
44
|
+
node_width,
|
|
45
|
+
node_padding,
|
|
46
|
+
link_opacity,
|
|
47
|
+
show_node_labels,
|
|
48
|
+
}}
|
|
49
|
+
on_reset={() => {
|
|
50
|
+
;({
|
|
51
|
+
orientation,
|
|
52
|
+
node_align,
|
|
53
|
+
node_width,
|
|
54
|
+
node_padding,
|
|
55
|
+
link_opacity,
|
|
56
|
+
show_node_labels,
|
|
57
|
+
} = DEFAULTS.sankey)
|
|
58
|
+
}}
|
|
59
|
+
style="display: flex; flex-wrap: wrap; gap: 2ex"
|
|
60
|
+
>
|
|
61
|
+
<label style="flex: 1">
|
|
62
|
+
Orientation:
|
|
63
|
+
<select bind:value={orientation}>
|
|
64
|
+
<option value="horizontal">Horizontal</option>
|
|
65
|
+
<option value="vertical">Vertical</option>
|
|
66
|
+
</select>
|
|
67
|
+
</label>
|
|
68
|
+
<label style="flex: 1">
|
|
69
|
+
Node align:
|
|
70
|
+
<select bind:value={node_align}>
|
|
71
|
+
<option value="justify">Justify</option>
|
|
72
|
+
<option value="left">Left</option>
|
|
73
|
+
<option value="right">Right</option>
|
|
74
|
+
<option value="center">Center</option>
|
|
75
|
+
</select>
|
|
76
|
+
</label>
|
|
77
|
+
<label style="flex: 1 1 100%">
|
|
78
|
+
Node width:
|
|
79
|
+
<input type="range" min="4" max="60" step="1" bind:value={node_width} />
|
|
80
|
+
<input type="number" min="4" max="60" step="1" bind:value={node_width} />
|
|
81
|
+
</label>
|
|
82
|
+
<label style="flex: 1 1 100%">
|
|
83
|
+
Node padding:
|
|
84
|
+
<input type="range" min="0" max="40" step="1" bind:value={node_padding} />
|
|
85
|
+
<input type="number" min="0" max="40" step="1" bind:value={node_padding} />
|
|
86
|
+
</label>
|
|
87
|
+
<label style="flex: 1 1 100%">
|
|
88
|
+
Link opacity:
|
|
89
|
+
<input type="range" min="0.05" max="1" step="0.05" bind:value={link_opacity} />
|
|
90
|
+
<input type="number" min="0.05" max="1" step="0.05" bind:value={link_opacity} />
|
|
91
|
+
</label>
|
|
92
|
+
<label style="flex: 1 1 100%">
|
|
93
|
+
<input type="checkbox" bind:checked={show_node_labels} />
|
|
94
|
+
Show node labels
|
|
95
|
+
</label>
|
|
96
|
+
</SettingsSection>
|
|
97
|
+
</ControlPane>
|
|
98
|
+
{/if}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SankeyNodeAlign, SankeyOrientation } from '..';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
type $$ComponentProps = {
|
|
5
|
+
show_controls?: boolean;
|
|
6
|
+
controls_open?: boolean;
|
|
7
|
+
orientation?: SankeyOrientation;
|
|
8
|
+
node_width?: number;
|
|
9
|
+
node_padding?: number;
|
|
10
|
+
node_align?: SankeyNodeAlign;
|
|
11
|
+
link_opacity?: number;
|
|
12
|
+
show_node_labels?: boolean;
|
|
13
|
+
toggle_props?: HTMLAttributes<HTMLButtonElement>;
|
|
14
|
+
pane_props?: HTMLAttributes<HTMLDivElement>;
|
|
15
|
+
children?: Snippet;
|
|
16
|
+
};
|
|
17
|
+
declare const SankeyControls: import("svelte").Component<$$ComponentProps, {}, "orientation" | "show_controls" | "controls_open" | "node_align" | "node_width" | "node_padding" | "link_opacity" | "show_node_labels">;
|
|
18
|
+
type SankeyControls = ReturnType<typeof SankeyControls>;
|
|
19
|
+
export default SankeyControls;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type SankeyOrientation = `horizontal` | `vertical`;
|
|
2
|
+
export type SankeyNodeAlign = `left` | `right` | `center` | `justify`;
|
|
3
|
+
export type SankeyLinkColorMode = `source` | `target` | `gradient` | `static`;
|
|
4
|
+
export interface SankeyNode<Metadata = Record<string, unknown>> {
|
|
5
|
+
id?: string | number;
|
|
6
|
+
label?: string;
|
|
7
|
+
color?: string;
|
|
8
|
+
metadata?: Metadata;
|
|
9
|
+
}
|
|
10
|
+
export interface SankeyLink<Metadata = Record<string, unknown>> {
|
|
11
|
+
source: number | string;
|
|
12
|
+
target: number | string;
|
|
13
|
+
value: number;
|
|
14
|
+
color?: string;
|
|
15
|
+
label?: string;
|
|
16
|
+
metadata?: Metadata;
|
|
17
|
+
}
|
|
18
|
+
export interface SankeyData<Metadata = Record<string, unknown>> {
|
|
19
|
+
nodes: SankeyNode<Metadata>[];
|
|
20
|
+
links: SankeyLink<Metadata>[];
|
|
21
|
+
}
|
|
22
|
+
export interface SankeyNodeHandlerProps<Metadata = Record<string, unknown>> {
|
|
23
|
+
type: `node`;
|
|
24
|
+
node_idx: number;
|
|
25
|
+
id: string | number;
|
|
26
|
+
label?: string;
|
|
27
|
+
value: number;
|
|
28
|
+
color: string;
|
|
29
|
+
metadata?: Metadata;
|
|
30
|
+
}
|
|
31
|
+
export interface SankeyLinkHandlerProps<Metadata = Record<string, unknown>> {
|
|
32
|
+
type: `link`;
|
|
33
|
+
link_idx: number;
|
|
34
|
+
source_idx: number;
|
|
35
|
+
target_idx: number;
|
|
36
|
+
source_label?: string;
|
|
37
|
+
target_label?: string;
|
|
38
|
+
value: number;
|
|
39
|
+
color: string;
|
|
40
|
+
metadata?: Metadata;
|
|
41
|
+
}
|
|
42
|
+
export type SankeyHandlerProps<Metadata = Record<string, unknown>> = SankeyNodeHandlerProps<Metadata> | SankeyLinkHandlerProps<Metadata>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { sankeyCenter, sankeyJustify, sankeyLeft, sankeyRight } from 'd3-sankey';
|
|
2
|
+
import type { SankeyLink as D3Link, SankeyNode as D3Node } from 'd3-sankey';
|
|
3
|
+
import type { SankeyData, SankeyNodeAlign, SankeyOrientation } from '../core/types';
|
|
4
|
+
interface NodeExtra {
|
|
5
|
+
node_idx: number;
|
|
6
|
+
id: string | number;
|
|
7
|
+
label?: string;
|
|
8
|
+
color?: string;
|
|
9
|
+
}
|
|
10
|
+
interface LinkExtra {
|
|
11
|
+
link_idx: number;
|
|
12
|
+
color?: string;
|
|
13
|
+
label?: string;
|
|
14
|
+
}
|
|
15
|
+
export type PositionedNode = D3Node<NodeExtra, LinkExtra> & {
|
|
16
|
+
node_idx: number;
|
|
17
|
+
id: string | number;
|
|
18
|
+
x0: number;
|
|
19
|
+
x1: number;
|
|
20
|
+
y0: number;
|
|
21
|
+
y1: number;
|
|
22
|
+
value: number;
|
|
23
|
+
depth: number;
|
|
24
|
+
};
|
|
25
|
+
export type PositionedLink = D3Link<NodeExtra, LinkExtra> & {
|
|
26
|
+
link_idx: number;
|
|
27
|
+
width: number;
|
|
28
|
+
source: PositionedNode;
|
|
29
|
+
target: PositionedNode;
|
|
30
|
+
path: string;
|
|
31
|
+
mid: {
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export interface SankeyLayoutOptions {
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
node_width?: number;
|
|
40
|
+
node_padding?: number;
|
|
41
|
+
node_align?: SankeyNodeAlign;
|
|
42
|
+
orientation?: SankeyOrientation;
|
|
43
|
+
iterations?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface SankeyLayoutResult {
|
|
46
|
+
nodes: PositionedNode[];
|
|
47
|
+
links: PositionedLink[];
|
|
48
|
+
}
|
|
49
|
+
export declare function sankey_from_links(source: readonly number[], target: readonly number[], value: readonly number[], labels?: readonly string[]): SankeyData;
|
|
50
|
+
export declare function compute_sankey_layout<Metadata = Record<string, unknown>>(data: SankeyData<Metadata>, opts: SankeyLayoutOptions): SankeyLayoutResult;
|
|
51
|
+
export declare const sankey_align_fn: (align: SankeyNodeAlign) => typeof sankeyLeft | typeof sankeyRight | typeof sankeyCenter | typeof sankeyJustify;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// Layout helpers for Sankey diagrams, wrapping d3-sankey.
|
|
2
|
+
// Single source of truth for node/link positioning math so the component stays
|
|
3
|
+
// declarative and the layout is independently unit-testable.
|
|
4
|
+
import { sankey as d3_sankey, sankeyCenter, sankeyJustify, sankeyLeft, sankeyRight, } from 'd3-sankey';
|
|
5
|
+
const ALIGN_FNS = {
|
|
6
|
+
left: sankeyLeft,
|
|
7
|
+
right: sankeyRight,
|
|
8
|
+
center: sankeyCenter,
|
|
9
|
+
justify: sankeyJustify,
|
|
10
|
+
};
|
|
11
|
+
// Resolve a link source/target reference (id or index) to a node array index.
|
|
12
|
+
// Prefers id lookup (ids may be numeric), falls back to treating numbers as indices.
|
|
13
|
+
function resolve_node_ref(ref, id_to_idx, n_nodes) {
|
|
14
|
+
const by_id = id_to_idx.get(ref);
|
|
15
|
+
if (by_id !== undefined)
|
|
16
|
+
return by_id;
|
|
17
|
+
if (typeof ref === `number` && Number.isInteger(ref) && ref >= 0 && ref < n_nodes) {
|
|
18
|
+
return ref;
|
|
19
|
+
}
|
|
20
|
+
throw new Error(`Sankey link references unknown node: ${JSON.stringify(ref)}`);
|
|
21
|
+
}
|
|
22
|
+
function resolve_numeric_node_ref(ref, n_nodes) {
|
|
23
|
+
if (Number.isInteger(ref) && ref >= 0 && ref < n_nodes)
|
|
24
|
+
return ref;
|
|
25
|
+
throw new Error(`Sankey link references unknown node: ${JSON.stringify(ref)}`);
|
|
26
|
+
}
|
|
27
|
+
// Build a SankeyData object from parallel flat arrays (e.g. the plotly/matbench
|
|
28
|
+
// `link.source`/`link.target`/`link.value` + `node.label` format).
|
|
29
|
+
export function sankey_from_links(source, target, value, labels) {
|
|
30
|
+
if (source.length !== target.length || source.length !== value.length) {
|
|
31
|
+
throw new Error(`sankey_from_links: source (${source.length}), target (${target.length}) and value (${value.length}) must have equal length`);
|
|
32
|
+
}
|
|
33
|
+
// Single pass instead of Math.max(...source, ...target): spreading large index arrays
|
|
34
|
+
// (e.g. spacegroup correspondence matrices) as call args can exceed the arg-count limit.
|
|
35
|
+
let max_idx = -1;
|
|
36
|
+
for (const idx of source)
|
|
37
|
+
if (idx > max_idx)
|
|
38
|
+
max_idx = idx;
|
|
39
|
+
for (const idx of target)
|
|
40
|
+
if (idx > max_idx)
|
|
41
|
+
max_idx = idx;
|
|
42
|
+
// Cover the highest indexed link even when labels is shorter (missing labels fall
|
|
43
|
+
// back to the index string below), so links never reference a non-existent node.
|
|
44
|
+
const n_nodes = Math.max(labels?.length ?? 0, max_idx + 1);
|
|
45
|
+
const nodes = Array.from({ length: n_nodes }, (_, idx) => ({
|
|
46
|
+
id: idx,
|
|
47
|
+
label: labels?.[idx] ?? `${idx}`,
|
|
48
|
+
}));
|
|
49
|
+
const links = source.map((src, idx) => ({
|
|
50
|
+
source: src,
|
|
51
|
+
target: target[idx],
|
|
52
|
+
value: value[idx],
|
|
53
|
+
}));
|
|
54
|
+
return { nodes, links };
|
|
55
|
+
}
|
|
56
|
+
// Vertical ribbon path: mirror of d3's sankeyLinkHorizontal but flowing top->bottom.
|
|
57
|
+
// Reads the raw d3 layout fields (link.y0/y1 are stacking-axis centers, which in
|
|
58
|
+
// vertical mode map to screen x; source.x1/target.x0 are depth positions = screen y).
|
|
59
|
+
function vertical_link_path(link) {
|
|
60
|
+
const x0 = link.y0 ?? 0;
|
|
61
|
+
const x1 = link.y1 ?? 0;
|
|
62
|
+
const y0 = link.source.x1;
|
|
63
|
+
const y1 = link.target.x0;
|
|
64
|
+
const ym = (y0 + y1) / 2;
|
|
65
|
+
return `M${x0},${y0}C${x0},${ym} ${x1},${ym} ${x1},${y1}`;
|
|
66
|
+
}
|
|
67
|
+
function horizontal_link_path(link) {
|
|
68
|
+
const x0 = link.source.x1;
|
|
69
|
+
const x1 = link.target.x0;
|
|
70
|
+
const y0 = link.y0 ?? 0;
|
|
71
|
+
const y1 = link.y1 ?? 0;
|
|
72
|
+
const xm = (x0 + x1) / 2;
|
|
73
|
+
return `M${x0},${y0}C${xm},${y0} ${xm},${y1} ${x1},${y1}`;
|
|
74
|
+
}
|
|
75
|
+
// Compute node boxes and link ribbon paths in screen space.
|
|
76
|
+
// Clones input so the (reactive) user data is never mutated by d3-sankey.
|
|
77
|
+
export function compute_sankey_layout(data, opts) {
|
|
78
|
+
const { width, height, node_width = 24, node_padding = 12, node_align = `justify`, orientation = `horizontal`, iterations = 6, } = opts;
|
|
79
|
+
// All-zero link values would make d3-sankey divide by zero (NaN ribbon paths)
|
|
80
|
+
const has_flow = data.links.some((link) => link.value > 0);
|
|
81
|
+
if (!(width > 0) || !(height > 0) || data.nodes.length === 0 || !has_flow)
|
|
82
|
+
return { nodes: [], links: [] };
|
|
83
|
+
// Resolve ids -> indices and clone into fresh objects (d3 mutates these).
|
|
84
|
+
// Links may reference a node by explicit `id`, or by `label` when no id is set,
|
|
85
|
+
// or by zero-based index (handled as a fallback in resolve_node_ref).
|
|
86
|
+
const needs_ref_lookup = data.links.some((link) => typeof link.source !== `number` || typeof link.target !== `number`) || data.nodes.some((node, idx) => typeof node.id === `number` && node.id !== idx);
|
|
87
|
+
let id_to_idx;
|
|
88
|
+
if (needs_ref_lookup) {
|
|
89
|
+
id_to_idx = new Map();
|
|
90
|
+
data.nodes.forEach((node, idx) => {
|
|
91
|
+
const key = node.id ?? node.label;
|
|
92
|
+
if (key === undefined)
|
|
93
|
+
return; // index-only node, resolved via fallback
|
|
94
|
+
if (id_to_idx?.has(key)) {
|
|
95
|
+
console.warn(`Sankey: duplicate node ${node.id !== undefined ? `id` : `label`} "${key}" — links resolve to the last occurrence. Set unique \`id\`s.`);
|
|
96
|
+
}
|
|
97
|
+
id_to_idx?.set(key, idx);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const node_copies = data.nodes.map((node, idx) => ({
|
|
101
|
+
node_idx: idx,
|
|
102
|
+
id: node.id ?? idx,
|
|
103
|
+
label: node.label,
|
|
104
|
+
color: node.color,
|
|
105
|
+
}));
|
|
106
|
+
// Resolve a source/target ref to a node index: id/label lookup when any link uses
|
|
107
|
+
// non-numeric refs, otherwise a cheap numeric-range check (no map built).
|
|
108
|
+
const resolve_ref = (ref) => needs_ref_lookup
|
|
109
|
+
? resolve_node_ref(ref, id_to_idx, data.nodes.length)
|
|
110
|
+
: resolve_numeric_node_ref(ref, data.nodes.length);
|
|
111
|
+
const link_copies = data.links.map((link, idx) => ({
|
|
112
|
+
link_idx: idx,
|
|
113
|
+
color: link.color,
|
|
114
|
+
label: link.label,
|
|
115
|
+
source: resolve_ref(link.source),
|
|
116
|
+
target: resolve_ref(link.target),
|
|
117
|
+
value: link.value,
|
|
118
|
+
}));
|
|
119
|
+
// Drop nodes with no incoming or outgoing links. d3-sankey gives such orphans
|
|
120
|
+
// value 0 (zero height) and still stacks them with node_padding each, so extra
|
|
121
|
+
// labels pile up and overflow past the plot edge. They are never referenced by a
|
|
122
|
+
// link, so removing them can't break link resolution (node_idx stays stable).
|
|
123
|
+
const linked_node_idxs = new Set();
|
|
124
|
+
for (const link of link_copies) {
|
|
125
|
+
linked_node_idxs.add(link.source);
|
|
126
|
+
linked_node_idxs.add(link.target);
|
|
127
|
+
}
|
|
128
|
+
const used_nodes = node_copies.filter((node) => linked_node_idxs.has(node.node_idx));
|
|
129
|
+
const is_vertical = orientation === `vertical`;
|
|
130
|
+
// d3 lays out left->right (depth on x). For vertical we run in a transposed
|
|
131
|
+
// extent (depth on what becomes screen y) then swap node boxes afterwards.
|
|
132
|
+
const extent = is_vertical
|
|
133
|
+
? [
|
|
134
|
+
[0, 0],
|
|
135
|
+
[height, width],
|
|
136
|
+
]
|
|
137
|
+
: [
|
|
138
|
+
[0, 0],
|
|
139
|
+
[width, height],
|
|
140
|
+
];
|
|
141
|
+
const layout = d3_sankey()
|
|
142
|
+
.nodeId((node) => node.node_idx)
|
|
143
|
+
.nodeWidth(node_width)
|
|
144
|
+
.nodePadding(node_padding)
|
|
145
|
+
.nodeAlign(ALIGN_FNS[node_align])
|
|
146
|
+
.iterations(iterations)
|
|
147
|
+
.extent(extent);
|
|
148
|
+
let graph;
|
|
149
|
+
try {
|
|
150
|
+
graph = layout({ nodes: used_nodes, links: link_copies });
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
154
|
+
throw new Error(`Sankey layout failed (graph must be a DAG without cycles): ${msg}`, {
|
|
155
|
+
cause: err,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
// Build link ribbon paths from raw d3 fields BEFORE transposing node boxes.
|
|
159
|
+
for (const link of graph.links) {
|
|
160
|
+
if (is_vertical) {
|
|
161
|
+
link.path = vertical_link_path(link);
|
|
162
|
+
link.mid = {
|
|
163
|
+
x: ((link.y0 ?? 0) + (link.y1 ?? 0)) / 2,
|
|
164
|
+
y: (link.source.x1 + link.target.x0) / 2,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
link.path = horizontal_link_path(link);
|
|
169
|
+
const x = (link.source.x1 + link.target.x0) / 2;
|
|
170
|
+
const y = ((link.y0 ?? 0) + (link.y1 ?? 0)) / 2;
|
|
171
|
+
link.mid = { x, y };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Transpose node boxes into screen space for vertical orientation
|
|
175
|
+
if (is_vertical) {
|
|
176
|
+
for (const node of graph.nodes) {
|
|
177
|
+
const { x0, x1, y0, y1 } = node;
|
|
178
|
+
node.x0 = y0;
|
|
179
|
+
node.x1 = y1;
|
|
180
|
+
node.y0 = x0;
|
|
181
|
+
node.y1 = x1;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return graph;
|
|
185
|
+
}
|
|
186
|
+
// Map a node alignment string to the d3-sankey alignment function (exposed for tests)
|
|
187
|
+
export const sankey_align_fn = (align) => ALIGN_FNS[align];
|