@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,48 @@
|
|
|
1
|
+
import { resolveAccessor } from '../../utils/accessors';
|
|
2
|
+
/** The bands a `band` marker draws, one per category its rows (or its `value`) name, in the order they first come. */
|
|
3
|
+
export class Bands {
|
|
4
|
+
static #WHOLE = { start: 0, end: 0 };
|
|
5
|
+
/** The marker's bands. Rows that share a category share one band, which fills what all of their slices do. */
|
|
6
|
+
static of(marker) {
|
|
7
|
+
const { rows, categoryOf } = Bands.#rowsOf(marker);
|
|
8
|
+
const sliceOf = Bands.#sliceOf(marker.slice);
|
|
9
|
+
const bands = new Map();
|
|
10
|
+
rows.forEach((row, index) => {
|
|
11
|
+
const category = categoryOf(row);
|
|
12
|
+
if (category == null)
|
|
13
|
+
return;
|
|
14
|
+
const key = category instanceof Date ? +category : category;
|
|
15
|
+
const slice = sliceOf(row);
|
|
16
|
+
const band = bands.get(key);
|
|
17
|
+
if (!band) {
|
|
18
|
+
bands.set(key, { category, slice, row, index });
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// What either one fills: the least left out at each end.
|
|
22
|
+
band.slice = {
|
|
23
|
+
start: Math.min(band.slice.start, slice.start),
|
|
24
|
+
end: Math.min(band.slice.end, slice.end)
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
return [...bands.values()];
|
|
28
|
+
}
|
|
29
|
+
/** The rows a marker draws from, and the category of each: its `data` and `value`, or its `value`'s own. */
|
|
30
|
+
static #rowsOf(marker) {
|
|
31
|
+
const { value, data } = marker;
|
|
32
|
+
if (data) {
|
|
33
|
+
const read = resolveAccessor(value);
|
|
34
|
+
return { rows: data, categoryOf: read };
|
|
35
|
+
}
|
|
36
|
+
const values = (Array.isArray(value) ? value : [value]);
|
|
37
|
+
return { rows: values, categoryOf: (row) => row };
|
|
38
|
+
}
|
|
39
|
+
/** Each row's slice: the marker's own, or a function of the row's; the whole band when it gives none. */
|
|
40
|
+
static #sliceOf(slice) {
|
|
41
|
+
const whole = Bands.#WHOLE;
|
|
42
|
+
const read = typeof slice === 'function' ? slice : () => slice;
|
|
43
|
+
return (row) => {
|
|
44
|
+
const own = read(row);
|
|
45
|
+
return own ? { start: own.start ?? 0, end: own.end ?? 0 } : whole;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -9,19 +9,19 @@
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Renders one `'bar'` marker: `role: 'segment'` (visible bar via
|
|
12
|
-
* `<BarX>`/`<BarY>`)
|
|
13
|
-
* one segment)
|
|
12
|
+
* `<BarX>`/`<BarY>`) or `role: 'hitArea'` (invisible hover hit region for
|
|
13
|
+
* one segment).
|
|
14
14
|
*/
|
|
15
15
|
let { marker }: { marker: BarMarkerConfig } = $props();
|
|
16
16
|
const events = MarkerEvents.use(() => marker);
|
|
17
|
-
/** The hover band stands for no row, so a style that is a function of one does not apply to it. */
|
|
18
|
-
const flatStyles = $derived(RowStyle.flat(marker.styles));
|
|
19
17
|
|
|
20
18
|
const cfg = $derived(getConfiguration());
|
|
21
19
|
const data = $derived(marker.data ?? []);
|
|
22
20
|
const channelFill = $derived(MarkerChannels.buildFill(data, marker.color, marker.scales, cfg));
|
|
23
21
|
|
|
24
|
-
const
|
|
22
|
+
const context = usePlot();
|
|
23
|
+
const plot = context.svelteplot;
|
|
24
|
+
const isHorizontal = $derived(marker.isHorizontal ?? context.axes?.isHorizontal ?? false);
|
|
25
25
|
function categoryScaleFor(isHorizontal: boolean) {
|
|
26
26
|
return isHorizontal ? plot.scales.y : plot.scales.x;
|
|
27
27
|
}
|
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
</script>
|
|
39
39
|
|
|
40
40
|
{#if marker.role === 'segment'}
|
|
41
|
-
{@const categoryScale = categoryScaleFor(
|
|
41
|
+
{@const categoryScale = categoryScaleFor(isHorizontal)}
|
|
42
42
|
{@const bandwidth = categoryScale?.type === 'band' ? categoryScale.fn.bandwidth() : 0}
|
|
43
43
|
{@const centered =
|
|
44
44
|
marker.thickness != null ? Math.max(0, (bandwidth - marker.thickness) / 2) : undefined}
|
|
45
|
-
{#if
|
|
45
|
+
{#if isHorizontal}
|
|
46
46
|
<BarX
|
|
47
47
|
{...events.props}
|
|
48
48
|
{data}
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
/>
|
|
83
83
|
{/if}
|
|
84
84
|
{:else}
|
|
85
|
-
{@const categoryScale = categoryScaleFor(
|
|
85
|
+
{@const categoryScale = categoryScaleFor(isHorizontal)}
|
|
86
86
|
{#if categoryScale?.type === 'band'}
|
|
87
87
|
{@const bandwidth = categoryScale.fn.bandwidth()}
|
|
88
88
|
{@const bandStart = Number(categoryScale.fn(marker.category as never) ?? 0)}
|
|
@@ -90,69 +90,28 @@
|
|
|
90
90
|
{@const insetRight = (marker.styles?.insetRight ?? 0) * bandwidth}
|
|
91
91
|
{@const insetTop = (marker.styles?.insetTop ?? 0) * bandwidth}
|
|
92
92
|
{@const insetBottom = (marker.styles?.insetBottom ?? 0) * bandwidth}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
/>
|
|
106
|
-
{:else}
|
|
107
|
-
<rect
|
|
108
|
-
class="dct-hit-area"
|
|
109
|
-
x={bandStart + insetLeft}
|
|
110
|
-
y={rangeMin + insetBottom}
|
|
111
|
-
width={Math.max(0, bandwidth - insetLeft - insetRight)}
|
|
112
|
-
height={Math.max(0, rangeMax - rangeMin - insetTop - insetBottom)}
|
|
113
|
-
fill="transparent"
|
|
114
|
-
{...events.forRow(data[0], 0)}
|
|
115
|
-
/>
|
|
116
|
-
{/if}
|
|
93
|
+
<!-- The band runs the plot's whole value axis, so the pointer needn't be over the bar. -->
|
|
94
|
+
{@const [rangeMin, rangeMax] = valueExtentFor(isHorizontal)}
|
|
95
|
+
{#if isHorizontal}
|
|
96
|
+
<rect
|
|
97
|
+
class="dct-hit-area"
|
|
98
|
+
x={rangeMin + insetLeft}
|
|
99
|
+
y={bandStart + insetBottom}
|
|
100
|
+
width={Math.max(0, rangeMax - rangeMin - insetLeft - insetRight)}
|
|
101
|
+
height={Math.max(0, bandwidth - insetTop - insetBottom)}
|
|
102
|
+
fill="transparent"
|
|
103
|
+
{...events.forRow(data[0], 0)}
|
|
104
|
+
/>
|
|
117
105
|
{:else}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
{
|
|
121
|
-
{
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
height={thickness}
|
|
128
|
-
fill={flatStyles.fill}
|
|
129
|
-
fill-opacity={flatStyles.fillOpacity}
|
|
130
|
-
stroke={flatStyles.stroke}
|
|
131
|
-
stroke-width={flatStyles.strokeWidth}
|
|
132
|
-
stroke-opacity={flatStyles.strokeOpacity}
|
|
133
|
-
stroke-dasharray={flatStyles.strokeDasharray}
|
|
134
|
-
rx={flatStyles.borderRadius}
|
|
135
|
-
pointer-events="none"
|
|
136
|
-
/>
|
|
137
|
-
{:else}
|
|
138
|
-
{@const thickness = Math.max(0, bandwidth - insetLeft - insetRight) + 2}
|
|
139
|
-
{@const center = bandStart + insetLeft + (bandwidth - insetLeft - insetRight) / 2}
|
|
140
|
-
<rect
|
|
141
|
-
class="hover-area"
|
|
142
|
-
x={center - thickness / 2}
|
|
143
|
-
y={valueMin}
|
|
144
|
-
width={thickness}
|
|
145
|
-
height={Math.max(0, valueMax - valueMin)}
|
|
146
|
-
fill={flatStyles.fill}
|
|
147
|
-
fill-opacity={flatStyles.fillOpacity}
|
|
148
|
-
stroke={flatStyles.stroke}
|
|
149
|
-
stroke-width={flatStyles.strokeWidth}
|
|
150
|
-
stroke-opacity={flatStyles.strokeOpacity}
|
|
151
|
-
stroke-dasharray={flatStyles.strokeDasharray}
|
|
152
|
-
ry={flatStyles.borderRadius}
|
|
153
|
-
pointer-events="none"
|
|
154
|
-
/>
|
|
155
|
-
{/if}
|
|
106
|
+
<rect
|
|
107
|
+
class="dct-hit-area"
|
|
108
|
+
x={bandStart + insetLeft}
|
|
109
|
+
y={rangeMin + insetBottom}
|
|
110
|
+
width={Math.max(0, bandwidth - insetLeft - insetRight)}
|
|
111
|
+
height={Math.max(0, rangeMax - rangeMin - insetTop - insetBottom)}
|
|
112
|
+
fill="transparent"
|
|
113
|
+
{...events.forRow(data[0], 0)}
|
|
114
|
+
/>
|
|
156
115
|
{/if}
|
|
157
116
|
{/if}
|
|
158
117
|
{/if}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
const events = MarkerEvents.use(() => marker);
|
|
23
23
|
|
|
24
24
|
const plot = usePlot();
|
|
25
|
-
const isHorizontal = $derived(plot.axes?.isHorizontal ?? false);
|
|
25
|
+
const isHorizontal = $derived(marker.isHorizontal ?? plot.axes?.isHorizontal ?? false);
|
|
26
26
|
const BollingerMark = $derived(isHorizontal ? BollingerX : BollingerY);
|
|
27
27
|
|
|
28
28
|
const cfg = $derived(getConfiguration());
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
const events = MarkerEvents.use(() => marker);
|
|
20
20
|
|
|
21
21
|
const plot = usePlot();
|
|
22
|
-
const isHorizontal = $derived(plot.axes?.isHorizontal ?? false);
|
|
22
|
+
const isHorizontal = $derived(marker.isHorizontal ?? plot.axes?.isHorizontal ?? false);
|
|
23
23
|
const BoxMark = $derived(isHorizontal ? BoxX : BoxY);
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BoxScales } from '../../types/markers/labels/box';
|
|
2
|
+
type Dotted = {
|
|
3
|
+
r?: unknown;
|
|
4
|
+
styles?: object;
|
|
5
|
+
};
|
|
6
|
+
/** A dot's radius in pixels, as its marker draws it. */
|
|
7
|
+
export declare class DotRadius {
|
|
8
|
+
/** Its `r`: a number as it is, a channel through the plot's `r` scale; else its `dotRadius`, else `fallback`. */
|
|
9
|
+
static of(marker: Dotted, row: unknown, scales: BoxScales, fallback?: number): number;
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const read = (channel, row) => typeof channel === 'function'
|
|
2
|
+
? channel(row)
|
|
3
|
+
: typeof channel === 'string' || typeof channel === 'symbol'
|
|
4
|
+
? row?.[channel]
|
|
5
|
+
: channel;
|
|
6
|
+
/** A dot's radius in pixels, as its marker draws it. */
|
|
7
|
+
export class DotRadius {
|
|
8
|
+
/** Its `r`: a number as it is, a channel through the plot's `r` scale; else its `dotRadius`, else `fallback`. */
|
|
9
|
+
static of(marker, row, scales, fallback = 5) {
|
|
10
|
+
const { r } = marker;
|
|
11
|
+
if (typeof r === 'number')
|
|
12
|
+
return r;
|
|
13
|
+
if (r !== undefined && scales.r) {
|
|
14
|
+
const value = Number(scales.r.fn(read(r, row)));
|
|
15
|
+
if (Number.isFinite(value))
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
const own = marker.styles?.dotRadius;
|
|
19
|
+
return typeof own === 'number' ? own : fallback;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -1,283 +1,25 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { usePlot } from '../../layout/plot/usePlot';
|
|
3
|
-
import
|
|
4
|
-
import TextMarker from '../text/TextMarker.svelte';
|
|
5
|
-
import RuleMarker from '../rule/RuleMarker.svelte';
|
|
6
|
-
import BarMarker from '../bar/BarMarker.svelte';
|
|
7
|
-
import { getConfiguration } from '../../configuration/config.svelte';
|
|
8
|
-
import { NumberFormat } from '../../utils/NumberFormat';
|
|
9
|
-
import { BandNudge } from '../utils/BandNudge';
|
|
10
|
-
import type { BandSlice } from '../../types/layout/hover';
|
|
11
|
-
import type { HoverMarkerConfig } from '../../types/markers/common';
|
|
3
|
+
import { PointPixel } from '../utils/PointPixel';
|
|
12
4
|
import type { HoverDisplayPoint } from '../../types/layout/hover';
|
|
13
5
|
|
|
14
6
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* any pixel math. Draws optional x/y crosshair rules plus a dot + value label
|
|
19
|
-
* for each matched point.
|
|
20
|
-
*
|
|
21
|
-
* Takes the raw `marker` config plus the couple of things it can't know on
|
|
22
|
-
* its own - `activePoint` (the specific matched point actually under the
|
|
23
|
-
* cursor, for the crosshair position; see `controller.svelte.ts`'s own doc
|
|
24
|
-
* comment) and whether the active hover strategy implies a crosshair on
|
|
25
|
-
* each axis by default - the same "component owns its own rendering"
|
|
26
|
-
* pattern `BarMarker`/`RuleMarker` follow. `activePoint`/
|
|
27
|
-
* `impliesCrosshairX`/`impliesCrosshairY` are all optional and default to
|
|
28
|
-
* "no crosshair".
|
|
29
|
-
*
|
|
30
|
-
* `areaX`/`areaY` are a separate, always-explicit opt-in (no implied
|
|
31
|
-
* default) for a thickened area highlight in place of the thin crosshair -
|
|
32
|
-
* see `HoverMarkerConfig`'s own doc comment. Rendered via `BarMarker`'s
|
|
33
|
-
* `role: 'highlight'`, so it renders nothing on an axis without a band
|
|
34
|
-
* scale (e.g. a line/scatter plot's continuous axis).
|
|
7
|
+
* Where the hover is, rendered *inside* a `<Plot>`: it reports the pixel position of the point under the pointer,
|
|
8
|
+
* through the host plot's scales, so a synced plot's tooltip can sit on it. It draws nothing itself - the
|
|
9
|
+
* `hover` marker's `back` and `front` markers are drawn by `GeometryLayout`, as every other marker.
|
|
35
10
|
*/
|
|
36
11
|
interface Props {
|
|
37
|
-
data?: HoverDisplayPoint[];
|
|
38
|
-
/** Narrowed to just the fields this component reads - `HoverMarkerConfig` also carries routing/scoping fields (`series`/`scope`/`strategy`/`sync`) it has no use for. */
|
|
39
|
-
marker: Pick<
|
|
40
|
-
HoverMarkerConfig,
|
|
41
|
-
| 'ruleX'
|
|
42
|
-
| 'ruleY'
|
|
43
|
-
| 'areaX'
|
|
44
|
-
| 'areaY'
|
|
45
|
-
| 'showLabels'
|
|
46
|
-
| 'format'
|
|
47
|
-
| 'rule'
|
|
48
|
-
| 'area'
|
|
49
|
-
| 'dot'
|
|
50
|
-
| 'text'
|
|
51
|
-
| 'decimals'
|
|
52
|
-
| 'prefix'
|
|
53
|
-
| 'suffix'
|
|
54
|
-
| 'signDisplay'
|
|
55
|
-
>;
|
|
56
12
|
activePoint?: HoverDisplayPoint | null;
|
|
57
|
-
|
|
58
|
-
impliesCrosshairY?: boolean;
|
|
59
|
-
/** Reports `activePoint`'s real pixel position within this facet's own box, or `null` when nothing's matched. */
|
|
13
|
+
/** Reports `activePoint`'s pixel position within this facet's own box, or `null` when nothing's matched. */
|
|
60
14
|
onActivePointPixel?: (pos: { x: number; y: number } | null) => void;
|
|
61
15
|
}
|
|
62
16
|
|
|
63
|
-
let {
|
|
64
|
-
data = [],
|
|
65
|
-
marker,
|
|
66
|
-
activePoint = null,
|
|
67
|
-
impliesCrosshairX = false,
|
|
68
|
-
impliesCrosshairY = false,
|
|
69
|
-
onActivePointPixel
|
|
70
|
-
}: Props = $props();
|
|
71
|
-
|
|
72
|
-
const cfg = $derived(getConfiguration());
|
|
17
|
+
let { activePoint = null, onActivePointPixel }: Props = $props();
|
|
73
18
|
const plot = usePlot().svelteplot;
|
|
74
19
|
|
|
75
|
-
|
|
76
|
-
function scaledPixel(
|
|
77
|
-
scale: { type?: string; fn?: (v: never) => unknown } | undefined,
|
|
78
|
-
value: unknown
|
|
79
|
-
): number | null {
|
|
80
|
-
if (!scale?.fn || value == null) return null;
|
|
81
|
-
const raw = Number(scale.fn(value as never));
|
|
82
|
-
if (!Number.isFinite(raw)) return null;
|
|
83
|
-
if (scale.type === 'band') {
|
|
84
|
-
const bandwidth = (scale.fn as { bandwidth?: () => number }).bandwidth?.() ?? 0;
|
|
85
|
-
return raw + bandwidth / 2;
|
|
86
|
-
}
|
|
87
|
-
return raw;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const nudgeOf = (point: { areaInset?: BandSlice } | null | undefined) =>
|
|
91
|
-
BandNudge.of(plot.scales, point?.areaInset);
|
|
92
|
-
|
|
93
|
-
const activePixel = $derived.by((): { x: number; y: number } | null => {
|
|
94
|
-
if (!activePoint) return null;
|
|
95
|
-
const x = scaledPixel(plot.scales.x, activePoint.x);
|
|
96
|
-
const y = scaledPixel(plot.scales.y, activePoint.y);
|
|
97
|
-
if (x == null || y == null) return null;
|
|
98
|
-
const nudge = nudgeOf(activePoint);
|
|
99
|
-
return { x: x + nudge.dx, y: y + nudge.dy };
|
|
100
|
-
});
|
|
20
|
+
const activePixel = $derived(activePoint ? PointPixel.of(plot.scales, activePoint) : null);
|
|
101
21
|
|
|
102
22
|
$effect(() => {
|
|
103
23
|
onActivePointPixel?.(activePixel);
|
|
104
24
|
});
|
|
105
|
-
|
|
106
|
-
const showCrosshairX = $derived(
|
|
107
|
-
marker.ruleX !== false && (impliesCrosshairX || marker.ruleX === true)
|
|
108
|
-
);
|
|
109
|
-
const showCrosshairY = $derived(
|
|
110
|
-
marker.ruleY !== false && (impliesCrosshairY || marker.ruleY === true)
|
|
111
|
-
);
|
|
112
|
-
const ruleX = $derived(showCrosshairX ? (activePoint?.x ?? null) : null);
|
|
113
|
-
const ruleY = $derived(showCrosshairY ? (activePoint?.y ?? null) : null);
|
|
114
|
-
// areaX/areaY have no implied default - always off unless explicitly set.
|
|
115
|
-
const areaX = $derived(marker.areaX === true ? (activePoint?.x ?? null) : null);
|
|
116
|
-
const areaY = $derived(marker.areaY === true ? (activePoint?.y ?? null) : null);
|
|
117
|
-
/**
|
|
118
|
-
* The part of the band an area covers: the active point's own slice (a grouped bar's series), or the whole
|
|
119
|
-
* band while the hover matches more than one point in that category, as its dots do.
|
|
120
|
-
*/
|
|
121
|
-
const areaInsetOf = (axis: 'x' | 'y'): BandSlice | undefined => {
|
|
122
|
-
const at = activePoint?.[axis];
|
|
123
|
-
const key = (value: unknown) => (value instanceof Date ? +value : value);
|
|
124
|
-
const shared = data.filter((point) => key(point[axis]) === key(at)).length > 1;
|
|
125
|
-
return shared ? undefined : activePoint?.areaInset;
|
|
126
|
-
};
|
|
127
|
-
const areaInsetX = $derived(areaX != null ? areaInsetOf('x') : undefined);
|
|
128
|
-
const areaInsetY = $derived(areaY != null ? areaInsetOf('y') : undefined);
|
|
129
|
-
const showLabels = $derived(marker.showLabels ?? true);
|
|
130
|
-
const format = $derived(marker.format);
|
|
131
|
-
/** The hovered value as the marker's display fields ask; `undefined` while nothing does, so the plot's own label stays. */
|
|
132
|
-
const numberOf = $derived(NumberFormat.maybe(NumberFormat.displayOf(marker), cfg));
|
|
133
|
-
const number = $derived(numberOf ?? NumberFormat.of(undefined, cfg));
|
|
134
|
-
const labelOf = (d: HoverDisplayPoint): string => {
|
|
135
|
-
if (format) return format(d, number);
|
|
136
|
-
const value = Number(d.label);
|
|
137
|
-
return numberOf && d.label !== undefined && d.label !== '' && Number.isFinite(value)
|
|
138
|
-
? numberOf(value)
|
|
139
|
-
: (d.label ?? '');
|
|
140
|
-
};
|
|
141
|
-
const ruleStyle = $derived(marker.rule);
|
|
142
|
-
const areaStyle = $derived({ ...cfg.hover.area, ...marker.area });
|
|
143
|
-
const dotStyle = $derived(marker.dot);
|
|
144
|
-
const fontStyle = $derived(marker.text);
|
|
145
|
-
|
|
146
|
-
/** Explicit style wins; otherwise fall back to the point's own resolved color. */
|
|
147
|
-
const resolveColor = (explicit: string | undefined, point: HoverDisplayPoint) =>
|
|
148
|
-
explicit ?? point.color;
|
|
149
|
-
|
|
150
|
-
// Horizontal gap between the dot's edge and an 'outside'-anchored label -
|
|
151
|
-
// scales with the dot's own resolved radius so the label clears it.
|
|
152
|
-
const dotRadius = $derived(dotStyle?.dotRadius ?? cfg.hover.dot.dotRadius ?? 5);
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Resolves `text.textAnchor: 'outside'` into a per-point anchor +
|
|
156
|
-
* offset, mirroring the value-label `'outside'` anchor's own left/right
|
|
157
|
-
* split (see pyramid/bar's own `ValueAnchor` handling): a positive `x`
|
|
158
|
-
* anchors `'start'` and nudges right, a negative `x` anchors `'end'` and
|
|
159
|
-
* nudges left - so a diverging mark's label sits on the side of the dot
|
|
160
|
-
* away from zero, on whichever side that dot itself landed. Only
|
|
161
|
-
* meaningful when the point's `x` is numeric (e.g. pyramid's magnitude
|
|
162
|
-
* axis); anything else falls through to the plain `text` style unchanged.
|
|
163
|
-
*
|
|
164
|
-
* Also overrides `cfg.hover.font`'s default `dy: -18` (meant for a label
|
|
165
|
-
* floating *above* the dot) back to vertically centered, and clears the
|
|
166
|
-
* dot's own radius horizontally instead of the flat default nudge, so the
|
|
167
|
-
* label doesn't collide with the dot it's labeling.
|
|
168
|
-
*/
|
|
169
|
-
function resolveFontStyle(point: HoverDisplayPoint) {
|
|
170
|
-
if (fontStyle?.textAnchor !== 'outside' || typeof point.x !== 'number') {
|
|
171
|
-
return { ...cfg.hover.font, ...fontStyle, fill: resolveColor(fontStyle?.fill, point) };
|
|
172
|
-
}
|
|
173
|
-
const outward = point.x >= 0;
|
|
174
|
-
const gap = dotRadius + 5;
|
|
175
|
-
return {
|
|
176
|
-
...cfg.hover.font,
|
|
177
|
-
...fontStyle,
|
|
178
|
-
fill: resolveColor(fontStyle?.fill, point),
|
|
179
|
-
textAnchor: outward ? ('start' as const) : ('end' as const),
|
|
180
|
-
lineAnchor: fontStyle?.lineAnchor ?? ('middle' as const),
|
|
181
|
-
dx: fontStyle?.dx ?? (outward ? gap : -gap),
|
|
182
|
-
dy: fontStyle?.dy ?? 0
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
25
|
</script>
|
|
186
|
-
|
|
187
|
-
{#if areaX != null}
|
|
188
|
-
<BarMarker
|
|
189
|
-
marker={{
|
|
190
|
-
type: 'bar',
|
|
191
|
-
role: 'highlight',
|
|
192
|
-
isHorizontal: false,
|
|
193
|
-
data: [],
|
|
194
|
-
category: areaX,
|
|
195
|
-
styles: {
|
|
196
|
-
...areaStyle,
|
|
197
|
-
insetLeft: areaInsetX?.start,
|
|
198
|
-
insetRight: areaInsetX?.end
|
|
199
|
-
}
|
|
200
|
-
}}
|
|
201
|
-
/>
|
|
202
|
-
{/if}
|
|
203
|
-
|
|
204
|
-
{#if areaY != null}
|
|
205
|
-
<BarMarker
|
|
206
|
-
marker={{
|
|
207
|
-
type: 'bar',
|
|
208
|
-
role: 'highlight',
|
|
209
|
-
isHorizontal: true,
|
|
210
|
-
data: [],
|
|
211
|
-
category: areaY,
|
|
212
|
-
styles: {
|
|
213
|
-
...areaStyle,
|
|
214
|
-
insetTop: areaInsetY?.start,
|
|
215
|
-
insetBottom: areaInsetY?.end
|
|
216
|
-
}
|
|
217
|
-
}}
|
|
218
|
-
/>
|
|
219
|
-
{/if}
|
|
220
|
-
|
|
221
|
-
{#if ruleX != null}
|
|
222
|
-
<g transform="translate({nudgeOf(activePoint).dx}, {nudgeOf(activePoint).dy})">
|
|
223
|
-
<RuleMarker
|
|
224
|
-
marker={{
|
|
225
|
-
type: 'rule',
|
|
226
|
-
axis: 'x',
|
|
227
|
-
value: ruleX,
|
|
228
|
-
styles: { ...cfg.hover.rule, ...ruleStyle }
|
|
229
|
-
}}
|
|
230
|
-
/>
|
|
231
|
-
</g>
|
|
232
|
-
{/if}
|
|
233
|
-
|
|
234
|
-
{#if ruleY != null}
|
|
235
|
-
<g transform="translate({nudgeOf(activePoint).dx}, {nudgeOf(activePoint).dy})">
|
|
236
|
-
<RuleMarker
|
|
237
|
-
marker={{
|
|
238
|
-
type: 'rule',
|
|
239
|
-
axis: 'y',
|
|
240
|
-
value: ruleY,
|
|
241
|
-
styles: { ...cfg.hover.rule, ...ruleStyle }
|
|
242
|
-
}}
|
|
243
|
-
/>
|
|
244
|
-
</g>
|
|
245
|
-
{/if}
|
|
246
|
-
|
|
247
|
-
{#if data.length > 0}
|
|
248
|
-
{#each data as point (`${point.series ?? ''}_${point.x}_${point.y}`)}
|
|
249
|
-
<!-- A grouped bar's point sits in its series' slice of the band (`areaInset`), not at the band's middle. -->
|
|
250
|
-
<g transform="translate({nudgeOf(point).dx}, {nudgeOf(point).dy})">
|
|
251
|
-
<DotMarker
|
|
252
|
-
marker={{
|
|
253
|
-
type: 'dot',
|
|
254
|
-
data: [point],
|
|
255
|
-
x: (d) => d.x,
|
|
256
|
-
y: (d) => d.y,
|
|
257
|
-
styles: {
|
|
258
|
-
...cfg.hover.dot,
|
|
259
|
-
...dotStyle,
|
|
260
|
-
dotFill: resolveColor(dotStyle?.dotFill, point),
|
|
261
|
-
dotStroke: resolveColor(dotStyle?.dotStroke, point)
|
|
262
|
-
}
|
|
263
|
-
}}
|
|
264
|
-
/>
|
|
265
|
-
</g>
|
|
266
|
-
{/each}
|
|
267
|
-
{#if showLabels}
|
|
268
|
-
{#each data as point (`${point.series ?? ''}_${point.x}_${point.y}`)}
|
|
269
|
-
<g transform="translate({nudgeOf(point).dx}, {nudgeOf(point).dy})">
|
|
270
|
-
<TextMarker
|
|
271
|
-
marker={{
|
|
272
|
-
type: 'text',
|
|
273
|
-
data: [point],
|
|
274
|
-
x: (d: HoverDisplayPoint) => d.x,
|
|
275
|
-
y: (d: HoverDisplayPoint) => d.y,
|
|
276
|
-
text: labelOf,
|
|
277
|
-
styles: resolveFontStyle(point)
|
|
278
|
-
}}
|
|
279
|
-
/>
|
|
280
|
-
</g>
|
|
281
|
-
{/each}
|
|
282
|
-
{/if}
|
|
283
|
-
{/if}
|
|
@@ -1,35 +1,12 @@
|
|
|
1
|
-
import type { HoverMarkerConfig } from '../../types/markers/common';
|
|
2
1
|
import type { HoverDisplayPoint } from '../../types/layout/hover';
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* any pixel math. Draws optional x/y crosshair rules plus a dot + value label
|
|
8
|
-
* for each matched point.
|
|
9
|
-
*
|
|
10
|
-
* Takes the raw `marker` config plus the couple of things it can't know on
|
|
11
|
-
* its own - `activePoint` (the specific matched point actually under the
|
|
12
|
-
* cursor, for the crosshair position; see `controller.svelte.ts`'s own doc
|
|
13
|
-
* comment) and whether the active hover strategy implies a crosshair on
|
|
14
|
-
* each axis by default - the same "component owns its own rendering"
|
|
15
|
-
* pattern `BarMarker`/`RuleMarker` follow. `activePoint`/
|
|
16
|
-
* `impliesCrosshairX`/`impliesCrosshairY` are all optional and default to
|
|
17
|
-
* "no crosshair".
|
|
18
|
-
*
|
|
19
|
-
* `areaX`/`areaY` are a separate, always-explicit opt-in (no implied
|
|
20
|
-
* default) for a thickened area highlight in place of the thin crosshair -
|
|
21
|
-
* see `HoverMarkerConfig`'s own doc comment. Rendered via `BarMarker`'s
|
|
22
|
-
* `role: 'highlight'`, so it renders nothing on an axis without a band
|
|
23
|
-
* scale (e.g. a line/scatter plot's continuous axis).
|
|
3
|
+
* Where the hover is, rendered *inside* a `<Plot>`: it reports the pixel position of the point under the pointer,
|
|
4
|
+
* through the host plot's scales, so a synced plot's tooltip can sit on it. It draws nothing itself - the
|
|
5
|
+
* `hover` marker's `back` and `front` markers are drawn by `GeometryLayout`, as every other marker.
|
|
24
6
|
*/
|
|
25
7
|
interface Props {
|
|
26
|
-
data?: HoverDisplayPoint[];
|
|
27
|
-
/** Narrowed to just the fields this component reads - `HoverMarkerConfig` also carries routing/scoping fields (`series`/`scope`/`strategy`/`sync`) it has no use for. */
|
|
28
|
-
marker: Pick<HoverMarkerConfig, 'ruleX' | 'ruleY' | 'areaX' | 'areaY' | 'showLabels' | 'format' | 'rule' | 'area' | 'dot' | 'text' | 'decimals' | 'prefix' | 'suffix' | 'signDisplay'>;
|
|
29
8
|
activePoint?: HoverDisplayPoint | null;
|
|
30
|
-
|
|
31
|
-
impliesCrosshairY?: boolean;
|
|
32
|
-
/** Reports `activePoint`'s real pixel position within this facet's own box, or `null` when nothing's matched. */
|
|
9
|
+
/** Reports `activePoint`'s pixel position within this facet's own box, or `null` when nothing's matched. */
|
|
33
10
|
onActivePointPixel?: (pos: {
|
|
34
11
|
x: number;
|
|
35
12
|
y: number;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { usePlot } from '../../layout/plot/usePlot';
|
|
3
|
+
import { getConfiguration } from '../../configuration/config.svelte';
|
|
4
|
+
import { CurveGeometry } from './geometry/CurveGeometry';
|
|
5
|
+
import { Box } from '../../layout/margins/Box';
|
|
6
|
+
import type { PathLabelConfig, PathShape } from '../../types/markers/labels/path';
|
|
7
|
+
import type { BoxScales } from '../../types/markers/labels/box';
|
|
8
|
+
|
|
9
|
+
/** Writes one `'path'` label along the curves of a marker: its lines, an area's edge or each dot's rim. */
|
|
10
|
+
const {
|
|
11
|
+
marker,
|
|
12
|
+
label,
|
|
13
|
+
shape
|
|
14
|
+
}: {
|
|
15
|
+
marker: Record<string, unknown>;
|
|
16
|
+
label: PathLabelConfig<string, string>;
|
|
17
|
+
shape: Exclude<PathShape, 'box'>;
|
|
18
|
+
} = $props();
|
|
19
|
+
const plot = usePlot();
|
|
20
|
+
const cfg = $derived(getConfiguration());
|
|
21
|
+
const id = $props.id();
|
|
22
|
+
|
|
23
|
+
const styles = $derived(label.styles ?? {});
|
|
24
|
+
const curves = $derived(
|
|
25
|
+
CurveGeometry.build(shape, marker, label, {
|
|
26
|
+
scales: plot.svelteplot.scales as unknown as BoxScales,
|
|
27
|
+
gap: cfg.text.label.gap,
|
|
28
|
+
measure: (text) => Box.ofText(text, Number(styles.fontSize ?? 11), cfg).width
|
|
29
|
+
})
|
|
30
|
+
);
|
|
31
|
+
// Centred on its curve, a label is drawn over a halo of the background so the curve does not cross it.
|
|
32
|
+
const halo = $derived((label.side ?? '') === 'on' && styles.stroke === undefined);
|
|
33
|
+
/** A style's value for a curve's row: a function of the row, or the value itself. */
|
|
34
|
+
const of = (value: unknown, row: unknown) =>
|
|
35
|
+
(typeof value === 'function' ? value(row) : value) as string | number | undefined;
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
{#each curves as curve, i (i)}
|
|
39
|
+
<path id="{id}-{i}" d={curve.d} fill="none" stroke="none" />
|
|
40
|
+
<text
|
|
41
|
+
dy={curve.dy}
|
|
42
|
+
dominant-baseline={curve.baseline}
|
|
43
|
+
text-anchor={curve.textAnchor}
|
|
44
|
+
fill={String(of(styles.fill, curve.row) ?? curve.fill ?? 'currentColor')}
|
|
45
|
+
fill-opacity={of(styles.fillOpacity, curve.row)}
|
|
46
|
+
font-size={styles.fontSize ?? 11}
|
|
47
|
+
font-weight={of(styles.fontWeight, curve.row)}
|
|
48
|
+
font-style={of(styles.fontStyle, curve.row)}
|
|
49
|
+
stroke={halo ? cfg.background : (of(styles.stroke, curve.row) as string | undefined)}
|
|
50
|
+
stroke-width={halo ? 3 : of(styles.strokeWidth, curve.row)}
|
|
51
|
+
paint-order={halo ? 'stroke' : styles.paintOrder}
|
|
52
|
+
pointer-events="none"
|
|
53
|
+
>
|
|
54
|
+
<textPath href="#{id}-{i}" startOffset={curve.startOffset}>{curve.text}</textPath>
|
|
55
|
+
</text>
|
|
56
|
+
{/each}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PathLabelConfig, PathShape } from '../../types/markers/labels/path';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
marker: Record<string, unknown>;
|
|
4
|
+
label: PathLabelConfig<string, string>;
|
|
5
|
+
shape: Exclude<PathShape, 'box'>;
|
|
6
|
+
};
|
|
7
|
+
declare const CurveLabel: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type CurveLabel = ReturnType<typeof CurveLabel>;
|
|
9
|
+
export default CurveLabel;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TextMarkerConfig } from '../../types/markers/basic/text';
|
|
2
|
+
/** The label a merged row was written by. */
|
|
3
|
+
export declare const LABEL_SOURCE: unique symbol;
|
|
4
|
+
/**
|
|
5
|
+
* Labels drawn as one `text` marker: those whose other options are alike merge, each row tagged with the label
|
|
6
|
+
* it comes from, so labels from several markers declutter together and draw as one.
|
|
7
|
+
*/
|
|
8
|
+
export declare class LabelMerge {
|
|
9
|
+
#private;
|
|
10
|
+
static merge(markers: TextMarkerConfig[]): TextMarkerConfig[];
|
|
11
|
+
}
|