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,96 @@
|
|
|
1
|
+
import type { D3InterpolateName } from '../../colors';
|
|
2
|
+
import type { BasePlotProps, LegendConfig, SunburstLabelRotation, SunburstLabelText, SunburstNode, SunburstNodeHandlerProps, SunburstShape, SunburstSort, SunburstValueMode } from '..';
|
|
3
|
+
import { ColorBar } from '..';
|
|
4
|
+
import type { Sides } from '../core/layout';
|
|
5
|
+
import { type PositionedArc } from './sunburst';
|
|
6
|
+
import { type ComponentProps, type Snippet } from 'svelte';
|
|
7
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
8
|
+
import { type TweenOptions } from 'svelte/motion';
|
|
9
|
+
declare function $$render<Metadata extends Record<string, unknown> = Record<string, unknown>>(): {
|
|
10
|
+
props: HTMLAttributes<HTMLDivElement> & Omit<BasePlotProps, "change"> & {
|
|
11
|
+
data?: SunburstNode<Metadata> | SunburstNode<Metadata>[];
|
|
12
|
+
shape?: SunburstShape;
|
|
13
|
+
value_mode?: SunburstValueMode;
|
|
14
|
+
sort?: SunburstSort;
|
|
15
|
+
level_lighten?: number;
|
|
16
|
+
min_fraction?: number;
|
|
17
|
+
other_label?: string;
|
|
18
|
+
max_depth?: number;
|
|
19
|
+
inner_radius?: number;
|
|
20
|
+
pad_angle?: number;
|
|
21
|
+
show_labels?: boolean;
|
|
22
|
+
label_rotation?: SunburstLabelRotation;
|
|
23
|
+
label_text?: SunburstLabelText;
|
|
24
|
+
zoom_on_click?: boolean;
|
|
25
|
+
zoom_root_id?: string | number | null;
|
|
26
|
+
show_breadcrumbs?: boolean;
|
|
27
|
+
color_values?: (arc: PositionedArc<Metadata>) => number | null;
|
|
28
|
+
color_scale?: D3InterpolateName;
|
|
29
|
+
color_range?: [number, number];
|
|
30
|
+
colorbar?: ComponentProps<typeof ColorBar> | null;
|
|
31
|
+
export_buttons?: boolean;
|
|
32
|
+
export_filename?: string;
|
|
33
|
+
tween?: TweenOptions<{
|
|
34
|
+
x0: number;
|
|
35
|
+
x1: number;
|
|
36
|
+
y0: number;
|
|
37
|
+
n_rings: number;
|
|
38
|
+
}>;
|
|
39
|
+
value_format?: string;
|
|
40
|
+
padding?: Sides;
|
|
41
|
+
legend?: LegendConfig | null;
|
|
42
|
+
show_legend?: boolean;
|
|
43
|
+
tooltip?: Snippet<[SunburstNodeHandlerProps<Metadata>]>;
|
|
44
|
+
arc_content?: Snippet<[{
|
|
45
|
+
arc: PositionedArc<Metadata>;
|
|
46
|
+
a0: number;
|
|
47
|
+
a1: number;
|
|
48
|
+
r0: number;
|
|
49
|
+
r1: number;
|
|
50
|
+
}]>;
|
|
51
|
+
center_content?: Snippet<[{
|
|
52
|
+
root: PositionedArc<Metadata> | null;
|
|
53
|
+
radius: number;
|
|
54
|
+
zoomed: boolean;
|
|
55
|
+
}]>;
|
|
56
|
+
change?: (data: SunburstNodeHandlerProps<Metadata> | null) => void;
|
|
57
|
+
on_node_click?: (data: SunburstNodeHandlerProps<Metadata> & {
|
|
58
|
+
event: MouseEvent | KeyboardEvent;
|
|
59
|
+
}) => void;
|
|
60
|
+
on_node_hover?: (data: (SunburstNodeHandlerProps<Metadata> & {
|
|
61
|
+
event: MouseEvent | FocusEvent;
|
|
62
|
+
}) | null) => void;
|
|
63
|
+
on_zoom?: (data: {
|
|
64
|
+
root: SunburstNodeHandlerProps<Metadata> | null;
|
|
65
|
+
}) => void;
|
|
66
|
+
header_controls?: Snippet<[{
|
|
67
|
+
height: number;
|
|
68
|
+
width: number;
|
|
69
|
+
fullscreen: boolean;
|
|
70
|
+
}]>;
|
|
71
|
+
controls_extra?: Snippet<[{
|
|
72
|
+
zoom_root_id: string | number | null;
|
|
73
|
+
}]>;
|
|
74
|
+
};
|
|
75
|
+
exports: {};
|
|
76
|
+
bindings: "data" | "show_controls" | "fullscreen" | "hovered" | "controls_open" | "value_mode" | "min_fraction" | "show_labels" | "shape" | "max_depth" | "inner_radius" | "pad_angle" | "label_rotation" | "label_text" | "zoom_on_click" | "show_breadcrumbs" | "zoom_root_id";
|
|
77
|
+
slots: {};
|
|
78
|
+
events: {};
|
|
79
|
+
};
|
|
80
|
+
declare class __sveltets_Render<Metadata extends Record<string, unknown> = Record<string, unknown>> {
|
|
81
|
+
props(): ReturnType<typeof $$render<Metadata>>['props'];
|
|
82
|
+
events(): ReturnType<typeof $$render<Metadata>>['events'];
|
|
83
|
+
slots(): ReturnType<typeof $$render<Metadata>>['slots'];
|
|
84
|
+
bindings(): "data" | "show_controls" | "fullscreen" | "hovered" | "controls_open" | "value_mode" | "min_fraction" | "show_labels" | "shape" | "max_depth" | "inner_radius" | "pad_angle" | "label_rotation" | "label_text" | "zoom_on_click" | "show_breadcrumbs" | "zoom_root_id";
|
|
85
|
+
exports(): {};
|
|
86
|
+
}
|
|
87
|
+
interface $$IsomorphicComponent {
|
|
88
|
+
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']>> & {
|
|
89
|
+
$$bindings?: ReturnType<__sveltets_Render<Metadata>['bindings']>;
|
|
90
|
+
} & ReturnType<__sveltets_Render<Metadata>['exports']>;
|
|
91
|
+
<Metadata extends Record<string, unknown> = Record<string, unknown>>(internal: unknown, props: ReturnType<__sveltets_Render<Metadata>['props']> & {}): ReturnType<__sveltets_Render<Metadata>['exports']>;
|
|
92
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
93
|
+
}
|
|
94
|
+
declare const Sunburst: $$IsomorphicComponent;
|
|
95
|
+
type Sunburst<Metadata extends Record<string, unknown> = Record<string, unknown>> = InstanceType<typeof Sunburst<Metadata>>;
|
|
96
|
+
export default Sunburst;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { SettingsSection } from '../../layout'
|
|
3
|
+
import type {
|
|
4
|
+
SunburstLabelRotation,
|
|
5
|
+
SunburstLabelText,
|
|
6
|
+
SunburstShape,
|
|
7
|
+
SunburstValueMode,
|
|
8
|
+
} from '..'
|
|
9
|
+
import { DEFAULTS, SETTINGS_CONFIG } from '../../settings'
|
|
10
|
+
import type { Snippet } from 'svelte'
|
|
11
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
12
|
+
import ControlPane from '../core/components/ControlPane.svelte'
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
show_controls = $bindable(true),
|
|
16
|
+
controls_open = $bindable(false),
|
|
17
|
+
shape = $bindable(DEFAULTS.sunburst.shape),
|
|
18
|
+
value_mode = $bindable(DEFAULTS.sunburst.value_mode),
|
|
19
|
+
max_depth = $bindable(DEFAULTS.sunburst.max_depth),
|
|
20
|
+
inner_radius = $bindable(DEFAULTS.sunburst.inner_radius),
|
|
21
|
+
pad_angle = $bindable(DEFAULTS.sunburst.pad_angle),
|
|
22
|
+
min_fraction = $bindable(DEFAULTS.sunburst.min_fraction),
|
|
23
|
+
show_labels = $bindable(DEFAULTS.sunburst.show_labels),
|
|
24
|
+
label_rotation = $bindable(DEFAULTS.sunburst.label_rotation),
|
|
25
|
+
label_text = $bindable(DEFAULTS.sunburst.label_text),
|
|
26
|
+
zoom_on_click = $bindable(DEFAULTS.sunburst.zoom_on_click),
|
|
27
|
+
show_breadcrumbs = $bindable(DEFAULTS.sunburst.show_breadcrumbs),
|
|
28
|
+
export_buttons = true,
|
|
29
|
+
on_export,
|
|
30
|
+
toggle_props = {},
|
|
31
|
+
pane_props = {},
|
|
32
|
+
children,
|
|
33
|
+
}: {
|
|
34
|
+
show_controls?: boolean
|
|
35
|
+
controls_open?: boolean
|
|
36
|
+
shape?: SunburstShape
|
|
37
|
+
value_mode?: SunburstValueMode
|
|
38
|
+
max_depth?: number
|
|
39
|
+
inner_radius?: number
|
|
40
|
+
pad_angle?: number
|
|
41
|
+
min_fraction?: number
|
|
42
|
+
show_labels?: boolean
|
|
43
|
+
label_rotation?: SunburstLabelRotation
|
|
44
|
+
label_text?: SunburstLabelText
|
|
45
|
+
zoom_on_click?: boolean
|
|
46
|
+
show_breadcrumbs?: boolean
|
|
47
|
+
export_buttons?: boolean // show SVG/PNG download buttons in the pane
|
|
48
|
+
on_export?: (format: `svg` | `png`) => void
|
|
49
|
+
toggle_props?: HTMLAttributes<HTMLButtonElement>
|
|
50
|
+
pane_props?: HTMLAttributes<HTMLDivElement>
|
|
51
|
+
children?: Snippet
|
|
52
|
+
} = $props()
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
{#if show_controls}
|
|
56
|
+
<!-- snippets live at the template top level (not inside the components below) so
|
|
57
|
+
they're locally renderable rather than treated as ControlPane/SettingsSection props -->
|
|
58
|
+
{#snippet options(enum_map: Record<string, string>)}
|
|
59
|
+
{#each Object.entries(enum_map) as [value, label] (value)}
|
|
60
|
+
<option {value}>{label}</option>
|
|
61
|
+
{/each}
|
|
62
|
+
{/snippet}
|
|
63
|
+
{#snippet num_row(
|
|
64
|
+
text: string,
|
|
65
|
+
[min, max, step]: [number, number, number],
|
|
66
|
+
get: () => number,
|
|
67
|
+
set: (val: number) => void,
|
|
68
|
+
)}
|
|
69
|
+
<label style="flex: 1 1 100%">
|
|
70
|
+
{text}
|
|
71
|
+
<input type="range" {min} {max} {step} bind:value={get, set} />
|
|
72
|
+
<input type="number" {min} {max} {step} bind:value={get, set} />
|
|
73
|
+
</label>
|
|
74
|
+
{/snippet}
|
|
75
|
+
{#snippet check_row(text: string, get: () => boolean, set: (val: boolean) => void)}
|
|
76
|
+
<label style="flex: 1 1 100%">
|
|
77
|
+
<input type="checkbox" bind:checked={get, set} />
|
|
78
|
+
{text}
|
|
79
|
+
</label>
|
|
80
|
+
{/snippet}
|
|
81
|
+
<ControlPane bind:controls_open controls_class="sunburst" {toggle_props} {pane_props}>
|
|
82
|
+
{@render children?.()}
|
|
83
|
+
<SettingsSection
|
|
84
|
+
title="Sunburst"
|
|
85
|
+
current_values={{
|
|
86
|
+
shape,
|
|
87
|
+
value_mode,
|
|
88
|
+
max_depth,
|
|
89
|
+
inner_radius,
|
|
90
|
+
pad_angle,
|
|
91
|
+
min_fraction,
|
|
92
|
+
show_labels,
|
|
93
|
+
label_rotation,
|
|
94
|
+
label_text,
|
|
95
|
+
zoom_on_click,
|
|
96
|
+
show_breadcrumbs,
|
|
97
|
+
}}
|
|
98
|
+
on_reset={() => {
|
|
99
|
+
;({
|
|
100
|
+
shape,
|
|
101
|
+
value_mode,
|
|
102
|
+
max_depth,
|
|
103
|
+
inner_radius,
|
|
104
|
+
pad_angle,
|
|
105
|
+
min_fraction,
|
|
106
|
+
show_labels,
|
|
107
|
+
label_rotation,
|
|
108
|
+
label_text,
|
|
109
|
+
zoom_on_click,
|
|
110
|
+
show_breadcrumbs,
|
|
111
|
+
} = DEFAULTS.sunburst)
|
|
112
|
+
}}
|
|
113
|
+
style="display: flex; flex-wrap: wrap; gap: 2ex"
|
|
114
|
+
>
|
|
115
|
+
<!-- select options come from the settings schema so labels/values have a
|
|
116
|
+
single source of truth -->
|
|
117
|
+
<label style="flex: 1">
|
|
118
|
+
Shape:
|
|
119
|
+
<select bind:value={shape}>
|
|
120
|
+
{@render options(SETTINGS_CONFIG.sunburst.shape.enum ?? {})}
|
|
121
|
+
</select>
|
|
122
|
+
</label>
|
|
123
|
+
<label style="flex: 1">
|
|
124
|
+
Value mode:
|
|
125
|
+
<select bind:value={value_mode}>
|
|
126
|
+
{@render options(SETTINGS_CONFIG.sunburst.value_mode.enum ?? {})}
|
|
127
|
+
</select>
|
|
128
|
+
</label>
|
|
129
|
+
{#if shape === `sunburst`}
|
|
130
|
+
<!-- icicle labels are always horizontal; inner radius/pad angle are polar-only -->
|
|
131
|
+
<label style="flex: 1">
|
|
132
|
+
Labels:
|
|
133
|
+
<select bind:value={label_rotation}>
|
|
134
|
+
{@render options(SETTINGS_CONFIG.sunburst.label_rotation.enum ?? {})}
|
|
135
|
+
</select>
|
|
136
|
+
</label>
|
|
137
|
+
{/if}
|
|
138
|
+
<label style="flex: 1">
|
|
139
|
+
Label text:
|
|
140
|
+
<select bind:value={label_text}>
|
|
141
|
+
{@render options(SETTINGS_CONFIG.sunburst.label_text.enum ?? {})}
|
|
142
|
+
</select>
|
|
143
|
+
</label>
|
|
144
|
+
{@render num_row(`Max depth (0 = all):`, [0, 10, 1], () => max_depth, (val) =>
|
|
145
|
+
max_depth = val)}
|
|
146
|
+
{#if shape === `sunburst`}
|
|
147
|
+
{@render num_row(`Inner radius:`, [0, 0.8, 0.05], () => inner_radius, (val) =>
|
|
148
|
+
inner_radius = val)}
|
|
149
|
+
{@render num_row(`Pad angle (°):`, [0, 4, 0.1], () => pad_angle, (val) =>
|
|
150
|
+
pad_angle = val)}
|
|
151
|
+
{/if}
|
|
152
|
+
{@render num_row(
|
|
153
|
+
`Group slices below (fraction of total):`,
|
|
154
|
+
[0, 0.2, 0.005],
|
|
155
|
+
() => min_fraction,
|
|
156
|
+
(val) => min_fraction = val,
|
|
157
|
+
)}
|
|
158
|
+
{@render check_row(`Show arc labels`, () => show_labels, (val) =>
|
|
159
|
+
show_labels = val)}
|
|
160
|
+
{@render check_row(`Zoom on click`, () => zoom_on_click, (val) =>
|
|
161
|
+
zoom_on_click = val)}
|
|
162
|
+
{@render check_row(`Show breadcrumbs when zoomed`, () => show_breadcrumbs, (val) =>
|
|
163
|
+
show_breadcrumbs = val)}
|
|
164
|
+
</SettingsSection>
|
|
165
|
+
{#if export_buttons && on_export}
|
|
166
|
+
<div class="export-row">
|
|
167
|
+
Export:
|
|
168
|
+
{#each [`svg`, `png`] as const as fmt (fmt)}
|
|
169
|
+
<button
|
|
170
|
+
type="button"
|
|
171
|
+
class="export-btn"
|
|
172
|
+
aria-label="Download {fmt.toUpperCase()}"
|
|
173
|
+
onclick={() => on_export?.(fmt)}
|
|
174
|
+
>{fmt.toUpperCase()}</button>
|
|
175
|
+
{/each}
|
|
176
|
+
</div>
|
|
177
|
+
{/if}
|
|
178
|
+
</ControlPane>
|
|
179
|
+
{/if}
|
|
180
|
+
|
|
181
|
+
<style>
|
|
182
|
+
.export-row {
|
|
183
|
+
display: flex;
|
|
184
|
+
align-items: center;
|
|
185
|
+
gap: 6px;
|
|
186
|
+
margin-top: 6px;
|
|
187
|
+
font-size: 0.85em;
|
|
188
|
+
}
|
|
189
|
+
.export-btn {
|
|
190
|
+
background: var(--sunburst-btn-bg, rgba(128, 128, 128, 0.15));
|
|
191
|
+
color: inherit;
|
|
192
|
+
border: none;
|
|
193
|
+
border-radius: 3pt;
|
|
194
|
+
padding: 1px 6px;
|
|
195
|
+
cursor: pointer;
|
|
196
|
+
}
|
|
197
|
+
.export-btn:hover {
|
|
198
|
+
background: var(--sunburst-btn-hover-bg, rgba(128, 128, 128, 0.35));
|
|
199
|
+
}
|
|
200
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SunburstLabelRotation, SunburstLabelText, SunburstShape, SunburstValueMode } 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
|
+
shape?: SunburstShape;
|
|
8
|
+
value_mode?: SunburstValueMode;
|
|
9
|
+
max_depth?: number;
|
|
10
|
+
inner_radius?: number;
|
|
11
|
+
pad_angle?: number;
|
|
12
|
+
min_fraction?: number;
|
|
13
|
+
show_labels?: boolean;
|
|
14
|
+
label_rotation?: SunburstLabelRotation;
|
|
15
|
+
label_text?: SunburstLabelText;
|
|
16
|
+
zoom_on_click?: boolean;
|
|
17
|
+
show_breadcrumbs?: boolean;
|
|
18
|
+
export_buttons?: boolean;
|
|
19
|
+
on_export?: (format: `svg` | `png`) => void;
|
|
20
|
+
toggle_props?: HTMLAttributes<HTMLButtonElement>;
|
|
21
|
+
pane_props?: HTMLAttributes<HTMLDivElement>;
|
|
22
|
+
children?: Snippet;
|
|
23
|
+
};
|
|
24
|
+
declare const SunburstControls: import("svelte").Component<$$ComponentProps, {}, "show_controls" | "controls_open" | "value_mode" | "min_fraction" | "show_labels" | "shape" | "max_depth" | "inner_radius" | "pad_angle" | "label_rotation" | "label_text" | "zoom_on_click" | "show_breadcrumbs">;
|
|
25
|
+
type SunburstControls = ReturnType<typeof SunburstControls>;
|
|
26
|
+
export default SunburstControls;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { PositionedArc, SunburstLabelRotation, SunburstShape } from './sunburst';
|
|
2
|
+
export interface ScreenArc<Metadata = Record<string, unknown>> {
|
|
3
|
+
arc: PositionedArc<Metadata>;
|
|
4
|
+
a0: number;
|
|
5
|
+
a1: number;
|
|
6
|
+
r0: number;
|
|
7
|
+
r1: number;
|
|
8
|
+
visible: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface ViewWindow {
|
|
11
|
+
x0: number;
|
|
12
|
+
x1: number;
|
|
13
|
+
y0: number;
|
|
14
|
+
n_rings: number;
|
|
15
|
+
}
|
|
16
|
+
export interface ScreenGeometry {
|
|
17
|
+
shape: SunburstShape;
|
|
18
|
+
inner_width: number;
|
|
19
|
+
inner_height: number;
|
|
20
|
+
radius: number;
|
|
21
|
+
hole_r: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function project_arcs<Metadata>(arcs: PositionedArc<Metadata>[], win: ViewWindow, geom: ScreenGeometry): {
|
|
24
|
+
all: ScreenArc<Metadata>[];
|
|
25
|
+
visible: ScreenArc<Metadata>[];
|
|
26
|
+
};
|
|
27
|
+
export declare function arrow_nav_target<Metadata>(arcs: readonly PositionedArc<Metadata>[], is_visible: (idx: number) => boolean, current_idx: number, key: string): number | null;
|
|
28
|
+
export declare function arc_label_transform(d: {
|
|
29
|
+
a0: number;
|
|
30
|
+
a1: number;
|
|
31
|
+
r0: number;
|
|
32
|
+
r1: number;
|
|
33
|
+
}, text_w: number, // rendered text width in px
|
|
34
|
+
shape: SunburstShape, rotation: SunburstLabelRotation): string | null;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Screen-space math for Sunburst/Icicle rendering: projecting normalized partition
|
|
2
|
+
// coordinates through a zoom window into pixels, and fitting labels into arcs/cells.
|
|
3
|
+
// Pure functions (no component state) so the trickiest geometry stays unit-testable;
|
|
4
|
+
// Sunburst.svelte wires them to reactive state and the DOM.
|
|
5
|
+
import { to_degrees } from '../../math';
|
|
6
|
+
const TWO_PI = 2 * Math.PI;
|
|
7
|
+
const clamp01 = (val) => Math.min(1, Math.max(0, val));
|
|
8
|
+
// Project all arcs through a view window into screen space. The two shapes share the
|
|
9
|
+
// same window-mapping math, only the scale constants differ. Returns `all` (indexed
|
|
10
|
+
// by node_idx, for event lookups) and `visible` (collapsed arcs pruned) from one pass.
|
|
11
|
+
export function project_arcs(arcs, win, geom) {
|
|
12
|
+
const span = Math.max(win.x1 - win.x0, 1e-9);
|
|
13
|
+
const icicle = geom.shape === `icicle`;
|
|
14
|
+
const x_scale = icicle ? geom.inner_width : TWO_PI; // angle/x per window fraction
|
|
15
|
+
const y_offset = icicle ? 0 : geom.hole_r;
|
|
16
|
+
const y_unit = (icicle ? geom.inner_height : Math.max(0, geom.radius - geom.hole_r)) /
|
|
17
|
+
Math.max(win.n_rings, 1e-9); // px per ring
|
|
18
|
+
const min_x_extent = icicle ? 0.1 : 1e-6;
|
|
19
|
+
// Window fraction -> angle/x (clamped: out-of-window arcs collapse to zero extent
|
|
20
|
+
// and animate smoothly through the clamps during zoom tweens)
|
|
21
|
+
const x_of = (frac) => clamp01((frac - win.x0) / span) * x_scale;
|
|
22
|
+
// Ring offset below the zoom root -> radius/y, clamped into the visible rings
|
|
23
|
+
const y_of = (ring) => y_offset + Math.min(Math.max(ring - win.y0 - 1, 0), win.n_rings) * y_unit;
|
|
24
|
+
const all = [];
|
|
25
|
+
const visible = [];
|
|
26
|
+
for (const arc of arcs) {
|
|
27
|
+
const a0 = x_of(arc.x0);
|
|
28
|
+
const a1 = x_of(arc.x1);
|
|
29
|
+
const r0 = y_of(arc.y0);
|
|
30
|
+
const r1 = y_of(arc.y1);
|
|
31
|
+
const is_visible = arc.depth > 0 && a1 - a0 > min_x_extent && r1 - r0 > 0.1;
|
|
32
|
+
const screen = { arc, a0, a1, r0, r1, visible: is_visible };
|
|
33
|
+
all.push(screen);
|
|
34
|
+
if (screen.visible)
|
|
35
|
+
visible.push(screen);
|
|
36
|
+
}
|
|
37
|
+
return { all, visible };
|
|
38
|
+
}
|
|
39
|
+
// Arrow-key navigation over the pre-order arc array: ArrowLeft/ArrowRight cycle
|
|
40
|
+
// through visible siblings (wrapping), ArrowDown enters the first child, ArrowUp
|
|
41
|
+
// returns to the parent (never the hidden root at depth 0). Visibility is delegated
|
|
42
|
+
// to is_visible (the component supplies screen-space collapse state). Returns the
|
|
43
|
+
// target node_idx, or null when the key isn't an arrow key or no target qualifies.
|
|
44
|
+
export function arrow_nav_target(arcs, is_visible, current_idx, key) {
|
|
45
|
+
if (![`ArrowRight`, `ArrowLeft`, `ArrowUp`, `ArrowDown`].includes(key))
|
|
46
|
+
return null;
|
|
47
|
+
const cur = arcs[current_idx];
|
|
48
|
+
if (!cur)
|
|
49
|
+
return null;
|
|
50
|
+
if (key === `ArrowDown`) {
|
|
51
|
+
// pre-order: a branch's first child directly follows it
|
|
52
|
+
const child = arcs[cur.node_idx + 1];
|
|
53
|
+
return child && child.parent_idx === cur.node_idx && is_visible(child.node_idx)
|
|
54
|
+
? child.node_idx
|
|
55
|
+
: null;
|
|
56
|
+
}
|
|
57
|
+
const parent = cur.parent_idx != null ? arcs[cur.parent_idx] : null;
|
|
58
|
+
if (key === `ArrowUp`) {
|
|
59
|
+
return parent && parent.depth > 0 && is_visible(parent.node_idx) ? parent.node_idx : null;
|
|
60
|
+
}
|
|
61
|
+
// Walk siblings via the contiguous pre-order subtree ranges (each sibling starts
|
|
62
|
+
// right after the previous one's subtree ends) - pre-order also matches angular
|
|
63
|
+
// order, so no sorting needed and no full-arcs scan per keypress
|
|
64
|
+
const last = parent?.subtree_end ?? arcs.length - 1;
|
|
65
|
+
const siblings = [];
|
|
66
|
+
for (let idx = (parent?.node_idx ?? 0) + 1; idx <= last; idx = arcs[idx].subtree_end + 1) {
|
|
67
|
+
if (is_visible(idx))
|
|
68
|
+
siblings.push(idx);
|
|
69
|
+
}
|
|
70
|
+
if (siblings.length < 2)
|
|
71
|
+
return null;
|
|
72
|
+
const pos = siblings.indexOf(cur.node_idx);
|
|
73
|
+
const step = key === `ArrowRight` ? 1 : -1;
|
|
74
|
+
return siblings[(pos + step + siblings.length) % siblings.length];
|
|
75
|
+
}
|
|
76
|
+
// Arc label placement: fit the text radially or tangentially (whichever has more room
|
|
77
|
+
// in 'auto' mode); null = doesn't fit, hide the label. Angles are clockwise from 12
|
|
78
|
+
// o'clock, so the point at (a, r) is (sin(a)*r, -cos(a)*r). Icicle cells label
|
|
79
|
+
// horizontally, or rotated 90° when too narrow but tall enough to fit upright.
|
|
80
|
+
export function arc_label_transform(d, text_w, // rendered text width in px
|
|
81
|
+
shape, rotation) {
|
|
82
|
+
// Text fits when it's shorter than the space along its reading direction and the
|
|
83
|
+
// cell is at least one line-height across
|
|
84
|
+
const fits = (along, across) => text_w <= along - 6 && across >= 12;
|
|
85
|
+
if (shape === `icicle`) {
|
|
86
|
+
const cell_w = d.a1 - d.a0;
|
|
87
|
+
const cell_h = d.r1 - d.r0;
|
|
88
|
+
const center = `translate(${(d.a0 + d.a1) / 2}, ${(d.r0 + d.r1) / 2})`;
|
|
89
|
+
// Horizontal when the text fits the row width; otherwise rotate 90° (read
|
|
90
|
+
// bottom-up) to use a thin-but-tall cell's height. Only cells too small in both
|
|
91
|
+
// dimensions stay unlabeled.
|
|
92
|
+
if (fits(cell_w, cell_h))
|
|
93
|
+
return center;
|
|
94
|
+
if (fits(cell_h, cell_w))
|
|
95
|
+
return `${center} rotate(-90)`;
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const mid_a = (d.a0 + d.a1) / 2;
|
|
99
|
+
const mid_r = (d.r0 + d.r1) / 2;
|
|
100
|
+
const angular_px = (d.a1 - d.a0) * mid_r; // arc length at mid radius
|
|
101
|
+
const radial_px = d.r1 - d.r0;
|
|
102
|
+
const mode = rotation === `auto` ? (radial_px >= angular_px ? `radial` : `tangential`) : rotation;
|
|
103
|
+
if (mode === `horizontal`) {
|
|
104
|
+
if (!fits(Math.max(angular_px, radial_px), Math.min(angular_px, radial_px))) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
return `translate(${Math.sin(mid_a) * mid_r}, ${-Math.cos(mid_a) * mid_r})`;
|
|
108
|
+
}
|
|
109
|
+
if (mode === `radial`) {
|
|
110
|
+
if (!fits(radial_px, angular_px))
|
|
111
|
+
return null;
|
|
112
|
+
// Read outward, flipped on the left half so text is never upside down
|
|
113
|
+
const deg = to_degrees(mid_a) - 90;
|
|
114
|
+
const flip = mid_a > Math.PI ? 180 : 0;
|
|
115
|
+
return `rotate(${deg}) translate(${mid_r}, 0) rotate(${flip})`;
|
|
116
|
+
}
|
|
117
|
+
// tangential: follow the circumference, flipped on the bottom half
|
|
118
|
+
if (!fits(angular_px, radial_px))
|
|
119
|
+
return null;
|
|
120
|
+
const upside_down = mid_a > Math.PI / 2 && mid_a < (3 * Math.PI) / 2;
|
|
121
|
+
return `rotate(${to_degrees(mid_a)}) translate(0, ${-mid_r}) rotate(${upside_down ? 180 : 0})`;
|
|
122
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export type SunburstValueMode = `leaf-sum` | `total` | `remainder`;
|
|
2
|
+
export type SunburstLabelRotation = `auto` | `radial` | `tangential` | `horizontal`;
|
|
3
|
+
export type SunburstSort = `descending` | `ascending` | `none`;
|
|
4
|
+
export type SunburstLabelText = `label` | `value` | `percent` | `label+value` | `label+percent`;
|
|
5
|
+
export type SunburstShape = `sunburst` | `icicle`;
|
|
6
|
+
export interface SunburstNode<Metadata = Record<string, unknown>> {
|
|
7
|
+
id?: string | number;
|
|
8
|
+
label?: string;
|
|
9
|
+
value?: number;
|
|
10
|
+
color?: string;
|
|
11
|
+
children?: SunburstNode<Metadata>[];
|
|
12
|
+
metadata?: Metadata;
|
|
13
|
+
}
|
|
14
|
+
export interface SunburstNodeHandlerProps<Metadata = Record<string, unknown>> extends Omit<PositionedArc<Metadata>, `x0` | `x1` | `y0` | `y1` | `subtree_end` | `parent_idx`> {
|
|
15
|
+
type: `node`;
|
|
16
|
+
parent_id: string | number | null;
|
|
17
|
+
}
|
|
18
|
+
export interface PositionedArc<Metadata = Record<string, unknown>> {
|
|
19
|
+
node_idx: number;
|
|
20
|
+
subtree_end: number;
|
|
21
|
+
parent_idx: number | null;
|
|
22
|
+
id: string | number;
|
|
23
|
+
label?: string;
|
|
24
|
+
value: number;
|
|
25
|
+
color: string;
|
|
26
|
+
depth: number;
|
|
27
|
+
is_leaf: boolean;
|
|
28
|
+
path: (string | number)[];
|
|
29
|
+
label_path: string[];
|
|
30
|
+
fraction: number;
|
|
31
|
+
parent_fraction: number;
|
|
32
|
+
is_other?: boolean;
|
|
33
|
+
x0: number;
|
|
34
|
+
x1: number;
|
|
35
|
+
y0: number;
|
|
36
|
+
y1: number;
|
|
37
|
+
metadata?: Metadata;
|
|
38
|
+
}
|
|
39
|
+
export interface SunburstLayoutOptions {
|
|
40
|
+
value_mode?: SunburstValueMode;
|
|
41
|
+
sort?: SunburstSort;
|
|
42
|
+
level_lighten?: number;
|
|
43
|
+
min_fraction?: number;
|
|
44
|
+
other_label?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface SunburstLayoutResult<Metadata = Record<string, unknown>> {
|
|
47
|
+
arcs: PositionedArc<Metadata>[];
|
|
48
|
+
root: PositionedArc<Metadata> | null;
|
|
49
|
+
max_depth: number;
|
|
50
|
+
}
|
|
51
|
+
export declare function compute_sunburst_layout<Metadata = Record<string, unknown>>(data: SunburstNode<Metadata> | SunburstNode<Metadata>[], opts?: SunburstLayoutOptions): SunburstLayoutResult<Metadata>;
|
|
52
|
+
export declare function sunburst_from_paths<Metadata = Record<string, unknown>>(rows: readonly {
|
|
53
|
+
path: readonly (string | number)[];
|
|
54
|
+
value: number;
|
|
55
|
+
color?: string;
|
|
56
|
+
metadata?: Metadata;
|
|
57
|
+
}[]): SunburstNode<Metadata>[];
|
|
58
|
+
export declare function sunburst_from_labels_parents<Metadata = Record<string, unknown>>(labels: readonly string[], parents: readonly (string | null | undefined)[], values?: readonly number[], opts?: {
|
|
59
|
+
ids?: readonly (string | number)[];
|
|
60
|
+
colors?: readonly (string | undefined)[];
|
|
61
|
+
metadata?: readonly (Metadata | undefined)[];
|
|
62
|
+
}): SunburstNode<Metadata>[];
|