@fundar/data-chart-telling 1.17.0 → 1.19.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/CHANGELOG.md +59 -0
- package/README.md +2 -1
- package/dist/configuration/config.svelte.js +4 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +4 -1
- package/dist/layout/coordinates/CoordinatesLayout.svelte +3 -1
- package/dist/layout/geometry/GeometryLayout.svelte +222 -53
- package/dist/layout/geometry/ScaleFreeContext.d.ts +31 -0
- package/dist/layout/geometry/ScaleFreeContext.js +65 -0
- package/dist/layout/geometry/ScaleFreeMarks.svelte +14 -0
- package/dist/layout/geometry/ScaleFreeMarks.svelte.d.ts +7 -0
- package/dist/layout/geometry/ScaleGate.svelte.d.ts +8 -0
- package/dist/layout/geometry/ScaleGate.svelte.js +95 -0
- package/dist/layout/geometry/ScaleGateMarks.svelte +15 -0
- package/dist/layout/geometry/ScaleGateMarks.svelte.d.ts +7 -0
- package/dist/layout/hover/HoverDefaults.d.ts +52 -0
- package/dist/layout/hover/HoverDefaults.js +96 -0
- package/dist/layout/hover/HoverLayers.d.ts +35 -0
- package/dist/layout/hover/HoverLayers.js +122 -0
- package/dist/layout/hover/HoverSettings.d.ts +1 -3
- package/dist/layout/hover/HoverSettings.js +3 -2
- package/dist/layout/hover/HoverShapes.d.ts +56 -0
- package/dist/layout/hover/HoverShapes.js +163 -0
- package/dist/layout/hover/PlotHover.svelte.d.ts +18 -0
- package/dist/layout/hover/PlotHover.svelte.js +54 -1
- package/dist/layout/legend/LegendState.svelte.d.ts +2 -0
- package/dist/layout/legend/LegendState.svelte.js +5 -0
- package/dist/layout/margins/Box.d.ts +4 -0
- package/dist/layout/margins/Box.js +14 -0
- package/dist/layout/margins/PlotMargins.svelte.js +26 -1
- package/dist/layout/plot/{Plot.svelte.d.ts → AbstractPlot.svelte.d.ts} +3 -3
- package/dist/layout/plot/Core.svelte +2 -2
- package/dist/layout/plot/PublicPlotContext.d.ts +6 -0
- package/dist/layout/plot/PublicPlotContext.js +8 -0
- package/dist/layout/styles/ValueLabels.d.ts +118 -59
- package/dist/layout/styles/ValueLabels.js +313 -146
- package/dist/layout/tooltip/TooltipState.svelte.d.ts +8 -9
- package/dist/layout/tooltip/TooltipState.svelte.js +28 -29
- package/dist/markers/MarkerKinds.d.ts +84 -1
- package/dist/markers/MarkerKinds.js +150 -23
- package/dist/markers/area/AreaMarker.svelte +1 -1
- package/dist/markers/band/BandMarker.svelte +74 -0
- package/dist/markers/band/BandMarker.svelte.d.ts +7 -0
- package/dist/markers/band/Bands.d.ts +16 -0
- package/dist/markers/band/Bands.js +48 -0
- package/dist/markers/bar/BarMarker.svelte +29 -70
- package/dist/markers/bollinger/BollingerMarker.svelte +1 -1
- package/dist/markers/box/BoxMarker.svelte +1 -1
- package/dist/markers/dot/DotRadius.d.ts +11 -0
- package/dist/markers/dot/DotRadius.js +21 -0
- package/dist/markers/hover/HoverMarker.svelte +7 -265
- package/dist/markers/hover/HoverMarker.svelte.d.ts +4 -27
- package/dist/markers/labels/CurveLabel.svelte +56 -0
- package/dist/markers/labels/CurveLabel.svelte.d.ts +9 -0
- package/dist/markers/labels/LabelMerge.d.ts +11 -0
- package/dist/markers/labels/LabelMerge.js +87 -0
- package/dist/markers/labels/MarkerLabel.svelte +36 -0
- package/dist/markers/labels/MarkerLabel.svelte.d.ts +10 -0
- package/dist/markers/labels/MarkerLabels.d.ts +52 -0
- package/dist/markers/labels/MarkerLabels.js +97 -0
- package/dist/markers/labels/geometry/BoxGeometry.d.ts +8 -0
- package/dist/markers/labels/geometry/BoxGeometry.js +101 -0
- package/dist/markers/labels/geometry/CurveGeometry.d.ts +34 -0
- package/dist/markers/labels/geometry/CurveGeometry.js +193 -0
- package/dist/markers/labels/geometry/PointGeometry.d.ts +9 -0
- package/dist/markers/labels/geometry/PointGeometry.js +22 -0
- package/dist/markers/labels/layouts/BoxLayout.d.ts +10 -0
- package/dist/markers/labels/layouts/BoxLayout.js +49 -0
- package/dist/markers/labels/layouts/PathLayout.d.ts +11 -0
- package/dist/markers/labels/layouts/PathLayout.js +91 -0
- package/dist/markers/labels/layouts/PointLayout.d.ts +19 -0
- package/dist/markers/labels/layouts/PointLayout.js +94 -0
- package/dist/markers/regression/RegressionMarker.svelte +1 -1
- package/dist/markers/text/Covering.d.ts +13 -0
- package/dist/markers/text/Covering.js +29 -0
- package/dist/markers/text/Declutter.d.ts +24 -3
- package/dist/markers/text/Declutter.js +46 -3
- package/dist/markers/text/TextMarker.svelte +90 -17
- package/dist/markers/text/TextMarker.svelte.d.ts +1 -1
- package/dist/markers/tick/TickMarker.svelte +1 -1
- package/dist/markers/utils/MarkerChannels.d.ts +1 -1
- package/dist/markers/utils/MarkerChannels.js +3 -2
- package/dist/markers/utils/PointPixel.d.ts +37 -0
- package/dist/markers/utils/PointPixel.js +44 -0
- package/dist/markers/violin/ViolinMarker.svelte +1 -1
- package/dist/markers/waffle/WaffleMarker.svelte +1 -1
- package/dist/phases/Pipeline.d.ts +7 -7
- package/dist/phases/Pipeline.js +12 -9
- package/dist/phases/context/ContextPhase.d.ts +22 -0
- package/dist/phases/context/ContextPhase.js +23 -0
- package/dist/phases/context/RowContext.d.ts +37 -0
- package/dist/phases/context/RowContext.js +97 -0
- package/dist/phases/data/DataPhase.d.ts +4 -4
- package/dist/phases/data/DataPhase.js +7 -7
- package/dist/phases/hover/HoverPhase.d.ts +6 -7
- package/dist/phases/hover/HoverPhase.js +28 -23
- package/dist/phases/mapping/MappingPhase.d.ts +4 -4
- package/dist/phases/mapping/MappingPhase.js +2 -2
- package/dist/phases/markers/MarkerStyles.d.ts +8 -0
- package/dist/phases/markers/MarkerStyles.js +24 -6
- package/dist/phases/markers/MarkersPhase.d.ts +6 -7
- package/dist/phases/markers/MarkersPhase.js +18 -12
- package/dist/phases/scales/ScalesPhase.d.ts +4 -4
- package/dist/phases/scales/ScalesPhase.js +4 -4
- package/dist/phases/sharedScales/SharedScalesPhase.d.ts +2 -2
- package/dist/phases/sharedScales/SharedScalesPhase.js +2 -2
- package/dist/phases/statistics/MarkerGrouping.d.ts +0 -9
- package/dist/phases/statistics/MarkerGrouping.js +5 -48
- package/dist/phases/statistics/MarkerInheritance.d.ts +11 -0
- package/dist/phases/statistics/MarkerInheritance.js +25 -0
- package/dist/phases/statistics/MarkerOrientation.d.ts +26 -0
- package/dist/phases/statistics/MarkerOrientation.js +29 -0
- package/dist/phases/statistics/StatisticsPhase.js +15 -15
- package/dist/phases/styles/StylesPhase.d.ts +3 -3
- package/dist/phases/styles/StylesPhase.js +2 -2
- package/dist/phases/tooltip/TooltipPhase.d.ts +4 -4
- package/dist/phases/tooltip/TooltipPhase.js +10 -7
- package/dist/phases/transforms/TransformsPhase.d.ts +3 -3
- package/dist/phases/transforms/TransformsPhase.js +7 -5
- package/dist/plots/correlation/heatmap/Plot.svelte +2 -2
- package/dist/plots/correlation/heatmap/Plot.svelte.d.ts +0 -1
- package/dist/plots/correlation/heatmap/defaults.d.ts +2 -2
- package/dist/plots/correlation/heatmap/defaults.js +35 -7
- package/dist/plots/correlation/heatmap/markers.d.ts +2 -8
- package/dist/plots/correlation/heatmap/markers.js +8 -11
- package/dist/plots/correlation/scatter/Plot.svelte +2 -2
- package/dist/plots/correlation/scatter/Plot.svelte.d.ts +0 -1
- package/dist/plots/correlation/scatter/defaults.d.ts +2 -2
- package/dist/plots/correlation/scatter/defaults.js +18 -6
- package/dist/plots/correlation/scatter/markers.d.ts +2 -11
- package/dist/plots/correlation/scatter/markers.js +24 -30
- package/dist/plots/distribution/box/BoxSummaries.d.ts +22 -8
- package/dist/plots/distribution/box/BoxSummaries.js +99 -40
- package/dist/plots/distribution/box/Plot.svelte +2 -2
- package/dist/plots/distribution/box/Plot.svelte.d.ts +0 -1
- package/dist/plots/distribution/box/defaults.d.ts +2 -2
- package/dist/plots/distribution/box/defaults.js +20 -6
- package/dist/plots/distribution/box/markers.d.ts +2 -2
- package/dist/plots/distribution/box/markers.js +13 -4
- package/dist/plots/distribution/density/Plot.svelte +2 -2
- package/dist/plots/distribution/density/Plot.svelte.d.ts +0 -1
- package/dist/plots/distribution/density/defaults.d.ts +2 -2
- package/dist/plots/distribution/density/defaults.js +33 -1
- package/dist/plots/distribution/density/markers.d.ts +2 -2
- package/dist/plots/distribution/density/markers.js +9 -5
- package/dist/plots/distribution/histogram/Plot.svelte +2 -2
- package/dist/plots/distribution/histogram/Plot.svelte.d.ts +0 -1
- package/dist/plots/distribution/histogram/defaults.d.ts +2 -2
- package/dist/plots/distribution/histogram/defaults.js +36 -36
- package/dist/plots/distribution/histogram/markers.d.ts +2 -2
- package/dist/plots/distribution/histogram/markers.js +7 -6
- package/dist/plots/distribution/pyramid/Plot.svelte +2 -2
- package/dist/plots/distribution/pyramid/Plot.svelte.d.ts +0 -1
- package/dist/plots/distribution/pyramid/defaults.d.ts +2 -2
- package/dist/plots/distribution/pyramid/defaults.js +13 -3
- package/dist/plots/distribution/pyramid/markers.d.ts +2 -10
- package/dist/plots/distribution/pyramid/markers.js +9 -18
- package/dist/plots/distribution/violin/Plot.svelte +2 -2
- package/dist/plots/distribution/violin/Plot.svelte.d.ts +0 -1
- package/dist/plots/distribution/violin/defaults.d.ts +2 -2
- package/dist/plots/distribution/violin/defaults.js +20 -7
- package/dist/plots/distribution/violin/markers.d.ts +2 -2
- package/dist/plots/distribution/violin/markers.js +30 -6
- package/dist/plots/evolution/area/Plot.svelte +2 -2
- package/dist/plots/evolution/area/Plot.svelte.d.ts +0 -1
- package/dist/plots/evolution/area/defaults.d.ts +2 -2
- package/dist/plots/evolution/area/defaults.js +5 -8
- package/dist/plots/evolution/area/markers.d.ts +2 -2
- package/dist/plots/evolution/area/markers.js +7 -5
- package/dist/plots/evolution/line/Plot.svelte +2 -2
- package/dist/plots/evolution/line/Plot.svelte.d.ts +0 -1
- package/dist/plots/evolution/line/defaults.d.ts +2 -2
- package/dist/plots/evolution/line/defaults.js +5 -7
- package/dist/plots/evolution/line/markers.d.ts +2 -2
- package/dist/plots/evolution/line/markers.js +6 -4
- package/dist/plots/evolution/slope/Plot.svelte +2 -2
- package/dist/plots/evolution/slope/Plot.svelte.d.ts +0 -1
- package/dist/plots/evolution/slope/defaults.d.ts +2 -2
- package/dist/plots/evolution/slope/defaults.js +11 -6
- package/dist/plots/evolution/slope/markers.d.ts +6 -5
- package/dist/plots/evolution/slope/markers.js +19 -12
- package/dist/plots/evolution/sparkline/Plot.svelte +2 -2
- package/dist/plots/evolution/sparkline/Plot.svelte.d.ts +0 -1
- package/dist/plots/evolution/sparkline/defaults.d.ts +2 -2
- package/dist/plots/evolution/sparkline/defaults.js +5 -2
- package/dist/plots/evolution/sparkline/markers.d.ts +2 -2
- package/dist/plots/evolution/sparkline/markers.js +6 -4
- package/dist/plots/generic/Plot.svelte +42 -0
- package/dist/plots/generic/Plot.svelte.d.ts +25 -0
- package/dist/plots/generic/defaults.d.ts +4 -0
- package/dist/plots/generic/defaults.js +7 -0
- package/dist/plots/map/geo/Core.svelte +3 -3
- package/dist/plots/map/geo/Plot.svelte +2 -2
- package/dist/plots/map/geo/Plot.svelte.d.ts +0 -1
- package/dist/plots/map/geo/defaults.d.ts +2 -2
- package/dist/plots/map/geo/phases/data.d.ts +1 -1
- package/dist/plots/map/geo/phases/data.js +1 -1
- package/dist/plots/map/geo/phases/hover.d.ts +2 -2
- package/dist/plots/map/geo/phases/hover.js +3 -3
- package/dist/plots/map/geo/phases/markers.d.ts +2 -2
- package/dist/plots/map/geo/phases/markers.js +3 -3
- package/dist/plots/map/geo/phases/scales.d.ts +2 -2
- package/dist/plots/map/geo/phases/scales.js +2 -2
- package/dist/plots/part-of-a-whole/treemap/Plot.svelte +2 -2
- package/dist/plots/part-of-a-whole/treemap/Plot.svelte.d.ts +0 -1
- package/dist/plots/part-of-a-whole/treemap/defaults.d.ts +2 -2
- package/dist/plots/part-of-a-whole/treemap/defaults.js +38 -22
- package/dist/plots/ranking/bar/Plot.svelte +2 -2
- package/dist/plots/ranking/bar/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/bar/defaults.d.ts +2 -2
- package/dist/plots/ranking/bar/defaults.js +26 -10
- package/dist/plots/ranking/bar/markers.d.ts +3 -3
- package/dist/plots/ranking/bar/markers.js +17 -33
- package/dist/plots/ranking/bullet/Plot.svelte +2 -2
- package/dist/plots/ranking/bullet/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/bullet/defaults.d.ts +2 -2
- package/dist/plots/ranking/bullet/defaults.js +24 -4
- package/dist/plots/ranking/bullet/markers.d.ts +3 -3
- package/dist/plots/ranking/bullet/markers.js +16 -10
- package/dist/plots/ranking/cleveland/ClevelandMarkers.d.ts +4 -11
- package/dist/plots/ranking/cleveland/ClevelandMarkers.js +73 -54
- package/dist/plots/ranking/cleveland/Plot.svelte +2 -2
- package/dist/plots/ranking/cleveland/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/cleveland/defaults.d.ts +2 -2
- package/dist/plots/ranking/cleveland/defaults.js +39 -5
- package/dist/plots/ranking/dumbbell/Plot.svelte +2 -2
- package/dist/plots/ranking/dumbbell/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/dumbbell/defaults.d.ts +2 -2
- package/dist/plots/ranking/forest/Plot.svelte +2 -2
- package/dist/plots/ranking/forest/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/forest/defaults.d.ts +2 -2
- package/dist/plots/ranking/lollipop/Plot.svelte +2 -2
- package/dist/plots/ranking/lollipop/Plot.svelte.d.ts +0 -1
- package/dist/plots/ranking/lollipop/defaults.d.ts +2 -2
- package/dist/types/configuration/styling.d.ts +4 -0
- package/dist/types/layout/context.d.ts +23 -0
- package/dist/types/layout/context.js +1 -0
- package/dist/types/layout/hover.d.ts +3 -0
- package/dist/types/layout/styles/bullet.d.ts +4 -1
- package/dist/types/layout/styles/values.d.ts +59 -13
- package/dist/types/layout/tooltip.d.ts +5 -10
- package/dist/types/markers/axis/area.d.ts +5 -1
- package/dist/types/markers/axis/axisBasedMarkersConfig.d.ts +2 -1
- package/dist/types/markers/axis/band.d.ts +24 -0
- package/dist/types/markers/axis/band.js +1 -0
- package/dist/types/markers/axis/bar.d.ts +7 -4
- package/dist/types/markers/axis/bollinger.d.ts +2 -1
- package/dist/types/markers/axis/box.d.ts +2 -1
- package/dist/types/markers/axis/cell.d.ts +4 -1
- package/dist/types/markers/axis/hover.d.ts +60 -15
- package/dist/types/markers/axis/line.d.ts +4 -1
- package/dist/types/markers/axis/rect.d.ts +4 -1
- package/dist/types/markers/axis/regression.d.ts +2 -1
- package/dist/types/markers/axis/tick.d.ts +2 -1
- package/dist/types/markers/axis/trail.d.ts +4 -1
- package/dist/types/markers/axis/violin.d.ts +2 -1
- package/dist/types/markers/axis/waffle.d.ts +5 -1
- package/dist/types/markers/basic/dot.d.ts +4 -1
- package/dist/types/markers/basic/text.d.ts +25 -21
- package/dist/types/markers/channels/commonMarkerConfig.d.ts +6 -2
- package/dist/types/markers/channels/commonMarkerConfigWithLabel.d.ts +5 -9
- package/dist/types/markers/channels/commonMarkerConfigWithOrientation.d.ts +5 -0
- package/dist/types/markers/channels/commonMarkerConfigWithOrientation.js +1 -0
- package/dist/types/markers/common.d.ts +1 -0
- package/dist/types/markers/common.js +1 -0
- package/dist/types/markers/labels/box.d.ts +57 -0
- package/dist/types/markers/labels/box.js +1 -0
- package/dist/types/markers/labels/common.d.ts +15 -0
- package/dist/types/markers/labels/common.js +1 -0
- package/dist/types/markers/labels/path.d.ts +52 -0
- package/dist/types/markers/labels/path.js +1 -0
- package/dist/types/markers/labels/point.d.ts +40 -0
- package/dist/types/markers/labels/point.js +1 -0
- package/dist/types/markers/traits.d.ts +10 -0
- package/dist/types/phases/context/phase.d.ts +7 -0
- package/dist/types/phases/context/phase.js +1 -0
- package/dist/types/phases/data/phase.d.ts +2 -2
- package/dist/types/phases/hover/phase.d.ts +10 -7
- package/dist/types/phases/index.d.ts +2 -1
- package/dist/types/phases/kind.d.ts +11 -8
- package/dist/types/phases/mapping/phase.d.ts +2 -2
- package/dist/types/phases/markers/phase.d.ts +3 -10
- package/dist/types/phases/scales/phase.d.ts +4 -4
- package/dist/types/phases/stage.d.ts +3 -3
- package/dist/types/phases/state.d.ts +1 -1
- package/dist/types/phases/statistics/phase.d.ts +8 -3
- package/dist/types/phases/styles/phase.d.ts +18 -5
- package/dist/types/phases/transforms/phase.d.ts +4 -2
- package/dist/types/plots/constants.d.ts +3 -17
- package/dist/types/plots/correlation/heatmap/props.d.ts +3 -2
- package/dist/types/plots/correlation/heatmap/state.d.ts +2 -2
- package/dist/types/plots/correlation/scatter/props.d.ts +3 -2
- package/dist/types/plots/correlation/scatter/state.d.ts +2 -2
- package/dist/types/plots/distribution/box/props.d.ts +28 -2
- package/dist/types/plots/distribution/box/state.d.ts +6 -17
- package/dist/types/plots/distribution/density/props.d.ts +2 -1
- package/dist/types/plots/distribution/density/state.d.ts +2 -2
- package/dist/types/plots/distribution/histogram/props.d.ts +16 -2
- package/dist/types/plots/distribution/histogram/state.d.ts +2 -2
- package/dist/types/plots/distribution/pyramid/props.d.ts +3 -2
- package/dist/types/plots/distribution/pyramid/state.d.ts +2 -2
- package/dist/types/plots/distribution/violin/props.d.ts +6 -2
- package/dist/types/plots/distribution/violin/state.d.ts +2 -2
- package/dist/types/plots/evolution/area/props.d.ts +3 -2
- package/dist/types/plots/evolution/area/state.d.ts +2 -2
- package/dist/types/plots/evolution/line/props.d.ts +3 -2
- package/dist/types/plots/evolution/line/state.d.ts +2 -2
- package/dist/types/plots/evolution/slope/state.d.ts +2 -2
- package/dist/types/plots/evolution/sparkline/state.d.ts +2 -2
- package/dist/types/plots/generic/props.d.ts +16 -0
- package/dist/types/plots/generic/props.js +1 -0
- package/dist/types/plots/generic/state.d.ts +4 -0
- package/dist/types/plots/generic/state.js +1 -0
- package/dist/types/plots/map/geo/state.d.ts +1 -1
- package/dist/types/plots/part-of-a-whole/treemap/props.d.ts +18 -6
- package/dist/types/plots/part-of-a-whole/treemap/state.d.ts +2 -2
- package/dist/types/plots/props.d.ts +3 -0
- package/dist/types/plots/ranking/bar/props.d.ts +3 -2
- package/dist/types/plots/ranking/bar/state.d.ts +2 -2
- package/dist/types/plots/ranking/bullet/state.d.ts +2 -2
- package/dist/types/plots/ranking/cleveland/props.d.ts +3 -2
- package/dist/types/plots/ranking/cleveland/state.d.ts +2 -2
- package/dist/types/plots/ranking/dumbbell/props.d.ts +3 -2
- package/dist/types/plots/ranking/dumbbell/state.d.ts +2 -2
- package/dist/types/plots/ranking/forest/props.d.ts +5 -2
- package/dist/types/plots/ranking/forest/state.d.ts +2 -2
- package/dist/types/plots/ranking/lollipop/props.d.ts +3 -2
- package/dist/types/plots/ranking/lollipop/state.d.ts +2 -2
- package/docs/architecture.md +9 -9
- package/docs/markers.md +36 -6
- package/docs/plots/evolution/line.md +1 -1
- package/docs/plots/evolution/slope.md +1 -1
- package/docs/plots/part-of-a-whole/treemap.md +36 -2
- package/docs/plots/ranking/bar.md +1 -0
- package/docs/plots/ranking/cleveland.md +1 -1
- package/docs/state.md +33 -0
- package/docs/styles-and-segments.md +2 -15
- package/docs/theming.md +2 -1
- package/docs/tooltip-and-hover.md +81 -3
- package/docs/value-labels.md +159 -0
- package/examples/BarValues.svelte +1 -1
- package/examples/LineDates.svelte +1 -1
- package/examples/ResponsiveLine.svelte +3 -1
- package/examples/TreemapHover.svelte +25 -0
- package/examples/ValueLabels.svelte +1 -1
- package/llms-full.txt +9 -7
- package/llms.txt +3 -1
- package/package.json +3 -1
- package/dist/markers/utils/BoxLabel.d.ts +0 -58
- package/dist/markers/utils/BoxLabel.js +0 -175
- package/dist/markers/utils/MarkerLabel.svelte +0 -33
- package/dist/markers/utils/MarkerLabel.svelte.d.ts +0 -10
- /package/dist/layout/plot/{Plot.svelte → AbstractPlot.svelte} +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Value labels
|
|
2
|
+
|
|
3
|
+
A plot can write its values on its own shapes: the value of each bar, the last value of each line, the count of each bin. They are the plot's `styles.values`. This page goes from turning them on to placing them precisely; the _Layout/Values_ stories in Storybook show every option drawn.
|
|
4
|
+
|
|
5
|
+
## Turning them on
|
|
6
|
+
|
|
7
|
+
```svelte
|
|
8
|
+
<BarPlot {data} x="province" y="value" styles={{ values: { show: true } }} />
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Setting any option of `styles.values` turns the labels on, so `show: true` is only needed alone: `styles={{ values: { decimals: 1 } }}` draws them too. `show: false` turns them off whatever else is set. A heatmap and a treemap show theirs by default.
|
|
12
|
+
|
|
13
|
+
Each plot kind places them its own way: past the tip of each bar, beside the last point of each line, on a free spot around each dot of a scatter, in the middle of each cell. The rest of this page is about changing that.
|
|
14
|
+
|
|
15
|
+
## What a label says
|
|
16
|
+
|
|
17
|
+
A label writes the value it labels - its row context's `value` - as `decimals`, `prefix`, `suffix` and `signDisplay` ask, over the configuration's `numbers` (see [Number format](theming.md#number-format)):
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
styles: { values: { decimals: 1, signDisplay: 'always', suffix: ' yrs' } }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`format(value, number, context)` writes anything else. `number` writes a value as the fields above ask; `context` is what the plot knows of the labelled row (see [Row context](state.md#row-context)): its `series`, its `row` with the other fields of the data, and what the plot kind works out, such as a histogram bin's `count` or a treemap tile's `share`.
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
format: (value, number, { series, row }) => `${row.country}: ${number(value)}`;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Which values of a row
|
|
30
|
+
|
|
31
|
+
Most plots have one value per row. On a plot whose rows have several, each one is a **part** of the row's context, and `parts` picks the ones written:
|
|
32
|
+
|
|
33
|
+
| Plot | Parts | Default |
|
|
34
|
+
| --------- | ------------------------------------------------------------ | -------------------------- |
|
|
35
|
+
| Box | `'min'`, `'p25'`, `'median'`, `'p75'`, `'max'`, `'outliers'` | `['min', 'median', 'max']` |
|
|
36
|
+
| Violin | the same | `['median']` |
|
|
37
|
+
| Bullet | `'value'` (its bar), `'target'`, `'ranges'` (each bound) | `['value']` |
|
|
38
|
+
| Forest | `'value'` (its estimate), `'lower'`, `'upper'` | `['value']` |
|
|
39
|
+
| Any other | `'value'` | `['value']` |
|
|
40
|
+
|
|
41
|
+
Each part is written beside its shape at its own value: a box's beside the box, an interval's ends past each end. A part holding several values - a box's `'outliers'`, a bullet's `'ranges'` - writes a label for each. `parts` is a list, or a record turning each on (`true`) or giving it options of its own - where it sits, its `format`:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
styles: { values: { parts: ['median'] } }
|
|
45
|
+
styles: { values: { parts: { median: true, max: { format: (v) => `max ${v}` } }, series: 'virginica' } }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Its type takes only the parts of the plot, and `format`'s `context.part` names the one written. A worked-out part - a quartile - is rounded to two decimals first.
|
|
49
|
+
|
|
50
|
+
## Which rows
|
|
51
|
+
|
|
52
|
+
`select` picks the rows labelled of each group: `'first'`, `'last'`, `'min'`, `'max'`, or a list of them. A group is a series on a line or area plot (where the default is `'last'`) and a category on the plots that join dots; elsewhere every row is labelled. `series` labels only the series named.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
styles: { values: { select: ['min', 'max'], series: 'female' } }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
On a bar, a heatmap or a histogram, `select` applies to the `'point'` layout below, which labels some shapes and leaves the others bare.
|
|
59
|
+
|
|
60
|
+
## Layouts
|
|
61
|
+
|
|
62
|
+
Where a label goes is its layout, one of three, named by the geometry it is laid out on:
|
|
63
|
+
|
|
64
|
+
| Layout | Where | Example |
|
|
65
|
+
| --------- | ------------------------------------------------------------------------------------ | -------------------------------------------------- |
|
|
66
|
+
| `'point'` | Beside a point of the shape: a line's last point, a dot, a corner of a bar | `{ layout: 'point', side: 'above' }` |
|
|
67
|
+
| `'path'` | Along an edge or a stroke of the shape: past a bar's tip, along a line, around a dot | `{ layout: 'path', edge: 'base', side: 'inside' }` |
|
|
68
|
+
| `'box'` | Inside the box of each shape, fitted to it: a bar, a cell, a tile | `{ layout: 'box', anchor: 'top' }` |
|
|
69
|
+
|
|
70
|
+
A plot kind takes the layouts its shapes can write, and its `styles.values` type takes only those: a line has no box to write in, so `LinePlot` takes `'point'` and `'path'`. Changing the layout is explicit, with `layout`; each kind brings its own defaults for every layout it takes, so `{ layout: 'path' }` alone is enough.
|
|
71
|
+
|
|
72
|
+
| Plot | Default | Also |
|
|
73
|
+
| ---------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------- |
|
|
74
|
+
| Line, slope, sparkline | `'point'` after the last point | `'path'`: each series' name along its line |
|
|
75
|
+
| Area | `'point'` after the last point | `'path'`: along the top (or bottom) edge of each area |
|
|
76
|
+
| Bar, bullet, pyramid | `'path'` past each bar's tip; `'box'` on a stacked bar | `'box'`, `'point'` |
|
|
77
|
+
| Histogram | `'path'` past each bin's top | `'box'`, `'point'` |
|
|
78
|
+
| Heatmap | `'box'` | `'path'`, `'point'` |
|
|
79
|
+
| Treemap | `'box'` | |
|
|
80
|
+
| Scatter, Cleveland, dumbbell, lollipop, forest | `'point'` beside each dot | `'path'`: around each dot's rim |
|
|
81
|
+
| Density | `'point'` over each curve's peak, naming it | `'path'`: each name along its curve, at its peak |
|
|
82
|
+
| Box, violin | `'point'` beside each box, at each part's value | |
|
|
83
|
+
|
|
84
|
+
## Beside a point: `'point'`
|
|
85
|
+
|
|
86
|
+
The point depends on the shape: on a line or an area, a row's own point; on a dot, its center; on a bar or a cell, a point of its box, which `anchor` names - an edge's middle (`'top'`...) or a corner (`'top-left'`...).
|
|
87
|
+
|
|
88
|
+
From that point, `side` says where the text goes, as it reads: `'after'` it (to its right), `'before'` it, `'above'`, `'below'` or `'on'` it. `gap` is how far, 6px across and 8px up or down by default.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
styles: { values: { side: 'above', gap: 12 } } // a line's last value, over its point
|
|
92
|
+
styles: { values: { layout: 'point', anchor: 'top', select: 'max' } } // only the longest bar, over its top
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Labels that would overlap move apart:
|
|
96
|
+
|
|
97
|
+
- On a line, they fan out into lanes along one column, each joined back to its point by an elbow; `strokeStyle` styles those connectors. The margin on that side grows to hold them while it is `'auto'`.
|
|
98
|
+
- On a scatter, each takes a free spot around its dot - above it first (its own `side`), then on clockwise - clear of the other labels and dots, and one with no room is left out.
|
|
99
|
+
- A label on its own point (`side: 'on'`) stays there; where a shape drawn after its own covers it, it is left out. Of dots drawn over one another, only the top one's value shows.
|
|
100
|
+
|
|
101
|
+
## Along a path: `'path'`
|
|
102
|
+
|
|
103
|
+
The path depends on the shape:
|
|
104
|
+
|
|
105
|
+
- On a bar or a cell, an edge of its box, which `edge` names: `'top'`, `'bottom'`, `'left'` or `'right'` as the page draws them, and on a bar `'tip'`, the end its value runs to, or `'base'`, the one at zero. The tip is read per row, so a bar below zero has its tip at its bottom, and a label past it goes under it.
|
|
106
|
+
- On a line, the line itself, curving with it: one label per series, its series' name unless `format` writes another.
|
|
107
|
+
- On an area, its top edge, or its bottom one with `edge: 'bottom'`; on a stack, each band's own.
|
|
108
|
+
- On a dot, its rim, over its top.
|
|
109
|
+
|
|
110
|
+
`side` is which side of the path the text sits on: on a shape `'outside'` (the default), `'inside'` or `'on'` its edge; on a line or an area `'above'` (the default), `'below'` or `'on'` it, where the text is drawn over a halo of the background. `offset` is where along the path, from its left or top end: `'start'`, `'middle'`, `'end'` or a percentage of its length; on a line or an area, `'max'` and `'min'` put each label at its own peak or trough. A label centred near an end of its line is moved in just enough to be written whole. `gap` is how far from it.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
styles: { values: { layout: 'path', edge: 'tip', side: 'inside' } } // inside each bar's end
|
|
114
|
+
styles: { values: { layout: 'path', side: 'on', offset: '60%' } } // each name on its line
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
A label along a path is written whole, not fitted to its shape. Along a straight-segmented line or area, it follows a smooth curve through the same points, so its letters do not spread apart at the corners.
|
|
118
|
+
|
|
119
|
+
## In a box: `'box'`
|
|
120
|
+
|
|
121
|
+
The label is written in the middle of its shape's box. `anchor` puts it against an edge (`'top'`, `'bottom'`, `'left'`, `'right'`) or in a corner (`'top-left'`...), `gap` from it.
|
|
122
|
+
|
|
123
|
+
A label in a box is fitted to it: one too wide is written smaller, down to `minFontSize`; at that size it breaks into the lines the box holds and the last one is cut short with an ellipsis; and when not even that fits, it is left out. `padding` is the room kept free inside each edge. The defaults of `gap`, `padding`, `minFontSize` (8) and `minLetters` (3) are the configuration's `text.label`: `setConfiguration({ text: { label: { gap: 6 } } })`.
|
|
124
|
+
|
|
125
|
+
## How labels look
|
|
126
|
+
|
|
127
|
+
- A label inside its shape - in a box, or along an edge with `side: 'inside'` - with no color of its own is written in the color that reads best on the shape: white on a dark one, near black on a light one, picked per shape from the configuration's `text.label.contrast`. The shape is read as it is seen: a `fillOpacity` under 1 blends it with the plot's `background`.
|
|
128
|
+
- A label outside its shape is written in its series' color on a line or an area, and in the axis color elsewhere. `color: 'series'` writes each in its series' color, and any other CSS color writes them all in it.
|
|
129
|
+
- `fontStyle` sets the text's look - `fontSize`, `fontWeight`, `fill`, `rotate`, `class`... - but never where it sits, which is the layout's.
|
|
130
|
+
- `hoverIsolate: true` dims every other series while the pointer is over a label.
|
|
131
|
+
|
|
132
|
+
## Labels on markers
|
|
133
|
+
|
|
134
|
+
A marker writes the same labels on its shapes with `label`, which takes a layout and its options like `styles.values`, with every option of a `text` marker besides (`text`, `styles`, `fit`, `declutter`...):
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
{ type: 'line', data, x: 'year', y: 'value', grouping: 'country',
|
|
138
|
+
label: { layout: 'path', text: 'country', offset: '80%' } }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`text` is a field of the row, a function of it, or a literal. A list of labels writes each of them: `label: [{ text: 'value', anchor: 'top' }, { text: 'name', anchor: 'bottom' }]`. Each marker kind takes the layouts its shapes can write, `'box'` by default on shapes with a box and `'point'` on the others:
|
|
142
|
+
|
|
143
|
+
| Marker | `'box'` | `'path'` | `'point'` |
|
|
144
|
+
| --------------- | ------- | ----------------------------------- | ----------------------------- |
|
|
145
|
+
| `bar`, `waffle` | default | its edges, `'tip'` and `'base'` too | a point of its box (`anchor`) |
|
|
146
|
+
| `rect`, `cell` | default | its edges | a point of its box (`anchor`) |
|
|
147
|
+
| `line`, `trail` | | the line | default: each row's point |
|
|
148
|
+
| `area` | | its top or bottom edge | default: each row's top |
|
|
149
|
+
| `dot` | | its rim | default: its center |
|
|
150
|
+
|
|
151
|
+
On a marker:
|
|
152
|
+
|
|
153
|
+
- `select` picks a `'point'` label's rows of each `grouping` of the marker; it also takes a function of the row. Rows without a place (a gap) are never labelled.
|
|
154
|
+
- `declutter: true` (or `'lanes'`) fans overlapping point labels into lanes, `declutter: 'around'` moves each to a free spot around its point. The point labels of every marker of a plot are laid out together, so the ends of several lines fan out as one.
|
|
155
|
+
- A label takes the pointer only with a handler of its own (`onpointerenter`...); the others leave it to the shape under it, so `onclick` and the hover go on as they were. Its styles take functions of the row, to dim the label of a series, say.
|
|
156
|
+
- A box label's `fit` takes `false`, or an object: `minFontSize`, `minLetters`, `padding`, and `fallback` - a value, a field or a function of the row, written instead when fewer than `minLetters` letters would show.
|
|
157
|
+
- `fitMargins: true` grows the plot's margins to hold a label that runs past them.
|
|
158
|
+
|
|
159
|
+
A `text` marker of your own takes the same `declutter`, and `covers`: the shape each row's point sits in, so a label covered by a later row's shape is left out.
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
x: { label: 'Month' },
|
|
24
24
|
y: { label: 'Inflation (%)' }
|
|
25
25
|
}}
|
|
26
|
-
styles={{
|
|
26
|
+
styles={{
|
|
27
|
+
values: { show: true, format: (v, _number, context) => `${context.series}: ${v}` }
|
|
28
|
+
}}
|
|
27
29
|
margins={{ right: 'auto' }}
|
|
28
30
|
/>
|
|
29
31
|
{/if}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { TreemapPlot } from '@fundar/data-chart-telling';
|
|
3
|
+
import { ACTIVITY_BRANCHES } from './datasets';
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<!--
|
|
7
|
+
The hover marker restyles the tiles themselves: the hovered one at full strength and outlined, every other
|
|
8
|
+
faded. Each label is still written on its tile, in the color that reads best on it.
|
|
9
|
+
-->
|
|
10
|
+
<TreemapPlot
|
|
11
|
+
width={760}
|
|
12
|
+
height={440}
|
|
13
|
+
data={ACTIVITY_BRANCHES}
|
|
14
|
+
value="value"
|
|
15
|
+
grouping="sector.branch"
|
|
16
|
+
styles={{ area: { fillOpacity: 0.85 } }}
|
|
17
|
+
tooltip
|
|
18
|
+
markers={[
|
|
19
|
+
{
|
|
20
|
+
type: 'hover',
|
|
21
|
+
active: { fillOpacity: 1, stroke: '#111827', strokeWidth: 2 },
|
|
22
|
+
others: { fillOpacity: 0.35 }
|
|
23
|
+
}
|
|
24
|
+
]}
|
|
25
|
+
/>
|
package/llms-full.txt
CHANGED
|
@@ -43,17 +43,17 @@ Two ways to give data, one per plot:
|
|
|
43
43
|
| `segments` | Style ranges of the data (rule 1 below). |
|
|
44
44
|
| `markers` | Extra marks, an array of `{ type: '...', ... }`. |
|
|
45
45
|
| `margins` | `{ top, right, bottom, left }`, each a number or `'auto'` (all `'auto'` by default). |
|
|
46
|
-
| `tooltip` | `true` or `{ strategy, sync, format, content, series, anchorX, anchorY }`; `format(row, number, context)`, `context` holding the row's `series` and what the kind adds (a treemap's `share`). The text lists matched rows highest value first; a `content` snippet gets them unsorted. |
|
|
46
|
+
| `tooltip` | `true` or `{ strategy, sync, format, content, series, anchorX, anchorY }`; `format(row, number, context)`, `context` holding the row's `series`, `x`, `y`, `value`, `row` and what the kind adds (a treemap's `share`, a histogram's `from`/`to`/`count`, a box's quartiles). The text lists matched rows highest value first; a `content` snippet gets them unsorted. |
|
|
47
47
|
| `timeline` | `{ accessor: 'year' }` steps through the rows by a field, drawn as a player bar (default); `type: 'rule'` draws a rule beside the plot instead. The field may hold numbers, `Date`s or date strings (ISO, or any other with `dateFormat: 'DD/MM/YYYY'`); date steps read as dates, and reach `onvalue`, `player.format` and `useFigure().timeline` (`steps`, `value`, `seekValue`) as `Date`s. Other options: `progress` (position, `0`-`1`), `values` (the steps, when not every distinct value), `filterMode` (`'exact'` shows the current step's rows, `'upTo'` every row up to it; `LinePlot` defaults to `'upTo'`), `interpolate` (tween values between steps), `scales` (`'shared'` keeps both axes still across steps, `'free'` refits both to each step, `'free-x'`/`'free-y'` refit one and keep the other still), `onprogress`, `onvalue`, and a rule's `orientation`, `show` and `thickness`. |
|
|
48
48
|
| `facet` | `{ by: 'field', columns, gap, scales: 'shared'\|'free'\|'free-x'\|'free-y', mode: 'grid'\|'carousel'\|'paginated' }` or `{ rows, cols }`. |
|
|
49
49
|
| `transforms` `statistics` | svelteplot transforms / derived summaries. `treemap` is the library's own transform: `{ type: 'treemap', value: 'count', levels: ['island', 'species'], tile: 'squarify', aspect: 1 }` makes a tile per distinct path of `levels` (outermost first), its area the sum of its rows' `value`, and gives a `rect` marker `x1`/`x2`/`y1`/`y2` in the unit square (`x`/`y` at each tile's centre for a `text`). `statistics` is `[{ type, ...options, series?, pooled? }]` (per series by default, `series: ['a']` only those, `pooled: true` all rows at once; a marker's own `.statistics` runs over its own `data`). Types: `regression` (`regressionType`: `'linear'|'quad'|'poly'|'exp'|'log'|'pow'|'loess'`, `order`, `base`, `span`, `confidence`, `styles`), `movingAverage` (`k`, `reduce`, `styles`), `bollinger` (`n`, `k`, `styles`), `density` (`kernel`, `bandwidth`, `styles`), `density2d` (`bandwidth`, `thresholds`, `styles`), `box` (the `box` marker's options), `deviation` (a rule at an estimator and a band around it, along the plot's value axis: `estimator`: `'mean'|'median'|'midrange'`, `spread`: `'stdev'|'mad'`, `k`, `rule` and `band`: styles or `false`, each with an optional `label: true | { text, styles: FontStyle }`, the band's also `edge: 'lower'|'upper'` and `position: 'inside'|'outside'`)|'upper'`). |
|
|
50
50
|
|
|
51
|
-
Per kind: `BarPlot` x = category, y = value (swap for horizontal bars); `PyramidPlot` mirrors two series around zero; `HeatmapPlot` colors cells by `color`; `HistogramPlot` bins one numeric field; `DensityPlot` smooths one numeric field into a kernel density curve (`styles.mark: 'line'` draws a line instead of an area; a `densityX` transform sets `kernel` and `bandwidth`); `BoxPlot` x = category, y = value, one box per category (its tooltip row is the box summary: `min`, `p25`, `median`, `p75`, `max`, `count`, `outliers`); `ViolinPlot` x = category, y = value (swap for horizontal), the mirrored density of each category's values with a box inside (`styles`: `kernel`, `bandwidth`, `trim`, `scale: 'width'|'shared'`, `box: false | width`; its tooltip row is a box plot's); `LollipopPlot` x = category, y = value, one dot on a stem per category (stems start at zero, or at the nearest end of a pinned domain; `styles.values` labels each dot); `DumbbellPlot` x = category, y = value, `color`/`grouping` names exactly two series, joined by a connector per category (another count warns); `ClevelandPlot` is the same for any number of series, joined from the lowest to the highest (use `grouping` for a numeric series field; `styles.values.select` (`'first'|'last'|'min'|'max'` or a list), `series` and `color: 'series'` choose and color the labelled dots; `styles.connector` sets the connector's `width` (number or `'dots'` for a band), `color` (one, `{ by: 'sign' | 'difference' | 'length' }` or a function), `opacity`, `arrow` (draws the from-to stretch as an arrow), `outside` (the part past the from/to dots), `label` (centered on the from-to stretch) and the `from`/`to` series of its difference); `ForestPlot` x = value, y = category (or swapped), one dot per row on a stem spanning its interval given by `lower`/`upper` fields or an `error` either side (the value axis fits the intervals; `styles.connector.caps` toggles the end ticks, on by default); `BulletPlot` is a bar plot with a `target` (field, function or number: a tick across the band) and `ranges` (upper bounds, each a field, function or number: bands from the baseline, the smallest darkest) drawn around its thin bars (the value axis reaches them); `SlopePlot` x = category (its first and last positions are the two moments), y = value, a line with a dot on every point per series, its first and last labelled before and after it by `styles.values` (the value axis is hidden by default; `scales.y.axisDisplay: 'visible'` shows it); `SparklinePlot` is a small `LinePlot` with no axes and no legend (`legend` and `margins` bring them back), a dot on each series' last point and its value beside it (`styles.values` formats it or turns it off with `show: false`; `facet` makes one per category); `TreemapPlot` takes `value` (a tile's area) and `grouping` (the whole path of a tile, fields joined by dots, outermost first: `'sector.branch'` - the last level names it, rows with one path are one tile, the outermost colors the tiles and the legend); a `treemap` entry in its `transforms` sets `tile` (`'squarify'` default, `'binary'`, `'slice'`, `'dice'`, `'sliceDice'`); its tiles are labelled by `styles.values` with their name over their share of the whole, cut short or reduced to the share alone where they do not fit; its `segments` can be keyed by the path of a tile (`'Tertiary.Finance'`) and `tooltip.format(row, number, context)` gets the tile's row and a `context` with its `series` and `share` (0-100); `ScatterPlot` takes `r` (size) and `symbol`; `GeoPlot` takes GeoJSON/TopoJSON in `data` and `coordinates` for the projection (`docs/geo.md`).
|
|
51
|
+
Per kind: `BarPlot` x = category, y = value (swap for horizontal bars); `PyramidPlot` mirrors two series around zero; `HeatmapPlot` colors cells by `color`; `HistogramPlot` bins one numeric field; `DensityPlot` smooths one numeric field into a kernel density curve (`styles.mark: 'line'` draws a line instead of an area; a `densityX` transform sets `kernel` and `bandwidth`); `BoxPlot` x = category, y = value, one box per category (its tooltip row is the box summary: `min`, `p25`, `median`, `p75`, `max`, `count`, `outliers`); `ViolinPlot` x = category, y = value (swap for horizontal), the mirrored density of each category's values with a box inside (`styles`: `kernel`, `bandwidth`, `trim`, `scale: 'width'|'shared'`, `box: false | width`; its tooltip row is a box plot's); `LollipopPlot` x = category, y = value, one dot on a stem per category (stems start at zero, or at the nearest end of a pinned domain; `styles.values` labels each dot); `DumbbellPlot` x = category, y = value, `color`/`grouping` names exactly two series, joined by a connector per category (another count warns); `ClevelandPlot` is the same for any number of series, joined from the lowest to the highest (use `grouping` for a numeric series field; `styles.values.select` (`'first'|'last'|'min'|'max'` or a list), `series` and `color: 'series'` choose and color the labelled dots; `styles.connector` sets the connector's `width` (number or `'dots'` for a band), `color` (one, `{ by: 'sign' | 'difference' | 'length' }` or a function), `opacity`, `arrow` (draws the from-to stretch as an arrow), `outside` (the part past the from/to dots), `label` (centered on the from-to stretch) and the `from`/`to` series of its difference); `ForestPlot` x = value, y = category (or swapped), one dot per row on a stem spanning its interval given by `lower`/`upper` fields or an `error` either side (the value axis fits the intervals; `styles.connector.caps` toggles the end ticks, on by default); `BulletPlot` is a bar plot with a `target` (field, function or number: a tick across the band) and `ranges` (upper bounds, each a field, function or number: bands from the baseline, the smallest darkest) drawn around its thin bars (the value axis reaches them); `SlopePlot` x = category (its first and last positions are the two moments), y = value, a line with a dot on every point per series, its first and last labelled before and after it by `styles.values` (the value axis is hidden by default; `scales.y.axisDisplay: 'visible'` shows it); `SparklinePlot` is a small `LinePlot` with no axes and no legend (`legend` and `margins` bring them back), a dot on each series' last point and its value beside it (`styles.values` formats it or turns it off with `show: false`; `facet` makes one per category); `TreemapPlot` takes `value` (a tile's area) and `grouping` (the whole path of a tile, fields joined by dots, outermost first: `'sector.branch'` - the last level names it, rows with one path are one tile, the outermost colors the tiles and the legend); a `treemap` entry in its `transforms` sets `tile` (`'squarify'` default, `'binary'`, `'slice'`, `'dice'`, `'sliceDice'`); its tiles are labelled by `styles.values` with their name over their share of the whole, cut short or reduced to the share alone where they do not fit; its `segments` can be keyed by the path of a tile (`'Tertiary.Finance'`) and `tooltip.format(row, number, context)` gets the tile's row and a `context` with its `series`, `name`, `path`, `value` and `share` (0-100); `ScatterPlot` takes `r` (size) and `symbol`; `GeoPlot` takes GeoJSON/TopoJSON in `data` and `coordinates` for the projection (`docs/geo.md`).
|
|
52
52
|
|
|
53
53
|
## Switches
|
|
54
54
|
|
|
55
|
-
- **Hover and tooltip** are enabled by `tooltip` and/or a hover marker. The usual look: `tooltip={true} markers={[{ type: 'hover' }]}`. `tooltip.strategy` is `'x' | 'y' | 'punctual' | 'series'`.
|
|
56
|
-
- **Value labels**: `styles
|
|
55
|
+
- **Hover and tooltip** are enabled by `tooltip` and/or a hover marker. The usual look: `tooltip={true} markers={[{ type: 'hover' }]}`. `tooltip.strategy` is `'x' | 'y' | 'punctual' | 'series'`. The hover marker's `active` and `others` restyle the hovered shapes and the rest (`fill`, `fillOpacity`, `stroke`, `strokeWidth`, `strokeOpacity`, `strokeDasharray`, each a value or a function of the row): `markers={[{ type: 'hover', active: { fillOpacity: 1 }, others: { fillOpacity: 0.3 } }]}`. It works on a treemap's tiles, a bar plot's bars and a heatmap's cells as they are; a marker of yours takes it with `hover: true` (also a hit area) or `hover: 'style'`. A series the legend dims stays hoverable but keeps its dimmed fill; one it hides, omits or rescales is never hovered. The hover marker draws its plot kind's own hover - a crosshair along the strategy's axes with a dot and the value on line, area and density plots; a crosshair through the point and its value on a scatter plot; a rule along the value axis with a dot and the value on slope and Cleveland-family plots; the hovered category's `band` behind bar, bullet, box, violin and pyramid plots; the hovered bin's span behind a histogram; a dot on a sparkline; on a treemap or a heatmap, only the hovered tile or cell outlined (`hover.active` in the configuration) - following the strategy in force (a composer's can change while shown), laid out as `back` (markers behind the plot's shapes) and `front` (in front), lists of any markers but `hover` that replace the kind's when set (`back: []` draws nothing behind). They draw the hovered points (`x`, `y`, `label`, `series`, `color`, `areaInset`, `row`), and what they leave unset comes from the hover: `x`/`y`, a `rule`'s and a `band`'s `value`, a `text`'s `text`, the configuration's `hover` look and the series color. `points: 'active' | (point) => boolean` draws only the point under the pointer, or some: `{ type: 'hover', back: [{ type: 'rule', axis: 'x', points: 'active' }], front: [{ type: 'dot' }] }`.
|
|
56
|
+
- **Value labels**: any option of `styles.values` turns them on (`{ show: true }` alone too). Each kind places them its own way: past each bar's tip, after a line's last point (overlapping ones fan out into lanes and the margin grows to fit them; keep `margins.right` at `'auto'`), around each scatter dot, in each heatmap cell. `layout` changes it, with the options of each: `'point'` (`side: 'after' | 'before' | 'above' | 'below' | 'on'`, `gap`; `anchor` on bars and cells), `'path'` (`edge`, with `'tip'`/`'base'` on bars; `side`; `offset: 'start' | 'middle' | 'end' | '40%'`; on a line it writes each series' name along it), `'box'` (`anchor`, fitted to the shape). A kind's `styles.values` type takes only its layouts. Text: `format: (value, number, context) => string` (`context.series`, `context.row`), or `decimals`/`prefix`/`suffix`/`signDisplay`; `select` and `series` pick the rows; `color: 'series'`; `fontStyle` styles the text but never places it. On a plot whose rows have several values, `parts` picks which: `BoxPlot`/`ViolinPlot` `'min' | 'p25' | 'median' | 'p75' | 'max' | 'outliers'` (box default `['min','median','max']`), `BulletPlot` `'value' | 'target' | 'ranges'`, `ForestPlot` `'value' | 'lower' | 'upper'`; a list, or a record with per-part options (`{ median: { format } }`); every value is read off the row context (`context.part` in `format`). `DensityPlot` names each curve at its peak. A marker's `label` takes the same layouts. See `docs/value-labels.md`.
|
|
57
57
|
- **Toggling series from the legend**: `interactive.enabled` on the series section.
|
|
58
58
|
- **A frame** around the plot area: `styles={{ frame: true }}`.
|
|
59
59
|
|
|
@@ -76,7 +76,8 @@ Per kind: `BarPlot` x = category, y = value (swap for horizontal bars); `Pyramid
|
|
|
76
76
|
Inside a plot's snippets (`header`, `footer`, tooltip `content`) or any child of a figure, call during component init:
|
|
77
77
|
|
|
78
78
|
- `useFigure()` returns `{ hover, legend, timeline }` for the whole figure.
|
|
79
|
-
- `usePlot()` returns the same plus `margins`, `scales`, `axes`, `data`, `width`, `height`, `svelteplot` (inside a plot, e.g. a `component` marker)
|
|
79
|
+
- `usePlot()` returns the same plus `margins`, `scales`, `axes`, `data`, `width`, `height`, `svelteplot` (inside a plot, e.g. a `component` marker), and `contextOf(row)`.
|
|
80
|
+
- Row context: every row a plot draws has a context worked out once - `series`, `x`, `y`, `value`, `row` and what the kind adds (`TreemapPlot`: `name`, `path`, `share`; `HistogramPlot`: `count`, `from`, `to`; `BoxPlot`/`ViolinPlot`: `category`, `min`, `p25`, `median`, `p75`, `max`, `count`, `outliers`; `DensityPlot`'s `value` is the estimate). `tooltip.format`, `styles.values.format`, the `hover` marker's points (`point.context`) and `RowContext.of(row)` all read it.
|
|
80
81
|
- `legend.off` (names of hidden series), `legend.isOff(name)`, `legend.toggle(name, action)`, `turnOff`, `turnOn`. `action` is `{ mode: 'dim' | 'hide' | 'omit' | 'rescale' }`; `'omit'` removes the series and refits the axes, and `'rescale'` also makes the parts left of a whole (a stack, a treemap) the new 100%, so the visible domain follows `legend.off`.
|
|
81
82
|
- `timeline.steps`, `value`, `progress`, `playing`, `seek(p)`, `seekValue(v)`, `next()`, `previous()`, `play()`, `pause()`, `toggle()`, `setSpeed()`.
|
|
82
83
|
- `hover.activeX`, `activeY`, `activeSeries`, `source`.
|
|
@@ -86,7 +87,7 @@ The timeline is a player bar by default: `timeline={{ accessor: 'year', player:
|
|
|
86
87
|
## Markers
|
|
87
88
|
|
|
88
89
|
Add with `markers={[{ type: '...' }]}`. For x/y plots:
|
|
89
|
-
`area arrow bar bollinger box brush cell component delaunayLink delaunayMesh delta density difference dot hover hull image line raster rect regression rule text tick trail violin voronoi voronoiMesh waffle`.
|
|
90
|
+
`area arrow band bar bollinger box brush cell component delaunayLink delaunayMesh delta density difference dot hover hull image line raster rect regression rule text tick trail violin voronoi voronoiMesh waffle`.
|
|
90
91
|
GeoPlot: `graticule sphere dot text vector link contour inset geo-hover geo-component`.
|
|
91
92
|
|
|
92
93
|
- `delta` annotates the difference between two series at a position: `{ type: 'delta', axis: 'x', at: 2020, from: { type: 'series', series: 'A' }, to: { type: 'series', series: 'B' }, formatDiff: (d) => d.toFixed(1) }`; `at` can be a list of positions, one delta at each (`at: [1991, 2001]`), and `line`, `text` and `dot` can be functions of the position (`text: (at) => at === 2022 ? { dx: -20, textAnchor: 'end' } : { dx: 20 }`).
|
|
@@ -101,13 +102,14 @@ GeoPlot: `graticule sphere dot text vector link contour inset geo-hover geo-comp
|
|
|
101
102
|
|
|
102
103
|
## Docs (in `docs/`)
|
|
103
104
|
|
|
104
|
-
`getting-started.md`, `concepts.md`, `plots.md` (an index: one page per plot kind in `plots/`), `scales.md`, `styles-and-segments.md`, `markers.md`, `transforms-and-statistics.md`, `tooltip-and-hover.md`, `legend.md`, `timeline.md`, `chrome.md`, `facets.md`, `composer.md`, `state.md`, `geo.md`, `theming.md`.
|
|
105
|
+
`getting-started.md`, `concepts.md`, `plots.md` (an index: one page per plot kind in `plots/`), `scales.md`, `styles-and-segments.md`, `value-labels.md`, `markers.md`, `transforms-and-statistics.md`, `tooltip-and-hover.md`, `legend.md`, `timeline.md`, `chrome.md`, `facets.md`, `composer.md`, `state.md`, `geo.md`, `theming.md`.
|
|
105
106
|
|
|
106
107
|
## Examples (in `examples/`, all runnable)
|
|
107
108
|
|
|
108
109
|
- `LineByRegion.svelte` - one line per region with title, legend, end labels and tooltip.
|
|
109
110
|
- `ResponsiveLine.svelte` - fill the window, end-of-line labels, axis labels.
|
|
110
111
|
- `Tooltip.svelte` - tooltip + hover marker.
|
|
112
|
+
- `TreemapHover.svelte` - a treemap whose hover lightens the hovered tile and fades the rest.
|
|
111
113
|
- `Segments.svelte` - styling a range of the data.
|
|
112
114
|
- `LegendToggle.svelte` + `LegendReader.svelte` - interactive legend and reading its state.
|
|
113
115
|
- `TimelinePlayer.svelte` - animated bar chart with a player.
|
package/llms.txt
CHANGED
|
@@ -33,6 +33,7 @@ Start with the full guide: it lists the mental model, the props every plot share
|
|
|
33
33
|
- [ScatterPlot](./docs/plots/correlation/scatter.md)
|
|
34
34
|
- [Scales](./docs/scales.md): axes and channel scales
|
|
35
35
|
- [Styles and segments](./docs/styles-and-segments.md): value labels, frame, gaps, ranges of data
|
|
36
|
+
- [Value labels](./docs/value-labels.md): `styles.values` and a marker's `label`, their `'point'`, `'path'` and `'box'` layouts and options
|
|
36
37
|
- [Markers](./docs/markers.md): annotations, regions, hover highlight, custom components
|
|
37
38
|
- [Transforms and statistics](./docs/transforms-and-statistics.md): stacking, binning, smoothing, regression, and the statistics `regression`, `movingAverage`, `bollinger`, `density`, `density2d`, `box`, `deviation` with their options
|
|
38
39
|
- [Tooltip and hover](./docs/tooltip-and-hover.md): tooltip options, hover marker, sync
|
|
@@ -41,7 +42,7 @@ Start with the full guide: it lists the mental model, the props every plot share
|
|
|
41
42
|
- [Chrome](./docs/chrome.md): title, caption, header, footer, order, dividers
|
|
42
43
|
- [Facets](./docs/facets.md): small multiples
|
|
43
44
|
- [Composer](./docs/composer.md): several plots in one figure
|
|
44
|
-
- [Reading plot state](./docs/state.md): `useFigure`, `usePlot
|
|
45
|
+
- [Reading plot state](./docs/state.md): `useFigure`, `usePlot`, the row context every format reads
|
|
45
46
|
- [Maps](./docs/geo.md): GeoPlot, projections, camera, map markers
|
|
46
47
|
- [Theming](./docs/theming.md): configuration, themes, locale, CSS variables
|
|
47
48
|
|
|
@@ -57,6 +58,7 @@ Start with the full guide: it lists the mental model, the props every plot share
|
|
|
57
58
|
- [Facets with a synced tooltip](./examples/Facets.svelte)
|
|
58
59
|
- [Bars with value labels](./examples/BarValues.svelte)
|
|
59
60
|
- [Treemap: a tile per row, sized by its value and nested by grouping](./examples/Treemap.svelte)
|
|
61
|
+
- [Treemap whose hover lightens the hovered tile and fades the rest](./examples/TreemapHover.svelte)
|
|
60
62
|
- [Custom tooltip card](./examples/CustomTooltip.svelte)
|
|
61
63
|
- [The smallest plot: rows, fields and a pixel size](./examples/FirstPlot.svelte)
|
|
62
64
|
- [Line per series over a date axis, with end labels](./examples/LineDates.svelte)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fundar/data-chart-telling",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "Declarative charts, maps and small multiples for Svelte, built on svelteplot.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ezequiel Puerta",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"d3-interpolate": "^3.0.1",
|
|
58
58
|
"d3-scale-chromatic": "^3.1.0",
|
|
59
59
|
"d3-selection": "^3.0.0",
|
|
60
|
+
"d3-shape": "^3.2.0",
|
|
60
61
|
"d3-zoom": "^3.0.0"
|
|
61
62
|
},
|
|
62
63
|
"peerDependencies": {
|
|
@@ -86,6 +87,7 @@
|
|
|
86
87
|
"@types/d3-interpolate": "^3.0.4",
|
|
87
88
|
"@types/d3-scale-chromatic": "^3.1.0",
|
|
88
89
|
"@types/d3-selection": "^3.0.11",
|
|
90
|
+
"@types/d3-shape": "^3.2.0",
|
|
89
91
|
"@types/d3-zoom": "^3.0.8",
|
|
90
92
|
"@types/node": "^22",
|
|
91
93
|
"@vitest/browser": "^4.1.7",
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type { TextMarkerConfig } from '../../types/markers/common';
|
|
2
|
-
import type { TextLabelConfig } from '../../types/markers/basic/text';
|
|
3
|
-
/** Where a row's edge along an axis is: a field of the rows, the symbol a transform keyed it by, a function of the row, or a literal. */
|
|
4
|
-
type Edge = unknown;
|
|
5
|
-
/** The edges of the box each row spans, in the data's own terms. */
|
|
6
|
-
export type BoxChannels = {
|
|
7
|
-
x1: Edge;
|
|
8
|
-
x2: Edge;
|
|
9
|
-
y1: Edge;
|
|
10
|
-
y2: Edge;
|
|
11
|
-
};
|
|
12
|
-
/** The scales a box is measured on. */
|
|
13
|
-
export type BoxScales = Record<string, {
|
|
14
|
-
type?: string;
|
|
15
|
-
fn: any;
|
|
16
|
-
} | undefined>;
|
|
17
|
-
/** The pixel size of the box of a row, for the markers whose boxes are bands of a category axis rather than edges. */
|
|
18
|
-
export type BoxSizer = (row: unknown, scales: BoxScales) => {
|
|
19
|
-
width: number;
|
|
20
|
-
height: number;
|
|
21
|
-
} | undefined;
|
|
22
|
-
/** The `text` marker that labels the boxes a marker draws, and where each label's box is. */
|
|
23
|
-
export type BoxLabelMarker = {
|
|
24
|
-
marker: TextMarkerConfig;
|
|
25
|
-
box: BoxChannels | BoxSizer;
|
|
26
|
-
};
|
|
27
|
-
/** What a marker has to say for its boxes to be labelled. */
|
|
28
|
-
export type Labelled = {
|
|
29
|
-
type?: string;
|
|
30
|
-
data?: unknown[];
|
|
31
|
-
label?: TextLabelConfig;
|
|
32
|
-
x?: Edge;
|
|
33
|
-
y?: Edge;
|
|
34
|
-
x1?: Edge;
|
|
35
|
-
x2?: Edge;
|
|
36
|
-
y1?: Edge;
|
|
37
|
-
y2?: Edge;
|
|
38
|
-
isHorizontal?: boolean;
|
|
39
|
-
role?: string;
|
|
40
|
-
thickness?: number;
|
|
41
|
-
/** The marker's styles: the insets of a cell or a bar are read off them. */
|
|
42
|
-
styles?: object;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* How a marker that draws a box per row writes a label in each: the `text` marker for them, centred on the box,
|
|
46
|
-
* and where the box is for it to fit to. A `rect` says it with its edges, a `cell` is a band of each axis, and a bar
|
|
47
|
-
* or a waffle is a band of its category axis and the stretch of its value.
|
|
48
|
-
*/
|
|
49
|
-
export declare class BoxLabel {
|
|
50
|
-
#private;
|
|
51
|
-
/** `undefined` when the marker has no label, or does not say where its boxes are. */
|
|
52
|
-
static of(marker: Labelled, plot?: {
|
|
53
|
-
isHorizontal?: boolean;
|
|
54
|
-
scales?: () => BoxScales | undefined;
|
|
55
|
-
gap?: number;
|
|
56
|
-
}): BoxLabelMarker | undefined;
|
|
57
|
-
}
|
|
58
|
-
export {};
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
const read = (edge) => (row) => typeof edge === 'function'
|
|
2
|
-
? edge(row)
|
|
3
|
-
: typeof edge === 'string' || typeof edge === 'symbol'
|
|
4
|
-
? row?.[edge]
|
|
5
|
-
: edge;
|
|
6
|
-
/** The middle of two positions along an axis, whether numbers or dates. */
|
|
7
|
-
const middle = (from, to) => from instanceof Date || to instanceof Date
|
|
8
|
-
? new Date((Number(from) + Number(to)) / 2)
|
|
9
|
-
: (Number(from) + Number(to)) / 2;
|
|
10
|
-
const bandwidth = (scale) => scale?.type === 'band' ? Number(scale.fn.bandwidth()) : undefined;
|
|
11
|
-
const distance = (scale, from, to) => scale ? Math.abs(Number(scale.fn(to)) - Number(scale.fn(from))) : undefined;
|
|
12
|
-
/**
|
|
13
|
-
* How a marker that draws a box per row writes a label in each: the `text` marker for them, centred on the box,
|
|
14
|
-
* and where the box is for it to fit to. A `rect` says it with its edges, a `cell` is a band of each axis, and a bar
|
|
15
|
-
* or a waffle is a band of its category axis and the stretch of its value.
|
|
16
|
-
*/
|
|
17
|
-
export class BoxLabel {
|
|
18
|
-
/** `undefined` when the marker has no label, or does not say where its boxes are. */
|
|
19
|
-
static of(marker, plot = {}) {
|
|
20
|
-
if (!marker.label)
|
|
21
|
-
return undefined;
|
|
22
|
-
const own = BoxLabel.#shape(marker, plot.isHorizontal ?? marker.isHorizontal ?? false);
|
|
23
|
-
if (!own)
|
|
24
|
-
return undefined;
|
|
25
|
-
const { anchor, outside, gap, ...label } = marker.label;
|
|
26
|
-
const size = typeof own.box === 'function' ? own.box : own.size;
|
|
27
|
-
const placed = BoxLabel.#anchored({
|
|
28
|
-
anchor,
|
|
29
|
-
outside,
|
|
30
|
-
gap: gap ?? plot.gap
|
|
31
|
-
}, label, size, plot.scales);
|
|
32
|
-
return {
|
|
33
|
-
box: own.box,
|
|
34
|
-
marker: {
|
|
35
|
-
// A label outside its shape has nothing to fit to.
|
|
36
|
-
fit: !outside,
|
|
37
|
-
...label,
|
|
38
|
-
...placed,
|
|
39
|
-
type: 'text',
|
|
40
|
-
data: marker.data,
|
|
41
|
-
x: own.x,
|
|
42
|
-
y: own.y
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* What puts a label at `anchor` of its shape: the pixels it is moved from the middle - a function of the row, for
|
|
48
|
-
* the size of its shape is the row's own - and the sides of its point it is written on. `{}` for the middle.
|
|
49
|
-
*/
|
|
50
|
-
static #anchored(where, label, size, scales) {
|
|
51
|
-
const { anchor = 'middle', outside = false } = where;
|
|
52
|
-
if (anchor === 'middle' || !size)
|
|
53
|
-
return {};
|
|
54
|
-
const gap = where.gap ?? 4;
|
|
55
|
-
const horizontal = anchor.endsWith('left') ? -1 : anchor.endsWith('right') ? 1 : 0;
|
|
56
|
-
const vertical = anchor.startsWith('top') ? -1 : anchor.startsWith('bottom') ? 1 : 0;
|
|
57
|
-
// Beyond an edge only means something for an edge: a corner is inside its shape.
|
|
58
|
-
const beyond = outside && horizontal * vertical === 0;
|
|
59
|
-
const away = beyond ? 1 : -1;
|
|
60
|
-
const move = (axis, side, row) => {
|
|
61
|
-
// Read when a label is drawn, not when its marker is made: the scales move as the labels register.
|
|
62
|
-
const current = scales?.();
|
|
63
|
-
const box = current ? size(row, current) : undefined;
|
|
64
|
-
return box ? side * (box[axis] / 2 + away * gap) : 0;
|
|
65
|
-
};
|
|
66
|
-
// A number of the label's own (or its styles') is added to the move: it is the push from the anchor.
|
|
67
|
-
const own = (value, fallback) => Number(typeof value === 'number' ? value : (fallback ?? 0));
|
|
68
|
-
const baseX = own(label.dx, label.styles?.dx);
|
|
69
|
-
const baseY = own(label.dy, label.styles?.dy);
|
|
70
|
-
return {
|
|
71
|
-
dx: horizontal === 0 ? label.dx : (row) => baseX + move('width', horizontal, row),
|
|
72
|
-
dy: vertical === 0 ? label.dy : (row) => baseY + move('height', vertical, row),
|
|
73
|
-
styles: {
|
|
74
|
-
...label.styles,
|
|
75
|
-
textAnchor: label.styles?.textAnchor ??
|
|
76
|
-
(horizontal === 0 ? 'middle' : (horizontal === 1) === beyond ? 'start' : 'end'),
|
|
77
|
-
lineAnchor: label.styles?.lineAnchor ??
|
|
78
|
-
(vertical === 0 ? 'middle' : (vertical === 1) === beyond ? 'top' : 'bottom')
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
/** A style of the marker, when it is a number: a function of the row says nothing of a box in general. */
|
|
83
|
-
static #style(marker, name) {
|
|
84
|
-
const value = marker.styles?.[name];
|
|
85
|
-
return typeof value === 'number' ? value : undefined;
|
|
86
|
-
}
|
|
87
|
-
static #shape(marker, isHorizontal) {
|
|
88
|
-
if (marker.type === 'cell')
|
|
89
|
-
return BoxLabel.#cell(marker);
|
|
90
|
-
if (marker.type === 'bar') {
|
|
91
|
-
return marker.role === 'segment'
|
|
92
|
-
? BoxLabel.#bar(marker, marker.isHorizontal ?? false)
|
|
93
|
-
: undefined;
|
|
94
|
-
}
|
|
95
|
-
if (marker.type === 'waffle')
|
|
96
|
-
return BoxLabel.#bar(marker, isHorizontal);
|
|
97
|
-
return BoxLabel.#edges(marker);
|
|
98
|
-
}
|
|
99
|
-
/** A rectangle: the box is between its edges. */
|
|
100
|
-
static #edges({ x, y, x1, x2, y1, y2 }) {
|
|
101
|
-
// A side with a value and no start, next to one with both its edges, runs from zero to it, as a bar does.
|
|
102
|
-
if (y1 === undefined &&
|
|
103
|
-
y2 === undefined &&
|
|
104
|
-
y !== undefined &&
|
|
105
|
-
x1 !== undefined &&
|
|
106
|
-
x2 !== undefined) {
|
|
107
|
-
[y1, y2] = [0, y];
|
|
108
|
-
}
|
|
109
|
-
if (x1 === undefined &&
|
|
110
|
-
x2 === undefined &&
|
|
111
|
-
x !== undefined &&
|
|
112
|
-
y1 !== undefined &&
|
|
113
|
-
y2 !== undefined) {
|
|
114
|
-
[x1, x2] = [0, x];
|
|
115
|
-
}
|
|
116
|
-
if ([x1, x2, y1, y2].some((edge) => edge === undefined))
|
|
117
|
-
return undefined;
|
|
118
|
-
const [left, right, top, bottom] = [x1, x2, y1, y2].map(read);
|
|
119
|
-
const size = (row, scales) => {
|
|
120
|
-
const [width, height] = [
|
|
121
|
-
distance(scales.x, left(row), right(row)),
|
|
122
|
-
distance(scales.y, top(row), bottom(row))
|
|
123
|
-
];
|
|
124
|
-
return width === undefined || height === undefined ? undefined : { width, height };
|
|
125
|
-
};
|
|
126
|
-
return {
|
|
127
|
-
box: { x1, x2, y1, y2 },
|
|
128
|
-
size,
|
|
129
|
-
x: (row) => middle(left(row), right(row)),
|
|
130
|
-
y: (row) => middle(top(row), bottom(row))
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
/** A cell: a band of each axis, less its inset. */
|
|
134
|
-
static #cell(marker) {
|
|
135
|
-
if (marker.x === undefined || marker.y === undefined)
|
|
136
|
-
return undefined;
|
|
137
|
-
const inset = Number(BoxLabel.#style(marker, 'inset') ?? 0.5);
|
|
138
|
-
const box = (_, scales) => {
|
|
139
|
-
const [width, height] = [bandwidth(scales.x), bandwidth(scales.y)];
|
|
140
|
-
return width === undefined || height === undefined
|
|
141
|
-
? undefined
|
|
142
|
-
: { width: width - 2 * inset, height: height - 2 * inset };
|
|
143
|
-
};
|
|
144
|
-
return { box: box, x: marker.x, y: marker.y };
|
|
145
|
-
}
|
|
146
|
-
/** A bar or a waffle: a band of the category axis, as wide as its insets leave it, and as long as its value. */
|
|
147
|
-
static #bar(marker, isHorizontal) {
|
|
148
|
-
const [category, from, to] = isHorizontal
|
|
149
|
-
? [marker.y, marker.x1, marker.x2]
|
|
150
|
-
: [marker.x, marker.y1, marker.y2];
|
|
151
|
-
const value = isHorizontal ? marker.x : marker.y;
|
|
152
|
-
// Without both ends, the bar runs from zero to its value.
|
|
153
|
-
const [start, end] = from !== undefined && to !== undefined ? [from, to] : [0, value];
|
|
154
|
-
if (category === undefined || end === undefined)
|
|
155
|
-
return undefined;
|
|
156
|
-
const [first, last] = [start, end].map(read);
|
|
157
|
-
const [before, after] = isHorizontal
|
|
158
|
-
? [BoxLabel.#style(marker, 'insetTop'), BoxLabel.#style(marker, 'insetBottom')]
|
|
159
|
-
: [BoxLabel.#style(marker, 'insetLeft'), BoxLabel.#style(marker, 'insetRight')];
|
|
160
|
-
const middleOf = (row) => middle(first(row), last(row));
|
|
161
|
-
const box = (row, scales) => {
|
|
162
|
-
const band = bandwidth(isHorizontal ? scales.y : scales.x);
|
|
163
|
-
const length = distance(isHorizontal ? scales.x : scales.y, first(row), last(row));
|
|
164
|
-
if (band === undefined || length === undefined)
|
|
165
|
-
return undefined;
|
|
166
|
-
const thickness = marker.thickness ?? band * (1 - Number(before ?? 0) - Number(after ?? 0));
|
|
167
|
-
return isHorizontal
|
|
168
|
-
? { width: length, height: thickness }
|
|
169
|
-
: { width: thickness, height: length };
|
|
170
|
-
};
|
|
171
|
-
return isHorizontal
|
|
172
|
-
? { box: box, x: middleOf, y: category }
|
|
173
|
-
: { box: box, x: category, y: middleOf };
|
|
174
|
-
}
|
|
175
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import TextMarker from '../text/TextMarker.svelte';
|
|
3
|
-
import { getConfiguration } from '../../configuration/config.svelte';
|
|
4
|
-
import { usePlot } from '../../layout/plot/usePlot';
|
|
5
|
-
import { BoxLabel, type Labelled } from './BoxLabel';
|
|
6
|
-
import { MARK_EVENTS } from '../../types/markers/channels/commonMarkerEvents';
|
|
7
|
-
import type { TextLabelConfig } from '../../types/markers/basic/text';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The `label` of a marker that draws a box per row: a `text` marker anchored in each box and fitted to it. A marker
|
|
11
|
-
* with a label only has to render `<MarkerLabel {marker} />` after its own shapes. Nothing is drawn without a
|
|
12
|
-
* `label`, or when the marker does not say where its boxes are.
|
|
13
|
-
*/
|
|
14
|
-
const { marker }: { marker: Labelled & { label?: TextLabelConfig } } = $props();
|
|
15
|
-
const plot = usePlot();
|
|
16
|
-
const cfg = $derived(getConfiguration());
|
|
17
|
-
|
|
18
|
-
const labelled = $derived(
|
|
19
|
-
BoxLabel.of(marker, {
|
|
20
|
-
isHorizontal: plot.axes?.isHorizontal,
|
|
21
|
-
gap: cfg.text.label.gap,
|
|
22
|
-
scales: () => plot.svelteplot.scales as never
|
|
23
|
-
})
|
|
24
|
-
);
|
|
25
|
-
/** A label with a handler of its own listens for the pointer; one without leaves it to the shape under it. */
|
|
26
|
-
const listens = $derived(MARK_EVENTS.some((name) => !!marker.label?.[name]));
|
|
27
|
-
</script>
|
|
28
|
-
|
|
29
|
-
{#if labelled}
|
|
30
|
-
<g pointer-events={listens ? undefined : 'none'}>
|
|
31
|
-
<TextMarker marker={labelled.marker} box={labelled.box} />
|
|
32
|
-
</g>
|
|
33
|
-
{/if}
|