@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
|
@@ -6,6 +6,12 @@ import { seriesIdOf } from '../../utils/grouping';
|
|
|
6
6
|
import { isGapValue } from '../../plots/utils/gaps';
|
|
7
7
|
import { PlotAxes } from '../../phases/data/PlotAxes';
|
|
8
8
|
import { NumberFormat } from '../../utils/NumberFormat';
|
|
9
|
+
import { RowContext } from '../../phases/context/RowContext';
|
|
10
|
+
import { PointLayout } from '../../markers/labels/layouts/PointLayout';
|
|
11
|
+
/** Where a part's value sits on the row a part label copies. */
|
|
12
|
+
const PART_VALUE = Symbol('partValue');
|
|
13
|
+
/** The options of `styles.values` that place a label in its layout. */
|
|
14
|
+
const LAYOUT_KEYS = ['anchor', 'edge', 'side', 'offset', 'gap'];
|
|
9
15
|
/**
|
|
10
16
|
* A plot's value labels: the author's `styles.values` over the plot kind's
|
|
11
17
|
* own defaults, how their text measures, where they are expected to sit
|
|
@@ -14,7 +20,21 @@ import { NumberFormat } from '../../utils/NumberFormat';
|
|
|
14
20
|
*/
|
|
15
21
|
export class ValueLabels {
|
|
16
22
|
show;
|
|
17
|
-
|
|
23
|
+
/** How the labels are laid out on their shapes: the author's `layout`, else the kind's. */
|
|
24
|
+
layout;
|
|
25
|
+
/** The options that place a label in its {@link layout}: the author's over the kind's own for it. */
|
|
26
|
+
placement;
|
|
27
|
+
/** The parts of each row labelled - a simple plot's one `value`, a box's `median`... - each with its own options. */
|
|
28
|
+
parts;
|
|
29
|
+
/** The series whose rows are labelled, when `styles.values.series` names some; every series else. */
|
|
30
|
+
series;
|
|
31
|
+
/** Whether the author gave the labels a text of their own, beyond the value. */
|
|
32
|
+
formatted;
|
|
33
|
+
/**
|
|
34
|
+
* A label's text for `value`: the author's `format`, else the kind's, else the value as the display fields ask.
|
|
35
|
+
* `row` is the row it labels, whose context the format reads; `series` names its series where there is no row
|
|
36
|
+
* (a label measured ahead of the rows); `part`, which of the row's values it writes.
|
|
37
|
+
*/
|
|
18
38
|
format;
|
|
19
39
|
hoverIsolate;
|
|
20
40
|
font;
|
|
@@ -29,17 +49,40 @@ export class ValueLabels {
|
|
|
29
49
|
reach;
|
|
30
50
|
#cfg;
|
|
31
51
|
constructor(values, cfg, options = {}, reach) {
|
|
32
|
-
this.
|
|
33
|
-
|
|
52
|
+
this.layout = values?.layout ?? options.layout ?? 'point';
|
|
53
|
+
const own = Object.fromEntries(LAYOUT_KEYS.flatMap((key) => {
|
|
54
|
+
const value = values?.[key];
|
|
55
|
+
return value === undefined ? [] : [[key, value]];
|
|
56
|
+
}));
|
|
34
57
|
// The value as the display fields ask (else as it is), which a plot kind's own text builds on.
|
|
35
58
|
const number = NumberFormat.maybe(NumberFormat.displayOf(values), cfg) ?? ((v) => `${v}`);
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
59
|
+
const writer = (write) => (v, row, series, part) => write
|
|
60
|
+
? write(v, number, { ...ValueLabels.contextOf(row, series), ...(part ? { part } : {}) })
|
|
61
|
+
: number(v);
|
|
62
|
+
this.format = writer(values?.format ?? options.format);
|
|
63
|
+
this.parts = ValueLabels.#parts(values?.parts, options.parts).map(([name, own_]) => {
|
|
64
|
+
const { format, ...placement } = own_;
|
|
65
|
+
return {
|
|
66
|
+
name,
|
|
67
|
+
placement: {
|
|
68
|
+
...options.layouts?.[this.layout],
|
|
69
|
+
...options.parts?.placements[name],
|
|
70
|
+
...own,
|
|
71
|
+
...placement
|
|
72
|
+
},
|
|
73
|
+
format: format ? writer(format) : this.format
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
this.placement = this.#part('value')?.placement ?? {
|
|
77
|
+
...options.layouts?.[this.layout],
|
|
78
|
+
...own
|
|
79
|
+
};
|
|
80
|
+
this.formatted =
|
|
81
|
+
values?.format !== undefined ||
|
|
82
|
+
!!values?.parts?.value?.format;
|
|
83
|
+
this.show = ValueLabels.shows(values, options.show) && this.parts.length > 0;
|
|
42
84
|
this.hoverIsolate = values?.hoverIsolate ?? false;
|
|
85
|
+
this.series = values?.series === undefined ? undefined : [values.series].flat();
|
|
43
86
|
this.font = values?.fontStyle;
|
|
44
87
|
this.fontSize = typeof this.font?.fontSize === 'number' ? this.font.fontSize : 12;
|
|
45
88
|
this.strokeStyle = values?.strokeStyle;
|
|
@@ -48,10 +91,97 @@ export class ValueLabels {
|
|
|
48
91
|
this.#cfg = cfg;
|
|
49
92
|
this.reach = (this.show && reach?.(this)) || [];
|
|
50
93
|
}
|
|
94
|
+
/** Whether the part named `name` is labelled: a plot writing its `value` on its own shapes asks first. */
|
|
95
|
+
writes(name) {
|
|
96
|
+
return this.#part(name) !== undefined;
|
|
97
|
+
}
|
|
98
|
+
/** The part named `name`, when it is labelled. */
|
|
99
|
+
#part(name) {
|
|
100
|
+
return this.parts.find((part) => part.name === name);
|
|
101
|
+
}
|
|
102
|
+
/** The parts labelled, each with its own options: the author's list or record, else the kind's default ones. */
|
|
103
|
+
static #parts(own, kind) {
|
|
104
|
+
if (own === undefined)
|
|
105
|
+
return (kind?.default ?? ['value']).map((name) => [name, {}]);
|
|
106
|
+
if (Array.isArray(own))
|
|
107
|
+
return own.map((name) => [name, {}]);
|
|
108
|
+
return Object.entries(own).flatMap(([name, option]) => option ? [[name, option === true ? {} : option]] : []);
|
|
109
|
+
}
|
|
110
|
+
/** Whether the labels draw: `show` as set, else when any other option of them is set, else the kind's default. */
|
|
111
|
+
static shows(values, fallback = false) {
|
|
112
|
+
if (values?.show !== undefined)
|
|
113
|
+
return values.show;
|
|
114
|
+
const set = Object.entries(values ?? {}).some(([key, value]) => key !== 'show' && value !== undefined);
|
|
115
|
+
return set || fallback;
|
|
116
|
+
}
|
|
117
|
+
/** The context a label's `format` reads: its row's, with `series` when the row gives none. */
|
|
118
|
+
static contextOf(row, series) {
|
|
119
|
+
const context = RowContext.of(row);
|
|
120
|
+
return context.series === undefined && series !== undefined ? { ...context, series } : context;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The value a label writes for `row`, read off its context: its `value`, or one `part` of it on a plot whose rows
|
|
124
|
+
* have several. `undefined` when it is not a number.
|
|
125
|
+
*/
|
|
126
|
+
static valueIn(row, part = 'value') {
|
|
127
|
+
const value = RowContext.of(row)[part];
|
|
128
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
129
|
+
}
|
|
130
|
+
/** A label's text for `row`: its context's `part` (its `value` by default), as that part's format writes it. */
|
|
131
|
+
text(row, part = 'value') {
|
|
132
|
+
const value = ValueLabels.valueIn(row, part);
|
|
133
|
+
const format = this.#part(part)?.format ?? this.format;
|
|
134
|
+
return value === undefined ? '' : format(value, row, undefined, part);
|
|
135
|
+
}
|
|
51
136
|
/** A plot's value labels: `values` over `options`, the kind's own defaults, their reach read off `state`. */
|
|
52
137
|
static build(values, cfg, options, state) {
|
|
53
|
-
const { reach } = options;
|
|
54
|
-
return new ValueLabels(values, cfg,
|
|
138
|
+
const { reach, layout, layouts, parts, formatFor } = options;
|
|
139
|
+
return new ValueLabels(values, cfg, {
|
|
140
|
+
...options,
|
|
141
|
+
layout: typeof layout === 'function' ? layout(state) : layout,
|
|
142
|
+
format: options.format ?? formatFor?.(state),
|
|
143
|
+
layouts: typeof layouts === 'function' ? layouts(state) : layouts,
|
|
144
|
+
parts: parts && {
|
|
145
|
+
...parts,
|
|
146
|
+
placements: typeof parts.placements === 'function' ? parts.placements(state) : parts.placements
|
|
147
|
+
}
|
|
148
|
+
}, reach && ((labels) => reach(labels, state)));
|
|
149
|
+
}
|
|
150
|
+
/** Whether the labels sit past the tip of their shapes, where the plot's margins keep room for them. */
|
|
151
|
+
get pastTip() {
|
|
152
|
+
const { edge = 'tip', side = 'outside' } = this.placement;
|
|
153
|
+
return this.layout === 'path' && edge === 'tip' && side === 'outside';
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The `label` a plot kind's shapes write their value in, in this plot's {@link layout}: `text`, over what every
|
|
157
|
+
* label shares ({@link hooks}). Inside its shape a label takes no `fill` of its own, so it is written in the color
|
|
158
|
+
* that reads best on the shape; past it, the plot's `fill`.
|
|
159
|
+
*/
|
|
160
|
+
label(env, text, defaults = {}) {
|
|
161
|
+
const { fitMargins, styles: shared, ...events } = this.hooks(env);
|
|
162
|
+
const { font } = this;
|
|
163
|
+
const onShape = this.layout === 'box' || this.placement.side === 'inside';
|
|
164
|
+
const picked = this.layout === 'point' && defaults.labelled && new Set(defaults.labelled);
|
|
165
|
+
return {
|
|
166
|
+
...events,
|
|
167
|
+
...this.placement,
|
|
168
|
+
...(picked ? { select: (row) => picked.has(row) } : {}),
|
|
169
|
+
layout: this.layout,
|
|
170
|
+
text,
|
|
171
|
+
fitMargins: onShape ? undefined : fitMargins,
|
|
172
|
+
styles: {
|
|
173
|
+
...shared,
|
|
174
|
+
...font,
|
|
175
|
+
// On its shape, a label unset reads in the color that contrasts with it; off it, in its own.
|
|
176
|
+
fill: onShape
|
|
177
|
+
? this.fill
|
|
178
|
+
: (this.fill ??
|
|
179
|
+
(this.color === 'series' ? defaults.seriesColor : undefined) ??
|
|
180
|
+
defaults.fill),
|
|
181
|
+
fontSize: font?.fontSize ?? defaults.fontSize ?? 12,
|
|
182
|
+
fontWeight: font?.fontWeight ?? defaults.fontWeight
|
|
183
|
+
}
|
|
184
|
+
};
|
|
55
185
|
}
|
|
56
186
|
/** The configuration the labels were built under, for a plot kind's own label defaults. */
|
|
57
187
|
get config() {
|
|
@@ -73,9 +203,9 @@ export class ValueLabels {
|
|
|
73
203
|
textBox(text) {
|
|
74
204
|
return Box.ofText(text, this.fontSize, this.#cfg);
|
|
75
205
|
}
|
|
76
|
-
/** The labels' gap (px) from their mark
|
|
77
|
-
offset(
|
|
78
|
-
const own =
|
|
206
|
+
/** The labels' gap (px) from their mark: the layout's `gap`, else `fallback`. */
|
|
207
|
+
offset(fallback = 6) {
|
|
208
|
+
const own = this.placement.gap;
|
|
79
209
|
return Math.abs(typeof own === 'number' ? own : fallback);
|
|
80
210
|
}
|
|
81
211
|
/**
|
|
@@ -120,22 +250,13 @@ export class ValueLabels {
|
|
|
120
250
|
return [lowest, highest].flatMap((value) => value === undefined ? [] : [{ series: s, value }]);
|
|
121
251
|
});
|
|
122
252
|
}
|
|
123
|
-
/**
|
|
124
|
-
* The author's own `textAnchor`, if any. `'outside'` is a hover marker's
|
|
125
|
-
* per-point anchor; a label's own `anchor` already places it, so here it
|
|
126
|
-
* counts as unset.
|
|
127
|
-
*/
|
|
128
|
-
get textAnchor() {
|
|
129
|
-
const own = this.font?.textAnchor;
|
|
130
|
-
return own === 'outside' ? undefined : own;
|
|
131
|
-
}
|
|
132
253
|
/**
|
|
133
254
|
* What every label marker shares: the plot's margins grow to fit it, it
|
|
134
255
|
* dims with its row's series, and with `hoverIsolate`, hovering it
|
|
135
256
|
* isolates that series. A row without a series gets the margins only.
|
|
136
257
|
*/
|
|
137
|
-
hooks(
|
|
138
|
-
const interaction =
|
|
258
|
+
hooks(env) {
|
|
259
|
+
const interaction = env.interaction;
|
|
139
260
|
const seriesOf = (d) => d?.[SERIES_KEY] === undefined ? undefined : String(d[SERIES_KEY]);
|
|
140
261
|
const isolate = this.hoverIsolate && interaction;
|
|
141
262
|
return {
|
|
@@ -152,64 +273,6 @@ export class ValueLabels {
|
|
|
152
273
|
onpointerleave: isolate ? () => interaction.isolate(null) : undefined
|
|
153
274
|
};
|
|
154
275
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Where in a bar a label goes, from the `anchor` of `styles.values`: its `label` anchor, and whether it is beyond
|
|
157
|
-
* the bar. `negative` tells a bar that runs to the left (or down) from its base from one that runs right (or up),
|
|
158
|
-
* which `'tip'`, `'base'` and `'outside'` follow; the others are the edges of the page. A `stacked` bar's label is
|
|
159
|
-
* always in the middle. An anchor the shapes do not read (`'start'`, `'end'`) is taken for `'outside'`, the default.
|
|
160
|
-
*/
|
|
161
|
-
static boxAnchor(anchor, shape) {
|
|
162
|
-
if (shape.stacked || anchor === 'middle')
|
|
163
|
-
return { anchor: 'middle' };
|
|
164
|
-
// A place in the shape as it is drawn on the page, which no sign moves.
|
|
165
|
-
if (anchor !== 'outside' &&
|
|
166
|
-
anchor !== 'start' &&
|
|
167
|
-
anchor !== 'end' &&
|
|
168
|
-
anchor !== 'tip' &&
|
|
169
|
-
anchor !== 'base') {
|
|
170
|
-
return { anchor };
|
|
171
|
-
}
|
|
172
|
-
const [tip, base] = shape.isHorizontal
|
|
173
|
-
? shape.negative
|
|
174
|
-
? ['left', 'right']
|
|
175
|
-
: ['right', 'left']
|
|
176
|
-
: shape.negative
|
|
177
|
-
? ['bottom', 'top']
|
|
178
|
-
: ['top', 'bottom'];
|
|
179
|
-
if (anchor === 'base')
|
|
180
|
-
return { anchor: base };
|
|
181
|
-
return anchor === 'tip' ? { anchor: tip } : { anchor: tip, outside: true };
|
|
182
|
-
}
|
|
183
|
-
/** Whether a label at `anchor` goes to one side or the other of a bar with the sign of its value. */
|
|
184
|
-
static followsSign(anchor) {
|
|
185
|
-
return anchor === 'outside' || anchor === 'tip' || anchor === 'base';
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* The `label` the shapes of a plot kind write their value in: this plot's `styles.values` over the `defaults` the kind
|
|
189
|
-
* sets, with what every label shares ({@link hooks}) - its dimming and isolating of a series. A label inside its shape
|
|
190
|
-
* never reaches out of the plot, so only one `outside` has the margins grow to hold it; and it takes the default
|
|
191
|
-
* `fill` only `outside`, for inside it is written in the color that contrasts with its shape.
|
|
192
|
-
*/
|
|
193
|
-
shapeLabel(ctx, text, defaults = {}) {
|
|
194
|
-
const { fitMargins, styles: shared, ...events } = this.hooks(ctx);
|
|
195
|
-
const { font } = this;
|
|
196
|
-
return {
|
|
197
|
-
...events,
|
|
198
|
-
text,
|
|
199
|
-
anchor: defaults.anchor,
|
|
200
|
-
outside: defaults.outside,
|
|
201
|
-
gap: defaults.gap,
|
|
202
|
-
fitMargins: defaults.outside ? fitMargins : undefined,
|
|
203
|
-
styles: {
|
|
204
|
-
...shared,
|
|
205
|
-
...font,
|
|
206
|
-
// Inside its shape, a label unset is written in the color that reads best on it.
|
|
207
|
-
fill: font?.fill ?? (defaults.outside ? defaults.fill : undefined),
|
|
208
|
-
fontSize: font?.fontSize ?? defaults.fontSize ?? 12,
|
|
209
|
-
fontWeight: font?.fontWeight ?? defaults.fontWeight
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
276
|
/**
|
|
214
277
|
* A processed row's own value, read through its series' own value channel
|
|
215
278
|
* (`y`, or `x` on a horizontal plot) - what a label shows, even where a
|
|
@@ -225,30 +288,147 @@ export class ValueLabels {
|
|
|
225
288
|
return (d) => bySeries.get(String(d[SERIES_ID_KEY]))?.(d);
|
|
226
289
|
}
|
|
227
290
|
/**
|
|
228
|
-
* A series-over-`x` plot's (line, area) labels:
|
|
229
|
-
* the
|
|
230
|
-
*
|
|
231
|
-
* `
|
|
232
|
-
* would overlap fan out into a shared column (`declutter`), colored by the
|
|
233
|
-
* segment the row falls in. A plot that labels each end of its series apart
|
|
234
|
-
* passes the `rows` and `anchor` of one end, and `lane` to route its labels
|
|
235
|
-
* out to a lane whether or not they overlap (`flip: false` keeps one on the
|
|
236
|
-
* left in the margin instead of flipping it over its points).
|
|
291
|
+
* A series-over-`x` plot's (line, area) labels, for its line or area markers: each labelled row (by default its
|
|
292
|
+
* series' last) with its own value, on the `side` of it its placement asks, colored by the segment it falls in.
|
|
293
|
+
* Labels that would overlap fan out into a shared column. A plot that labels each end of its series apart passes
|
|
294
|
+
* the `rows` and `side` of one end, and `lane` to route them out to a lane whether or not they overlap.
|
|
237
295
|
*/
|
|
238
|
-
atSeriesEnds(state, end = {}) {
|
|
296
|
+
atSeriesEnds(state, env, end = {}) {
|
|
239
297
|
if (end.rows)
|
|
240
|
-
return this.#seriesEnds(state, end);
|
|
298
|
+
return this.#seriesEnds(state, env, end);
|
|
241
299
|
// A label on a series' first point would sit on its own line: it goes out to a lane instead.
|
|
242
300
|
const firsts = ValueLabels.#firstRows(state);
|
|
243
301
|
const labelled = state.labelled ?? [];
|
|
244
302
|
return [
|
|
245
|
-
...this.#seriesEnds(state, { rows: labelled.filter((row) => !firsts.has(row)) }),
|
|
246
|
-
...this.#seriesEnds(state, {
|
|
303
|
+
...this.#seriesEnds(state, env, { rows: labelled.filter((row) => !firsts.has(row)) }),
|
|
304
|
+
...this.#seriesEnds(state, env, {
|
|
247
305
|
rows: labelled.filter((row) => firsts.has(row)),
|
|
248
306
|
lane: { elbowGap: ValueLabels.FIRST_LANE_GAP }
|
|
249
307
|
})
|
|
250
308
|
];
|
|
251
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* The labels of a plot whose rows have several values (a box's quartiles, a bullet's target): one `text` marker per
|
|
312
|
+
* part labelled, each of `rows` written at that part's value in its context - one label per value, for a part
|
|
313
|
+
* holding several (a box's outliers). `at` places a label at a value: its point, and the shape around it its
|
|
314
|
+
* `anchor` reads.
|
|
315
|
+
*/
|
|
316
|
+
partMarkers(env, rows, at, defaults = {}) {
|
|
317
|
+
const { styles: shared, ...hooks } = this.hooks(env);
|
|
318
|
+
const { font } = this;
|
|
319
|
+
// `series` labels the rows of those series only.
|
|
320
|
+
const named = this.series && new Set(this.series);
|
|
321
|
+
const labelled = named ? rows.filter((row) => named.has(String(row[SERIES_KEY]))) : rows;
|
|
322
|
+
return this.parts.flatMap((part) => {
|
|
323
|
+
if (defaults.skip?.includes(part.name))
|
|
324
|
+
return [];
|
|
325
|
+
const placed = labelled.flatMap((row) => {
|
|
326
|
+
const own = RowContext.of(row)[part.name];
|
|
327
|
+
return (Array.isArray(own) ? own : [own])
|
|
328
|
+
.filter((value) => typeof value === 'number' && Number.isFinite(value))
|
|
329
|
+
.map((value) => ({ ...row, [PART_VALUE]: value }));
|
|
330
|
+
});
|
|
331
|
+
const label = {
|
|
332
|
+
...hooks,
|
|
333
|
+
...part.placement,
|
|
334
|
+
layout: 'point',
|
|
335
|
+
text: (row) => part.format(Number(row[PART_VALUE]), row, undefined, part.name),
|
|
336
|
+
styles: {
|
|
337
|
+
...shared,
|
|
338
|
+
...font,
|
|
339
|
+
fill: this.fill ??
|
|
340
|
+
(this.color === 'series' ? defaults.seriesColor : undefined) ??
|
|
341
|
+
'currentColor',
|
|
342
|
+
fontSize: font?.fontSize ?? 11
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
const marker = placed.length > 0 &&
|
|
346
|
+
PointLayout.build(label, at(PART_VALUE), placed, { gap: this.#cfg.text.label.gap });
|
|
347
|
+
return marker ? [marker] : [];
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Where a part label of a row sits on a plot of categories: at the row's `category` (a field or a function of
|
|
352
|
+
* it), level with the part's value, across the category's band - which an `anchor` reads, to write it beside.
|
|
353
|
+
*/
|
|
354
|
+
static bandPoint(state, category,
|
|
355
|
+
/** How wide the shape is across its band, in pixels, when it does not fill it: a violin's inner box. */
|
|
356
|
+
across,
|
|
357
|
+
/** A row's slot of its band, when its series share it side by side. */
|
|
358
|
+
slot) {
|
|
359
|
+
const valueAxis = PlotAxes.valueOf(state);
|
|
360
|
+
const categoryAxis = PlotAxes.categoryOf(state);
|
|
361
|
+
return (value) => ({
|
|
362
|
+
[categoryAxis]: category,
|
|
363
|
+
[valueAxis]: value,
|
|
364
|
+
shift: slot &&
|
|
365
|
+
((row, scales) => {
|
|
366
|
+
const own = slot(row);
|
|
367
|
+
const band = Number(scales[categoryAxis]?.fn?.bandwidth?.() ?? 0);
|
|
368
|
+
if (!own || !band)
|
|
369
|
+
return undefined;
|
|
370
|
+
const share = band / own.count;
|
|
371
|
+
const offset = share * own.index + share / 2 - band / 2;
|
|
372
|
+
return categoryAxis === 'x' ? { dx: offset, dy: 0 } : { dx: 0, dy: offset };
|
|
373
|
+
}),
|
|
374
|
+
size: (_row, scales) => {
|
|
375
|
+
const band = across ?? Number(scales[categoryAxis]?.fn?.bandwidth?.() ?? 0);
|
|
376
|
+
return categoryAxis === 'x' ? { width: band, height: 0 } : { width: 0, height: band };
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
/** The placement that writes each of `parts` beside its category's band: to its right, or above sideways bands. */
|
|
381
|
+
static besideBand(state, parts) {
|
|
382
|
+
const beside = { anchor: state.axes?.isHorizontal ? 'top' : 'right' };
|
|
383
|
+
return Object.fromEntries(parts.map((part) => [part, beside]));
|
|
384
|
+
}
|
|
385
|
+
/** A series-over-`x` plot's labels in its {@link layout}: at its series' ends, or along its lines. */
|
|
386
|
+
forSeries(state, env) {
|
|
387
|
+
return this.layout === 'path' ? this.alongSeries(state, env) : this.atSeriesEnds(state, env);
|
|
388
|
+
}
|
|
389
|
+
/** The side of its point a `'point'` label is written on: its placement's, else after it. */
|
|
390
|
+
get side() {
|
|
391
|
+
return this.placement.side ?? 'after';
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* A series-over-`x` plot's `'path'` labels, for its line or area markers: each series' name - or, with a `format`,
|
|
395
|
+
* the text it writes for the series' first row - along its line, colored by the series.
|
|
396
|
+
*/
|
|
397
|
+
alongSeries(state, env) {
|
|
398
|
+
const { font } = this;
|
|
399
|
+
const nameOf = (d) => String(d[SERIES_KEY]);
|
|
400
|
+
const { styles: shared, ...hooks } = this.hooks(env);
|
|
401
|
+
return [
|
|
402
|
+
{
|
|
403
|
+
...hooks,
|
|
404
|
+
...this.placement,
|
|
405
|
+
layout: 'path',
|
|
406
|
+
text: (d) => (this.formatted ? this.text(d) : nameOf(d)),
|
|
407
|
+
styles: {
|
|
408
|
+
...shared,
|
|
409
|
+
...font,
|
|
410
|
+
fill: this.fill ?? ((d) => this.#colorOf(state, d) ?? 'currentColor'),
|
|
411
|
+
fontSize: font?.fontSize ?? 12
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
];
|
|
415
|
+
}
|
|
416
|
+
/** A series row's color: the segment it falls in, else its series'. */
|
|
417
|
+
#colorOf(state, d) {
|
|
418
|
+
const id = String(d[SERIES_ID_KEY]);
|
|
419
|
+
const group = state.scopedGroups?.find((g) => (g.id ?? g.name) === id);
|
|
420
|
+
const segment = group?.segments.find((seg) => seg.match(d));
|
|
421
|
+
return (segment?.color ??
|
|
422
|
+
group?.segments[0]?.color ??
|
|
423
|
+
group?.color ??
|
|
424
|
+
state.colorForSeries?.(String(d[SERIES_KEY])));
|
|
425
|
+
}
|
|
426
|
+
/** `markers` with `labels` on each one of `type`: the shapes of a series carry its labels. */
|
|
427
|
+
static onMarkers(markers, type, labels) {
|
|
428
|
+
if (!labels?.length)
|
|
429
|
+
return markers;
|
|
430
|
+
return markers.map((marker) => (marker.type === type ? { ...marker, label: labels } : marker));
|
|
431
|
+
}
|
|
252
432
|
/** How far (px) a lane takes the label of a series' first point from it - clear of the line that leaves it. */
|
|
253
433
|
static FIRST_LANE_GAP = 28;
|
|
254
434
|
/** The first row of every series that has more than one. */
|
|
@@ -263,50 +443,39 @@ export class ValueLabels {
|
|
|
263
443
|
}
|
|
264
444
|
return new Set([...first].filter(([id]) => (counts.get(id) ?? 0) > 1).map(([, row]) => row));
|
|
265
445
|
}
|
|
266
|
-
#seriesEnds(state, end) {
|
|
267
|
-
const
|
|
268
|
-
if (
|
|
446
|
+
#seriesEnds(state, env, end) {
|
|
447
|
+
const rows = new Set(end.rows ?? state.labelled ?? []);
|
|
448
|
+
if (rows.size === 0)
|
|
269
449
|
return [];
|
|
270
|
-
const { font
|
|
271
|
-
const
|
|
272
|
-
const
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
dx: font?.dx ?? (anchor === 'start' ? 6 : anchor === 'end' ? -6 : 0),
|
|
298
|
-
dy: font?.dy ?? (anchor === 'outside' ? -8 : 0),
|
|
299
|
-
textAnchor: this.textAnchor ?? (anchor === 'start' || anchor === 'end' ? anchor : 'middle'),
|
|
300
|
-
lineAnchor: font?.lineAnchor ?? (anchor === 'outside' ? 'bottom' : 'middle')
|
|
301
|
-
},
|
|
302
|
-
declutter: {
|
|
303
|
-
connector: this.strokeStyle,
|
|
304
|
-
aligned: !!end.lane && (anchor === 'start' || anchor === 'end'),
|
|
305
|
-
elbowGap: typeof end.lane === 'object' ? end.lane.elbowGap : undefined,
|
|
306
|
-
flip: end.flip
|
|
450
|
+
const { font } = this;
|
|
451
|
+
const side = end.side ?? this.side;
|
|
452
|
+
const at = PointLayout.sideOf(side, this.placement.gap);
|
|
453
|
+
const { styles: shared, ...hooks } = this.hooks(env);
|
|
454
|
+
return [
|
|
455
|
+
{
|
|
456
|
+
...hooks,
|
|
457
|
+
layout: 'point',
|
|
458
|
+
select: (row) => rows.has(row),
|
|
459
|
+
grouping: SERIES_ID_KEY,
|
|
460
|
+
text: (d) => this.text(d),
|
|
461
|
+
styles: {
|
|
462
|
+
...shared,
|
|
463
|
+
...font,
|
|
464
|
+
fill: this.fill ?? ((d) => this.#colorOf(state, d) ?? 'currentColor'),
|
|
465
|
+
fontSize: font?.fontSize ?? 12,
|
|
466
|
+
dx: at.dx,
|
|
467
|
+
dy: at.dy,
|
|
468
|
+
textAnchor: at.textAnchor,
|
|
469
|
+
lineAnchor: at.lineAnchor
|
|
470
|
+
},
|
|
471
|
+
declutter: {
|
|
472
|
+
connector: this.strokeStyle,
|
|
473
|
+
aligned: !!end.lane && (side === 'after' || side === 'before'),
|
|
474
|
+
elbowGap: typeof end.lane === 'object' ? end.lane.elbowGap : undefined,
|
|
475
|
+
flip: end.flip
|
|
476
|
+
}
|
|
307
477
|
}
|
|
308
|
-
|
|
309
|
-
return marker.data?.length ? [marker] : [];
|
|
478
|
+
];
|
|
310
479
|
}
|
|
311
480
|
/** The rows of a series-over-`x` plot that cannot be labelled: a gap, or a stack with no top. For the "transforms" phase's `labels.skip`. */
|
|
312
481
|
static skipGaps(state) {
|
|
@@ -322,13 +491,11 @@ export class ValueLabels {
|
|
|
322
491
|
* domain when the scales set one, so it holds across a timeline; else off
|
|
323
492
|
* every value.
|
|
324
493
|
*/
|
|
325
|
-
reachAtSeriesEnds(state,
|
|
494
|
+
reachAtSeriesEnds(state, pointSide = this.side) {
|
|
326
495
|
const series = state.resolvedSeries ?? [];
|
|
327
|
-
const {
|
|
328
|
-
const
|
|
329
|
-
const
|
|
330
|
-
const textAnchor = this.textAnchor ?? (anchor === 'start' ? 'start' : anchor === 'end' ? 'end' : 'middle');
|
|
331
|
-
const lineAnchor = font?.lineAnchor ?? (anchor === 'outside' ? 'bottom' : 'middle');
|
|
496
|
+
const { format } = this;
|
|
497
|
+
const written = PointLayout.sideOf(pointSide, this.placement.gap);
|
|
498
|
+
const { dx, dy, textAnchor, lineAnchor } = written;
|
|
332
499
|
const side = {
|
|
333
500
|
x: textAnchor === 'start' ? 'after' : textAnchor === 'end' ? 'before' : 'middle',
|
|
334
501
|
y: lineAnchor === 'top' ? 'after' : lineAnchor === 'bottom' ? 'before' : 'middle'
|
|
@@ -356,7 +523,7 @@ export class ValueLabels {
|
|
|
356
523
|
const lo = Number(domain[0]);
|
|
357
524
|
const hi = Number(domain[domain.length - 1]);
|
|
358
525
|
for (const s of series)
|
|
359
|
-
texts.push(format(lo, s.name), format(hi, s.name));
|
|
526
|
+
texts.push(format(lo, undefined, s.name), format(hi, undefined, s.name));
|
|
360
527
|
}
|
|
361
528
|
else {
|
|
362
529
|
for (const s of series) {
|
|
@@ -366,7 +533,7 @@ export class ValueLabels {
|
|
|
366
533
|
for (const d of s.data) {
|
|
367
534
|
const v = Number(y(d));
|
|
368
535
|
if (!Number.isNaN(v))
|
|
369
|
-
texts.push(format(v, s.name));
|
|
536
|
+
texts.push(format(v, undefined, s.name));
|
|
370
537
|
}
|
|
371
538
|
}
|
|
372
539
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Box } from '../margins/Box';
|
|
2
|
-
import
|
|
2
|
+
import { PlotAxes } from '../../phases/data/PlotAxes';
|
|
3
3
|
import type { ProcessedData, ProcessedRow } from '../../types/phases';
|
|
4
|
-
import type { TooltipAnchorX, TooltipAnchorY } from '../../types/layout/tooltip';
|
|
5
4
|
import type { Series } from '../../types/plots/data/common';
|
|
5
|
+
import type { TooltipAnchorX, TooltipAnchorY } from '../../types/layout/tooltip';
|
|
6
6
|
/** What a tooltip is shown from, each read reactively. */
|
|
7
7
|
export type TooltipInputs = {
|
|
8
8
|
/** The point it sits beside. */
|
|
@@ -46,16 +46,15 @@ export declare class TooltipState {
|
|
|
46
46
|
/** A value as plain text: a date as a locale date, a number as `number` writes it (when given), anything else as itself. */
|
|
47
47
|
static value(value: unknown, number?: (value: number) => string): string;
|
|
48
48
|
/**
|
|
49
|
-
* How a hovered row reads by default, on every plot: its series,
|
|
50
|
-
* plot groups its rows; then where it sits - `category: value` when one
|
|
51
|
-
* axis
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* (the plot's `y` when neither axis holds categories) and the color's - read as it writes them.
|
|
49
|
+
* How a hovered row reads by default, on every plot, from its context (see {@link RowContext}): its series,
|
|
50
|
+
* when the plot groups its rows; then where it sits - `category: value` when one axis is a band of categories,
|
|
51
|
+
* else `x: y` (an axis the transforms spread into a span, a bin's, as `from-to`); then the value its color
|
|
52
|
+
* shows, when that is a number (a heatmap's cells). With `number`, the values - the one on the value axis and
|
|
53
|
+
* the color's - read as it writes them.
|
|
55
54
|
*/
|
|
56
55
|
static default(state: {
|
|
57
56
|
processedData?: ProcessedData;
|
|
58
|
-
resolvedSeries?: Series<
|
|
57
|
+
resolvedSeries?: Series<any>[];
|
|
59
58
|
channels?: {
|
|
60
59
|
grouping?: unknown;
|
|
61
60
|
color?: {
|