@fundar/data-chart-telling 1.16.0 → 1.18.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 +56 -0
- package/dist/configuration/ConfigVars.svelte +14 -0
- package/dist/configuration/ConfigVars.svelte.d.ts +3 -0
- package/dist/configuration/config.svelte.d.ts +5 -0
- package/dist/configuration/config.svelte.js +20 -6
- package/dist/configuration/themes/dark.js +1 -1
- package/dist/configuration/themes/editorial.js +1 -1
- package/dist/index.d.ts +12 -4
- package/dist/index.js +4 -1
- package/dist/layout/base/BasePlotLayout.svelte +1 -1
- package/dist/layout/figure/Figure.svelte +5 -12
- package/dist/layout/figure/FigureChrome.svelte +2 -10
- package/dist/layout/geometry/GeometryLayout.svelte +219 -44
- 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.js +4 -1
- package/dist/layout/hover/HoverShapes.d.ts +44 -0
- package/dist/layout/hover/HoverShapes.js +103 -0
- package/dist/layout/hover/PlotHover.svelte.d.ts +18 -0
- package/dist/layout/hover/PlotHover.svelte.js +54 -1
- package/dist/layout/legend/DisabledStyle.d.ts +1 -1
- package/dist/layout/legend/DisabledStyle.js +1 -1
- package/dist/layout/legend/DiscreteBadgeItem.svelte +1 -1
- package/dist/layout/legend/DiscreteSection.svelte +1 -1
- package/dist/layout/legend/LegendState.svelte.d.ts +14 -2
- package/dist/layout/legend/LegendState.svelte.js +23 -4
- package/dist/layout/legend/LegendText.d.ts +4 -1
- package/dist/layout/legend/LegendText.js +7 -1
- package/dist/layout/margins/PlotMargins.svelte.d.ts +2 -2
- package/dist/layout/margins/PlotMargins.svelte.js +2 -2
- package/dist/layout/plot/Core.svelte +2 -2
- package/dist/layout/plot/Plot.svelte +4 -2
- package/dist/layout/plot/Plot.svelte.d.ts +2 -1
- package/dist/layout/plot/PublicPlotContext.d.ts +6 -0
- package/dist/layout/plot/PublicPlotContext.js +8 -0
- package/dist/layout/scales/ScalesLayout.svelte +1 -1
- package/dist/layout/styles/ValueLabels.d.ts +43 -4
- package/dist/layout/styles/ValueLabels.js +87 -19
- package/dist/layout/timeline/Timeline.svelte +5 -1
- 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 +5 -0
- package/dist/markers/MarkerKinds.js +1 -0
- package/dist/markers/area/AreaMarker.svelte +3 -0
- package/dist/markers/arrow/ArrowMarker.svelte +9 -5
- 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 +50 -96
- package/dist/markers/bollinger/BollingerMarker.svelte +3 -0
- package/dist/markers/box/BoxMarker.svelte +3 -1
- package/dist/markers/cell/CellMarker.svelte +11 -7
- package/dist/markers/contour/ContourMarker.svelte +3 -0
- package/dist/markers/delaunay/DelaunayLinkMarker.svelte +9 -5
- package/dist/markers/delaunay/DelaunayMeshMarker.svelte +3 -0
- package/dist/markers/density/DensityMarker.svelte +3 -0
- package/dist/markers/difference/DifferenceMarker.svelte +3 -0
- package/dist/markers/dot/DotMarker.svelte +11 -6
- package/dist/markers/geo/GraticuleMarker.svelte +3 -0
- package/dist/markers/geo/SphereMarker.svelte +3 -0
- package/dist/markers/hover/HoverMarker.svelte +7 -249
- package/dist/markers/hover/HoverMarker.svelte.d.ts +4 -27
- package/dist/markers/hull/HullMarker.svelte +3 -0
- package/dist/markers/image/ImageMarker.svelte +3 -0
- package/dist/markers/line/LineMarker.svelte +3 -0
- package/dist/markers/link/LinkMarker.svelte +3 -0
- package/dist/markers/raster/RasterMarker.svelte +3 -0
- package/dist/markers/rect/RectMarker.svelte +25 -17
- package/dist/markers/regression/RegressionMarker.svelte +3 -0
- package/dist/markers/rule/RuleMarker.svelte +15 -5
- package/dist/markers/text/TextFit.d.ts +44 -0
- package/dist/markers/text/TextFit.js +86 -0
- package/dist/markers/text/TextMarker.svelte +186 -90
- package/dist/markers/text/TextMarker.svelte.d.ts +2 -0
- package/dist/markers/tick/TickMarker.svelte +9 -3
- package/dist/markers/trail/TrailMarker.svelte +3 -0
- package/dist/markers/utils/BoxLabel.d.ts +58 -0
- package/dist/markers/utils/BoxLabel.js +175 -0
- package/dist/markers/utils/MarkerEvents.d.ts +23 -0
- package/dist/markers/utils/MarkerEvents.js +44 -0
- package/dist/markers/utils/MarkerLabel.svelte +33 -0
- package/dist/markers/utils/MarkerLabel.svelte.d.ts +10 -0
- package/dist/markers/utils/PointPixel.d.ts +37 -0
- package/dist/markers/utils/PointPixel.js +44 -0
- package/dist/markers/utils/RowStroke.d.ts +9 -21
- package/dist/markers/utils/RowStroke.js +10 -21
- package/dist/markers/utils/RowStyle.d.ts +26 -0
- package/dist/markers/utils/RowStyle.js +55 -0
- package/dist/markers/vector/VectorMarker.svelte +3 -0
- package/dist/markers/voronoi/VoronoiMarker.svelte +9 -5
- package/dist/markers/voronoi/VoronoiMeshMarker.svelte +3 -0
- package/dist/markers/waffle/WaffleMarker.svelte +9 -5
- package/dist/phases/Pipeline.d.ts +10 -8
- package/dist/phases/Pipeline.js +13 -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 +35 -0
- package/dist/phases/context/RowContext.js +95 -0
- package/dist/phases/data/DataPhase.d.ts +4 -4
- package/dist/phases/data/DataPhase.js +53 -12
- package/dist/phases/hover/HoverPhase.d.ts +6 -7
- package/dist/phases/hover/HoverPhase.js +28 -15
- package/dist/phases/mapping/MappingPhase.d.ts +4 -4
- package/dist/phases/mapping/MappingPhase.js +4 -3
- package/dist/phases/markers/MarkerStyles.d.ts +26 -0
- package/dist/phases/markers/MarkerStyles.js +126 -0
- package/dist/phases/markers/MarkersPhase.d.ts +5 -5
- package/dist/phases/markers/MarkersPhase.js +8 -6
- 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 +0 -16
- package/dist/phases/statistics/StatisticsPhase.js +1 -1
- 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/Transforms.js +3 -1
- package/dist/phases/transforms/TransformsPhase.d.ts +3 -3
- package/dist/phases/transforms/TransformsPhase.js +60 -6
- package/dist/phases/transforms/methods/TreemapTransform.d.ts +28 -0
- package/dist/phases/transforms/methods/TreemapTransform.js +119 -0
- package/dist/plots/correlation/heatmap/defaults.d.ts +2 -2
- package/dist/plots/correlation/heatmap/defaults.js +23 -8
- package/dist/plots/correlation/heatmap/markers.d.ts +2 -10
- package/dist/plots/correlation/heatmap/markers.js +11 -37
- package/dist/plots/correlation/scatter/defaults.d.ts +2 -2
- package/dist/plots/correlation/scatter/defaults.js +9 -3
- package/dist/plots/correlation/scatter/markers.d.ts +3 -3
- package/dist/plots/correlation/scatter/markers.js +6 -5
- package/dist/plots/distribution/box/BoxSummaries.d.ts +17 -8
- package/dist/plots/distribution/box/BoxSummaries.js +90 -40
- package/dist/plots/distribution/box/defaults.d.ts +2 -2
- package/dist/plots/distribution/box/defaults.js +9 -6
- package/dist/plots/distribution/box/markers.d.ts +2 -2
- package/dist/plots/distribution/box/markers.js +3 -3
- package/dist/plots/distribution/density/defaults.d.ts +2 -2
- package/dist/plots/distribution/density/defaults.js +17 -1
- package/dist/plots/distribution/density/markers.d.ts +2 -2
- package/dist/plots/distribution/density/markers.js +4 -4
- package/dist/plots/distribution/histogram/defaults.d.ts +2 -2
- package/dist/plots/distribution/histogram/defaults.js +22 -27
- package/dist/plots/distribution/histogram/markers.d.ts +3 -12
- package/dist/plots/distribution/histogram/markers.js +21 -62
- package/dist/plots/distribution/pyramid/defaults.d.ts +2 -2
- package/dist/plots/distribution/pyramid/defaults.js +7 -4
- package/dist/plots/distribution/pyramid/markers.d.ts +2 -12
- package/dist/plots/distribution/pyramid/markers.js +16 -66
- package/dist/plots/distribution/violin/defaults.d.ts +2 -2
- package/dist/plots/distribution/violin/defaults.js +9 -7
- package/dist/plots/distribution/violin/markers.d.ts +2 -2
- package/dist/plots/distribution/violin/markers.js +4 -4
- package/dist/plots/evolution/area/defaults.d.ts +2 -2
- package/dist/plots/evolution/area/defaults.js +1 -1
- package/dist/plots/evolution/area/markers.d.ts +2 -2
- package/dist/plots/evolution/area/markers.js +4 -4
- package/dist/plots/evolution/line/defaults.d.ts +2 -2
- package/dist/plots/evolution/line/defaults.js +1 -1
- package/dist/plots/evolution/line/markers.d.ts +2 -2
- package/dist/plots/evolution/line/markers.js +3 -3
- package/dist/plots/evolution/slope/defaults.d.ts +2 -2
- package/dist/plots/evolution/slope/defaults.js +8 -4
- package/dist/plots/evolution/slope/markers.d.ts +2 -2
- package/dist/plots/evolution/slope/markers.js +3 -3
- 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 +3 -3
- package/dist/plots/map/geo/Core.svelte +3 -3
- 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 +5 -4
- 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 +47 -0
- package/dist/plots/part-of-a-whole/treemap/Plot.svelte.d.ts +26 -0
- package/dist/plots/part-of-a-whole/treemap/defaults.d.ts +10 -0
- package/dist/plots/part-of-a-whole/treemap/defaults.js +183 -0
- package/dist/plots/ranking/bar/defaults.d.ts +2 -2
- package/dist/plots/ranking/bar/defaults.js +15 -9
- package/dist/plots/ranking/bar/markers.d.ts +4 -14
- package/dist/plots/ranking/bar/markers.js +45 -86
- package/dist/plots/ranking/bullet/defaults.d.ts +2 -2
- package/dist/plots/ranking/bullet/defaults.js +4 -4
- package/dist/plots/ranking/bullet/markers.d.ts +3 -3
- package/dist/plots/ranking/bullet/markers.js +11 -12
- package/dist/plots/ranking/cleveland/ClevelandMarkers.d.ts +3 -3
- package/dist/plots/ranking/cleveland/ClevelandMarkers.js +28 -23
- package/dist/plots/ranking/cleveland/defaults.d.ts +2 -2
- package/dist/plots/ranking/cleveland/defaults.js +7 -4
- package/dist/plots/ranking/dumbbell/defaults.d.ts +2 -2
- package/dist/plots/ranking/forest/defaults.d.ts +2 -2
- package/dist/plots/ranking/lollipop/defaults.d.ts +2 -2
- package/dist/types/configuration/styling.d.ts +31 -2
- package/dist/types/layout/context.d.ts +21 -0
- package/dist/types/layout/context.js +1 -0
- package/dist/types/layout/hover.d.ts +3 -0
- package/dist/types/layout/legend.d.ts +8 -1
- package/dist/types/layout/mapping.d.ts +12 -3
- package/dist/types/layout/scales.d.ts +6 -0
- package/dist/types/layout/styles/values.d.ts +8 -2
- package/dist/types/layout/tooltip.d.ts +11 -4
- package/dist/types/markers/axis/arrow.d.ts +2 -8
- 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 +6 -10
- package/dist/types/markers/axis/cell.d.ts +5 -5
- package/dist/types/markers/axis/delaunayLink.d.ts +2 -2
- package/dist/types/markers/axis/hover.d.ts +60 -15
- package/dist/types/markers/axis/rect.d.ts +4 -8
- package/dist/types/markers/axis/rule.d.ts +2 -16
- package/dist/types/markers/axis/tick.d.ts +2 -2
- package/dist/types/markers/axis/voronoi.d.ts +2 -2
- package/dist/types/markers/axis/waffle.d.ts +4 -3
- package/dist/types/markers/basic/dot.d.ts +2 -2
- package/dist/types/markers/basic/text.d.ts +56 -14
- package/dist/types/markers/channels/commonMarkerConfig.d.ts +8 -1
- package/dist/types/markers/channels/commonMarkerConfigWithArea.d.ts +1 -2
- package/dist/types/markers/channels/commonMarkerConfigWithLabel.d.ts +10 -0
- package/dist/types/markers/channels/commonMarkerConfigWithLabel.js +1 -0
- package/dist/types/markers/channels/commonMarkerEvents.d.ts +17 -0
- package/dist/types/markers/channels/commonMarkerEvents.js +13 -0
- package/dist/types/markers/common.d.ts +1 -0
- package/dist/types/markers/common.js +1 -0
- package/dist/types/markers/geo/contour.d.ts +2 -1
- package/dist/types/markers/geo/graticule.d.ts +2 -1
- package/dist/types/markers/geo/link.d.ts +2 -1
- package/dist/types/markers/geo/sphere.d.ts +2 -1
- package/dist/types/markers/geo/vector.d.ts +2 -1
- 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 +7 -2
- package/dist/types/phases/hover/phase.d.ts +10 -5
- 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 -3
- 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 +8 -1
- package/dist/types/phases/statistics/phase.d.ts +2 -1
- package/dist/types/phases/styles/phase.d.ts +3 -2
- package/dist/types/phases/transforms/phase.d.ts +13 -2
- package/dist/types/plots/constants.d.ts +17 -19
- package/dist/types/plots/correlation/heatmap/props.d.ts +3 -3
- package/dist/types/plots/correlation/heatmap/state.d.ts +2 -2
- package/dist/types/plots/correlation/scatter/props.d.ts +3 -3
- package/dist/types/plots/correlation/scatter/state.d.ts +2 -2
- package/dist/types/plots/data/common.d.ts +19 -6
- package/dist/types/plots/data/geo.d.ts +1 -1
- package/dist/types/plots/distribution/box/props.d.ts +25 -3
- package/dist/types/plots/distribution/box/state.d.ts +6 -17
- package/dist/types/plots/distribution/density/props.d.ts +3 -11
- package/dist/types/plots/distribution/density/state.d.ts +2 -2
- package/dist/types/plots/distribution/histogram/props.d.ts +16 -11
- package/dist/types/plots/distribution/histogram/state.d.ts +2 -2
- package/dist/types/plots/distribution/pyramid/props.d.ts +3 -3
- package/dist/types/plots/distribution/pyramid/state.d.ts +2 -2
- package/dist/types/plots/distribution/violin/props.d.ts +4 -3
- package/dist/types/plots/distribution/violin/state.d.ts +2 -2
- package/dist/types/plots/evolution/area/props.d.ts +3 -3
- package/dist/types/plots/evolution/area/state.d.ts +2 -2
- package/dist/types/plots/evolution/line/props.d.ts +3 -3
- 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/map/geo/state.d.ts +1 -1
- package/dist/types/plots/part-of-a-whole/treemap/props.d.ts +29 -0
- package/dist/types/plots/part-of-a-whole/treemap/props.js +1 -0
- package/dist/types/plots/part-of-a-whole/treemap/state.d.ts +6 -0
- package/dist/types/plots/part-of-a-whole/treemap/state.js +1 -0
- package/dist/types/plots/props.d.ts +10 -4
- package/dist/types/plots/ranking/bar/props.d.ts +3 -3
- 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 -3
- package/dist/types/plots/ranking/cleveland/state.d.ts +2 -2
- package/dist/types/plots/ranking/dumbbell/props.d.ts +3 -3
- package/dist/types/plots/ranking/dumbbell/state.d.ts +2 -2
- package/dist/types/plots/ranking/forest/props.d.ts +3 -3
- package/dist/types/plots/ranking/forest/state.d.ts +2 -2
- package/dist/types/plots/ranking/lollipop/props.d.ts +3 -3
- package/dist/types/plots/ranking/lollipop/state.d.ts +2 -2
- package/dist/types/plots/styling.d.ts +24 -0
- package/dist/types/transforms/index.d.ts +3 -1
- package/dist/types/transforms/treemap.d.ts +32 -0
- package/dist/types/transforms/treemap.js +5 -0
- package/dist/utils/color/ColorTones.d.ts +19 -0
- package/dist/utils/color/ColorTones.js +64 -0
- package/dist/utils/color/CssColor.d.ts +14 -5
- package/dist/utils/color/CssColor.js +69 -27
- package/dist/utils/color/index.d.ts +4 -0
- package/dist/utils/color/index.js +4 -0
- package/dist/utils/grouping.d.ts +18 -1
- package/dist/utils/grouping.js +31 -0
- package/docs/concepts.md +3 -2
- package/docs/legend.md +8 -5
- package/docs/markers.md +110 -28
- 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 +103 -0
- package/docs/plots/ranking/bar.md +2 -1
- package/docs/plots/ranking/cleveland.md +1 -1
- package/docs/plots.md +21 -20
- package/docs/scales.md +3 -0
- package/docs/state.md +34 -1
- package/docs/styles-and-segments.md +20 -19
- package/docs/theming.md +6 -12
- package/docs/tooltip-and-hover.md +81 -3
- package/docs/transforms-and-statistics.md +17 -16
- package/examples/LineDates.svelte +1 -1
- package/examples/ResponsiveLine.svelte +3 -1
- package/examples/Treemap.svelte +13 -0
- package/examples/TreemapHover.svelte +25 -0
- package/examples/ValueLabels.svelte +1 -1
- package/examples/datasets/economic-activity.ts +40 -0
- package/examples/datasets/index.ts +1 -0
- package/llms-full.txt +11 -9
- package/llms.txt +4 -1
- package/package.json +3 -1
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
import DotMarker from '../../markers/dot/DotMarker.svelte';
|
|
29
29
|
import TextMarker from '../../markers/text/TextMarker.svelte';
|
|
30
30
|
import RuleMarker from '../../markers/rule/RuleMarker.svelte';
|
|
31
|
+
import BandMarker from '../../markers/band/BandMarker.svelte';
|
|
31
32
|
import HoverMarker from '../../markers/hover/HoverMarker.svelte';
|
|
32
33
|
import GeoHoverMarker from '../../markers/geo/GeoHoverMarker.svelte';
|
|
33
34
|
import DeltaMarker from '../../markers/delta/DeltaMarker.svelte';
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
import ContourMarker from '../../markers/contour/ContourMarker.svelte';
|
|
40
41
|
import ContourClipMarker from '../../markers/contour/ContourClipMarker.svelte';
|
|
41
42
|
import InsetMarker from '../../markers/inset/InsetMarker.svelte';
|
|
43
|
+
import MarkerLabel from '../../markers/utils/MarkerLabel.svelte';
|
|
42
44
|
import FrameClip from './FrameClip.svelte';
|
|
43
45
|
import MarkerOffset from './MarkerOffset.svelte';
|
|
44
46
|
import { getConfiguration } from '../../configuration/config.svelte';
|
|
@@ -46,12 +48,21 @@
|
|
|
46
48
|
import { PlotMargins } from '../margins/PlotMargins.svelte';
|
|
47
49
|
import type { Series } from '../../types/plots/data/common';
|
|
48
50
|
import type { MarkerConfig } from '../../types/markers/all';
|
|
51
|
+
import type { CommonMarkerEvents } from '../../types/markers/channels/commonMarkerEvents';
|
|
49
52
|
import type { TooltipAnchorX, TooltipAnchorY } from '../../types/layout/tooltip';
|
|
50
53
|
import type { PlotHover } from '../hover/PlotHover.svelte';
|
|
51
54
|
import type { ScopedMarkerGroup } from '../../types/layout/geometry';
|
|
52
55
|
import type { GeoFeature } from '../../types/plots/data/geo';
|
|
53
56
|
import { MarkerGrouping } from '../../phases/statistics/MarkerGrouping';
|
|
54
57
|
import { FrameClipping } from './FrameClipping';
|
|
58
|
+
import { HoverShapes, type HoverShapesReach } from '../hover/HoverShapes';
|
|
59
|
+
import { PlotInteraction } from '../interaction/PlotInteraction.svelte';
|
|
60
|
+
import { SERIES_KEY } from '../../phases/transforms/TransformsPhase';
|
|
61
|
+
import { HoverLayers, type HoverPointGroup } from '../hover/HoverLayers';
|
|
62
|
+
import { BandNudge } from '../../markers/utils/BandNudge';
|
|
63
|
+
import { PointPixel } from '../../markers/utils/PointPixel';
|
|
64
|
+
import { HoverDefaults } from '../hover/HoverDefaults';
|
|
65
|
+
import type { HoverMarkerConfig } from '../../types/markers/common';
|
|
55
66
|
|
|
56
67
|
/**
|
|
57
68
|
* Renders every marker in `markers`, in array order, each delegated to the
|
|
@@ -105,9 +116,137 @@
|
|
|
105
116
|
} = $props();
|
|
106
117
|
|
|
107
118
|
const cfg = $derived(getConfiguration());
|
|
119
|
+
const interaction = PlotInteraction.current(() => cfg);
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The markers, each `hover` one laid over the plot kind's own hover under the strategy in force - read as they
|
|
123
|
+
* are drawn, so a strategy changed while the plot is shown changes what the hover draws.
|
|
124
|
+
*/
|
|
125
|
+
const drawn = $derived.by(() => {
|
|
126
|
+
const look = ctrl.look;
|
|
127
|
+
return markers.map((marker) =>
|
|
128
|
+
marker.type === 'hover'
|
|
129
|
+
? (HoverDefaults.merge(look, marker as HoverMarkerConfig) as MarkerConfig)
|
|
130
|
+
: marker
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
/** The look the hover markers give the shapes linked to the hover. */
|
|
135
|
+
const shapes = $derived(new HoverShapes(drawn));
|
|
136
|
+
const reach: HoverShapesReach = {
|
|
137
|
+
roleOf: (row, series) => ctrl.roleOf(row as TData, series),
|
|
138
|
+
dimmed: (row) => {
|
|
139
|
+
const series = row[SERIES_KEY];
|
|
140
|
+
return typeof series === 'string' && interaction.fillFor(series) !== undefined;
|
|
141
|
+
},
|
|
142
|
+
get cfg() {
|
|
143
|
+
return cfg;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
108
146
|
|
|
109
147
|
// Mounted inside svelteplot's `<Plot>`, the one place the margins it settles on can be read.
|
|
110
|
-
|
|
148
|
+
const svelteplot = usePlot().svelteplot;
|
|
149
|
+
PlotMargins.current()?.follow(svelteplot);
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The points a hover marker draws over: every matched one; with `series`, that series' only, in its color -
|
|
153
|
+
* or with `scope: 'segment'`, each segment's, in the segment's. The first is the active one of a series.
|
|
154
|
+
*/
|
|
155
|
+
function hoverGroupsOf(marker: HoverMarkerConfig): HoverPointGroup[] {
|
|
156
|
+
const points = ctrl.points;
|
|
157
|
+
if (points.length === 0) return [];
|
|
158
|
+
const nearest = JSON.parse(nearestKey || '{}') as {
|
|
159
|
+
all?: number;
|
|
160
|
+
bySeries?: Record<string, number>;
|
|
161
|
+
};
|
|
162
|
+
const scope = marker.series;
|
|
163
|
+
if (!scope) {
|
|
164
|
+
const active = nearest.all !== undefined ? points[nearest.all] : undefined;
|
|
165
|
+
return [{ key: '', points, active: active ?? ctrl.activePoint }];
|
|
166
|
+
}
|
|
167
|
+
const under = nearest.bySeries?.[scope];
|
|
168
|
+
const activeOf = (list: typeof points) =>
|
|
169
|
+
(under !== undefined && list.find((p) => p.row === points[under].row)) || list[0] || null;
|
|
170
|
+
const group = groupByName.get(scope);
|
|
171
|
+
if (!group) return [];
|
|
172
|
+
const own = points.filter((p) => p.series === scope);
|
|
173
|
+
const colored = (list: typeof own, color: string | undefined) =>
|
|
174
|
+
color ? list.map((p) => ({ ...p, color })) : list;
|
|
175
|
+
if (marker.scope !== 'segment') {
|
|
176
|
+
const seriesPoints = colored(own, group.segments[0]?.color ?? group.color);
|
|
177
|
+
return [{ key: scope, points: seriesPoints, active: activeOf(seriesPoints) }];
|
|
178
|
+
}
|
|
179
|
+
return group.segments.map((seg, i) => {
|
|
180
|
+
// p.row (TData) is always a superset of TSeries in practice, not provable across two independent generics.
|
|
181
|
+
const segPoints = colored(
|
|
182
|
+
own.filter((p) => seg.match(p.row as unknown as TSeries)),
|
|
183
|
+
seg.color
|
|
184
|
+
);
|
|
185
|
+
return { key: `${scope}-${i}`, points: segPoints, active: activeOf(segPoints) };
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The hovered point under the pointer: of all of them, and of each series - the nearest to the pointer, not the
|
|
191
|
+
* first the strategy matched, so a crosshair at it follows the pointer across the series of a category. Kept as
|
|
192
|
+
* text, so the hover's markers are built again only when it changes, not at every move of the pointer.
|
|
193
|
+
*/
|
|
194
|
+
const nearestKey = $derived.by(() => {
|
|
195
|
+
const cursor = ctrl.cursor;
|
|
196
|
+
const points = ctrl.points;
|
|
197
|
+
if (!cursor || points.length === 0) return '';
|
|
198
|
+
const all = PointPixel.nearest(svelteplot.scales, points, cursor);
|
|
199
|
+
const bySeries: Record<string, number> = {};
|
|
200
|
+
for (const series of new Set(points.map((p) => p.series))) {
|
|
201
|
+
if (series == null) continue;
|
|
202
|
+
const indexes = points.flatMap((p, i) => (p.series === series ? [i] : []));
|
|
203
|
+
const nearest = PointPixel.nearest(
|
|
204
|
+
svelteplot.scales,
|
|
205
|
+
indexes.map((i) => points[i]),
|
|
206
|
+
cursor
|
|
207
|
+
);
|
|
208
|
+
if (nearest >= 0) bySeries[series] = indexes[nearest];
|
|
209
|
+
}
|
|
210
|
+
return JSON.stringify({ all: all >= 0 ? all : undefined, bySeries });
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
/** The markers `marker`'s `layer` draws, over each group of the points it draws over. */
|
|
214
|
+
function hoverPartsOf(marker: HoverMarkerConfig, layer: 'back' | 'front', index: number) {
|
|
215
|
+
return hoverGroupsOf(marker).flatMap((group) =>
|
|
216
|
+
HoverLayers.parts(
|
|
217
|
+
marker,
|
|
218
|
+
layer,
|
|
219
|
+
{
|
|
220
|
+
...group,
|
|
221
|
+
points: HoverLayers.labelled(group.points, marker, cfg),
|
|
222
|
+
active: group.active && HoverLayers.labelled([group.active], marker, cfg)[0]
|
|
223
|
+
},
|
|
224
|
+
cfg
|
|
225
|
+
).map((part) => ({ ...part, key: `${index}-${part.key}` }))
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* What each hover marker draws, behind and in front, built once per hover - not as it is drawn, where reading
|
|
231
|
+
* the scales would build its markers anew whenever svelteplot settles them, and settle them again.
|
|
232
|
+
*/
|
|
233
|
+
const hoverLayers = $derived(
|
|
234
|
+
new Map(
|
|
235
|
+
drawn.flatMap((marker, index) =>
|
|
236
|
+
marker.type === 'hover'
|
|
237
|
+
? [
|
|
238
|
+
[
|
|
239
|
+
index,
|
|
240
|
+
{
|
|
241
|
+
back: hoverPartsOf(marker as HoverMarkerConfig, 'back', index),
|
|
242
|
+
front: hoverPartsOf(marker as HoverMarkerConfig, 'front', index)
|
|
243
|
+
}
|
|
244
|
+
] as const
|
|
245
|
+
]
|
|
246
|
+
: []
|
|
247
|
+
)
|
|
248
|
+
)
|
|
249
|
+
);
|
|
111
250
|
|
|
112
251
|
const scopedSeriesOf = (marker: MarkerConfig): string | undefined =>
|
|
113
252
|
'series' in marker && typeof marker.series === 'string' && marker.series
|
|
@@ -127,6 +266,33 @@
|
|
|
127
266
|
if (marker.type === 'bar') return `bar-${marker.role}-${i}`;
|
|
128
267
|
return `${marker.type}-${i}`;
|
|
129
268
|
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* A marker with `hover: true` or `'trigger'`, with the plot's hover added to its own pointer handlers: entering or
|
|
272
|
+
* moving over one of its shapes hovers that shape's row, and leaving it ends the hover.
|
|
273
|
+
*/
|
|
274
|
+
function withHover(marker: MarkerConfig, rows: TData[] | TSeries[]): MarkerConfig {
|
|
275
|
+
if (!('hover' in marker) || (marker.hover !== true && marker.hover !== 'trigger'))
|
|
276
|
+
return marker;
|
|
277
|
+
const own = marker as CommonMarkerEvents & { data?: unknown[] };
|
|
278
|
+
// The row of the shape under the pointer - a copy svelteplot hands over, which the hover finds by its place.
|
|
279
|
+
const hovered = (row: unknown) => [(row ?? (own.data ?? rows)[0]) as TData];
|
|
280
|
+
return {
|
|
281
|
+
...marker,
|
|
282
|
+
onpointerenter: (event: Event, row: unknown, index: number) => {
|
|
283
|
+
own.onpointerenter?.(event, row, index);
|
|
284
|
+
ctrl.onPointer(hovered(row));
|
|
285
|
+
},
|
|
286
|
+
onpointerleave: (event: Event, row: unknown, index: number) => {
|
|
287
|
+
own.onpointerleave?.(event, row, index);
|
|
288
|
+
ctrl.onLeave();
|
|
289
|
+
},
|
|
290
|
+
onpointermove: (event: Event, row: unknown, index: number) => {
|
|
291
|
+
own.onpointermove?.(event, row, index);
|
|
292
|
+
ctrl.onPointer(hovered(row));
|
|
293
|
+
}
|
|
294
|
+
} as MarkerConfig;
|
|
295
|
+
}
|
|
130
296
|
</script>
|
|
131
297
|
|
|
132
298
|
{#snippet drawMarker(marker: MarkerConfig, rows: TData[] | TSeries[])}
|
|
@@ -182,6 +348,8 @@
|
|
|
182
348
|
<TextMarker marker={{ ...marker, data: marker.data ?? rows }} />
|
|
183
349
|
{:else if marker.type === 'rule'}
|
|
184
350
|
<RuleMarker {marker} />
|
|
351
|
+
{:else if marker.type === 'band'}
|
|
352
|
+
<BandMarker {marker} />
|
|
185
353
|
{:else if marker.type === 'geo'}
|
|
186
354
|
<GeoFeaturesMarker {marker} />
|
|
187
355
|
{:else if marker.type === 'graticule'}
|
|
@@ -219,15 +387,6 @@
|
|
|
219
387
|
<marker.component {...marker.props} data={marker.data ?? seriesData} />
|
|
220
388
|
{:else if marker.type === 'geo-component'}
|
|
221
389
|
<marker.component {...marker.props} data={marker.data ?? rows} />
|
|
222
|
-
{:else if marker.type === 'hover'}
|
|
223
|
-
<HoverMarker
|
|
224
|
-
{marker}
|
|
225
|
-
data={ctrl.points}
|
|
226
|
-
activePoint={ctrl.activePoint}
|
|
227
|
-
impliesCrosshairX={ctrl.impliesCrosshairX}
|
|
228
|
-
impliesCrosshairY={ctrl.impliesCrosshairY}
|
|
229
|
-
onActivePointPixel={ctrl.reportActivePointPixel}
|
|
230
|
-
/>
|
|
231
390
|
{:else if marker.type === 'geo-hover'}
|
|
232
391
|
<GeoHoverMarker {marker} data={ctrl.points} />
|
|
233
392
|
{:else if marker.type === 'delta'}
|
|
@@ -236,41 +395,16 @@
|
|
|
236
395
|
{/snippet}
|
|
237
396
|
|
|
238
397
|
{#snippet renderMarker(marker: MarkerConfig, rows: TData[] | TSeries[])}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
398
|
+
<!-- In parts the hover styles alike, while it restyles the marker's shapes. -->
|
|
399
|
+
{#each shapes.split(withHover(marker, rows), rows, reach) as part (part.key)}
|
|
400
|
+
<MarkerOffset marker={part.marker}>
|
|
401
|
+
{@render drawMarker(part.marker, rows)}
|
|
402
|
+
</MarkerOffset>
|
|
403
|
+
{/each}
|
|
242
404
|
{/snippet}
|
|
243
405
|
|
|
244
406
|
{#snippet renderScoped(marker: MarkerConfig, group: ScopedMarkerGroup<TSeries>)}
|
|
245
|
-
{#if marker.type === '
|
|
246
|
-
{@const seriesPoints = ctrl.points.filter((p) => p.series === group.name)}
|
|
247
|
-
{#if marker.scope === 'segment'}
|
|
248
|
-
{#each group.segments as seg, segIdx (`${group.name}-hover-segment-${segIdx}`)}
|
|
249
|
-
<!-- p.row (TData) is always a superset of TSeries in practice, not provable across two independent generics. -->
|
|
250
|
-
{@const segPoints = seriesPoints.filter((p) => seg.match(p.row as unknown as TSeries))}
|
|
251
|
-
{#if segPoints.length > 0}
|
|
252
|
-
<HoverMarker
|
|
253
|
-
marker={MarkerGrouping.withHoverSeriesColor(marker, seg.color)}
|
|
254
|
-
data={segPoints}
|
|
255
|
-
activePoint={segPoints[0] ?? null}
|
|
256
|
-
impliesCrosshairX={ctrl.impliesCrosshairX}
|
|
257
|
-
impliesCrosshairY={ctrl.impliesCrosshairY}
|
|
258
|
-
/>
|
|
259
|
-
{/if}
|
|
260
|
-
{/each}
|
|
261
|
-
{:else}
|
|
262
|
-
<HoverMarker
|
|
263
|
-
marker={MarkerGrouping.withHoverSeriesColor(
|
|
264
|
-
marker,
|
|
265
|
-
group.segments[0]?.color ?? group.color
|
|
266
|
-
)}
|
|
267
|
-
data={seriesPoints}
|
|
268
|
-
activePoint={seriesPoints[0] ?? null}
|
|
269
|
-
impliesCrosshairX={ctrl.impliesCrosshairX}
|
|
270
|
-
impliesCrosshairY={ctrl.impliesCrosshairY}
|
|
271
|
-
/>
|
|
272
|
-
{/if}
|
|
273
|
-
{:else if marker.type === 'component'}
|
|
407
|
+
{#if marker.type === 'component'}
|
|
274
408
|
{#if marker.scope === 'segment'}
|
|
275
409
|
{#each group.segments as seg, segIdx (`${group.name}-component-segment-${segIdx}`)}
|
|
276
410
|
{@const segmentData = group.data.filter((row) => seg.match(row))}
|
|
@@ -288,10 +422,35 @@
|
|
|
288
422
|
{/if}
|
|
289
423
|
{/snippet}
|
|
290
424
|
|
|
291
|
-
|
|
425
|
+
{#snippet renderHoverLayer(index: number, layer: 'back' | 'front')}
|
|
426
|
+
{#each hoverLayers.get(index)?.[layer] ?? [] as part (part.key)}
|
|
427
|
+
<!-- A point in a slice of its band (a grouped bar's series) is drawn in the middle of it. -->
|
|
428
|
+
{@const nudge = BandNudge.of(svelteplot.scales, part.slice)}
|
|
429
|
+
<g transform="translate({nudge.dx}, {nudge.dy})">
|
|
430
|
+
<FrameClip clip={FrameClipping.isClipped(part.marker)}>
|
|
431
|
+
{@render renderMarker(part.marker as MarkerConfig, data)}
|
|
432
|
+
</FrameClip>
|
|
433
|
+
</g>
|
|
434
|
+
{/each}
|
|
435
|
+
{/snippet}
|
|
436
|
+
|
|
437
|
+
<!-- What the hover draws behind the plot's shapes, before any of them. -->
|
|
438
|
+
{#each [...hoverLayers.keys()] as index (index)}
|
|
439
|
+
{@render renderHoverLayer(index, 'back')}
|
|
440
|
+
{/each}
|
|
441
|
+
|
|
442
|
+
<!-- Every marker in array order, so a later one always draws on top; a hover marker draws its front markers. -->
|
|
292
443
|
{#each markers as marker, i (markerKey(marker, i))}
|
|
293
444
|
{@const scope = scopedSeriesOf(marker)}
|
|
294
|
-
{#if
|
|
445
|
+
{#if marker.type === 'hover'}
|
|
446
|
+
{#if scope === undefined}
|
|
447
|
+
<HoverMarker
|
|
448
|
+
activePoint={ctrl.activePoint}
|
|
449
|
+
onActivePointPixel={ctrl.reportActivePointPixel}
|
|
450
|
+
/>
|
|
451
|
+
{/if}
|
|
452
|
+
{@render renderHoverLayer(i, 'front')}
|
|
453
|
+
{:else if scope === undefined}
|
|
295
454
|
<FrameClip clip={FrameClipping.isClipped(marker)}>
|
|
296
455
|
{@render renderMarker(marker, data)}
|
|
297
456
|
</FrameClip>
|
|
@@ -299,3 +458,19 @@
|
|
|
299
458
|
{@render renderScoped(marker, groupByName.get(scope)!)}
|
|
300
459
|
{/if}
|
|
301
460
|
{/each}
|
|
461
|
+
|
|
462
|
+
<!--
|
|
463
|
+
The labels the shapes write in themselves, after every marker - the hover's hit areas too, which are the last of them -
|
|
464
|
+
so a label that listens for the pointer is not covered, and one outside its shape is not clipped with it.
|
|
465
|
+
-->
|
|
466
|
+
{#each markers as marker, i (markerKey(marker, i))}
|
|
467
|
+
{@const scope = scopedSeriesOf(marker)}
|
|
468
|
+
{#if 'label' in marker && marker.label && (scope === undefined || groupByName.has(scope))}
|
|
469
|
+
<!-- Split as the shapes are, so a label reads on its shape's color under the hover. -->
|
|
470
|
+
{#each shapes.split(marker, data, reach) as part (part.key)}
|
|
471
|
+
<MarkerOffset marker={part.marker}>
|
|
472
|
+
<MarkerLabel marker={{ ...part.marker, data: part.marker.data ?? data }} />
|
|
473
|
+
</MarkerOffset>
|
|
474
|
+
{/each}
|
|
475
|
+
{/if}
|
|
476
|
+
{/each}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { HoverDisplayPoint, HoverStrategy } from '../../types/layout/hover';
|
|
2
|
+
import type { HoverLayerMarker, HoverLook, HoverMarkerConfig } from '../../types/markers/common';
|
|
3
|
+
import type { PlotStylesConfig } from '../../types/configuration/styling';
|
|
4
|
+
/** An end of a span: a field of the hovered point's context (else of its row), or a function of the point. */
|
|
5
|
+
type SpanEnd = string | ((point: HoverDisplayPoint) => unknown);
|
|
6
|
+
/**
|
|
7
|
+
* The hover a plot kind draws, and how an author's `hover` marker is laid over it. Its parts - a crosshair rule, a
|
|
8
|
+
* band, a dot, a label - are the markers a kind composes its own hover from; each takes the configuration's
|
|
9
|
+
* `hover` look as it is drawn (see `HoverLayers`).
|
|
10
|
+
*/
|
|
11
|
+
export declare class HoverDefaults {
|
|
12
|
+
/** A crosshair along `axis`, at the point under the pointer. */
|
|
13
|
+
static rule(axis: 'x' | 'y'): HoverLayerMarker;
|
|
14
|
+
/** The band of each hovered category along `axis`, or its series' slice of it when it alone is hovered there. */
|
|
15
|
+
static band(axis: 'x' | 'y'): HoverLayerMarker;
|
|
16
|
+
/**
|
|
17
|
+
* The span of the point under the pointer along `axis`, from `from` to `to`, across the whole of the other axis -
|
|
18
|
+
* where a band is no category's: a histogram's bin, an interval on a continuous axis. Each end is a field of the
|
|
19
|
+
* point's context (a bin's `from` and `to`) - else of its row - or a function of the point.
|
|
20
|
+
*/
|
|
21
|
+
static span(axis: 'x' | 'y', from: SpanEnd, to: SpanEnd): HoverLayerMarker;
|
|
22
|
+
/** A dot on each hovered point, in its series' color. */
|
|
23
|
+
static dot(): HoverLayerMarker;
|
|
24
|
+
/** Each hovered point's label, in its series' color. */
|
|
25
|
+
static text(): HoverLayerMarker;
|
|
26
|
+
/**
|
|
27
|
+
* A hover that only restyles the shapes, with `active` and `others`: a treemap's tiles, a heatmap's cells. The
|
|
28
|
+
* hovered one is outlined, in the configuration's `hover.active`.
|
|
29
|
+
*/
|
|
30
|
+
static shapes(cfg: PlotStylesConfig): HoverLook;
|
|
31
|
+
/** The hovered category's band along `axis`, behind the plot's shapes: a bar's, a box's, a violin's. */
|
|
32
|
+
static behindBand(axis: 'x' | 'y'): HoverLook;
|
|
33
|
+
/** The span of the point under the pointer along `axis`, behind the plot's shapes: a histogram's bin. */
|
|
34
|
+
static behindSpan(axis: 'x' | 'y', from: SpanEnd, to: SpanEnd): HoverLook;
|
|
35
|
+
/**
|
|
36
|
+
* A rule along the value axis at the point under the pointer, and a dot and a label on each point - for a plot
|
|
37
|
+
* whose other axis holds a few positions or categories, where a crosshair along it says little (a slope's, a
|
|
38
|
+
* Cleveland plot's).
|
|
39
|
+
*/
|
|
40
|
+
static valueRule(valueAxis: 'x' | 'y'): HoverLook;
|
|
41
|
+
/**
|
|
42
|
+
* The hover every plot kind starts from: a crosshair along each axis its `strategy` matches along (unless
|
|
43
|
+
* `crosshair` is off), and a dot and a label on each hovered point.
|
|
44
|
+
*/
|
|
45
|
+
static of(strategy: HoverStrategy, crosshair?: boolean | undefined): HoverLook;
|
|
46
|
+
/**
|
|
47
|
+
* An author's `hover` marker over its kind's `look`: `active` and `others` field by field, `back` and `front`
|
|
48
|
+
* the author's when set (an empty list draws nothing), the kind's otherwise.
|
|
49
|
+
*/
|
|
50
|
+
static merge(look: HoverLook, marker: HoverMarkerConfig): HoverMarkerConfig;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The hover a plot kind draws, and how an author's `hover` marker is laid over it. Its parts - a crosshair rule, a
|
|
3
|
+
* band, a dot, a label - are the markers a kind composes its own hover from; each takes the configuration's
|
|
4
|
+
* `hover` look as it is drawn (see `HoverLayers`).
|
|
5
|
+
*/
|
|
6
|
+
export class HoverDefaults {
|
|
7
|
+
/** A crosshair along `axis`, at the point under the pointer. */
|
|
8
|
+
static rule(axis) {
|
|
9
|
+
return { type: 'rule', axis, points: 'active' };
|
|
10
|
+
}
|
|
11
|
+
/** The band of each hovered category along `axis`, or its series' slice of it when it alone is hovered there. */
|
|
12
|
+
static band(axis) {
|
|
13
|
+
return { type: 'band', axis };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The span of the point under the pointer along `axis`, from `from` to `to`, across the whole of the other axis -
|
|
17
|
+
* where a band is no category's: a histogram's bin, an interval on a continuous axis. Each end is a field of the
|
|
18
|
+
* point's context (a bin's `from` and `to`) - else of its row - or a function of the point.
|
|
19
|
+
*/
|
|
20
|
+
static span(axis, from, to) {
|
|
21
|
+
const end = (side) => typeof side === 'function'
|
|
22
|
+
? side
|
|
23
|
+
: (point) => point.context?.[side] ?? point.row?.[side];
|
|
24
|
+
return {
|
|
25
|
+
type: 'rect',
|
|
26
|
+
[`${axis}1`]: end(from),
|
|
27
|
+
[`${axis}2`]: end(to),
|
|
28
|
+
points: 'active'
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** A dot on each hovered point, in its series' color. */
|
|
32
|
+
static dot() {
|
|
33
|
+
return { type: 'dot' };
|
|
34
|
+
}
|
|
35
|
+
/** Each hovered point's label, in its series' color. */
|
|
36
|
+
static text() {
|
|
37
|
+
return { type: 'text' };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A hover that only restyles the shapes, with `active` and `others`: a treemap's tiles, a heatmap's cells. The
|
|
41
|
+
* hovered one is outlined, in the configuration's `hover.active`.
|
|
42
|
+
*/
|
|
43
|
+
static shapes(cfg) {
|
|
44
|
+
return { back: [], front: [], active: { ...cfg.hover.active } };
|
|
45
|
+
}
|
|
46
|
+
/** The hovered category's band along `axis`, behind the plot's shapes: a bar's, a box's, a violin's. */
|
|
47
|
+
static behindBand(axis) {
|
|
48
|
+
return { back: [HoverDefaults.band(axis)], front: [] };
|
|
49
|
+
}
|
|
50
|
+
/** The span of the point under the pointer along `axis`, behind the plot's shapes: a histogram's bin. */
|
|
51
|
+
static behindSpan(axis, from, to) {
|
|
52
|
+
return { back: [HoverDefaults.span(axis, from, to)], front: [] };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A rule along the value axis at the point under the pointer, and a dot and a label on each point - for a plot
|
|
56
|
+
* whose other axis holds a few positions or categories, where a crosshair along it says little (a slope's, a
|
|
57
|
+
* Cleveland plot's).
|
|
58
|
+
*/
|
|
59
|
+
static valueRule(valueAxis) {
|
|
60
|
+
return {
|
|
61
|
+
back: [HoverDefaults.rule(valueAxis)],
|
|
62
|
+
front: [HoverDefaults.dot(), HoverDefaults.text()]
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The hover every plot kind starts from: a crosshair along each axis its `strategy` matches along (unless
|
|
67
|
+
* `crosshair` is off), and a dot and a label on each hovered point.
|
|
68
|
+
*/
|
|
69
|
+
static of(strategy, crosshair = true) {
|
|
70
|
+
const axes = strategy === 'x'
|
|
71
|
+
? ['x']
|
|
72
|
+
: strategy === 'y'
|
|
73
|
+
? ['y']
|
|
74
|
+
: strategy === 'punctual'
|
|
75
|
+
? ['x', 'y']
|
|
76
|
+
: [];
|
|
77
|
+
return {
|
|
78
|
+
back: crosshair === false ? [] : axes.map((axis) => HoverDefaults.rule(axis)),
|
|
79
|
+
front: [HoverDefaults.dot(), HoverDefaults.text()]
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* An author's `hover` marker over its kind's `look`: `active` and `others` field by field, `back` and `front`
|
|
84
|
+
* the author's when set (an empty list draws nothing), the kind's otherwise.
|
|
85
|
+
*/
|
|
86
|
+
static merge(look, marker) {
|
|
87
|
+
const styles = (own, base) => own || base ? { ...base, ...own } : undefined;
|
|
88
|
+
return {
|
|
89
|
+
...marker,
|
|
90
|
+
active: styles(marker.active, look.active),
|
|
91
|
+
others: styles(marker.others, look.others),
|
|
92
|
+
back: marker.back ?? look.back ?? [],
|
|
93
|
+
front: marker.front ?? look.front ?? []
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { BandSlice, HoverDisplayPoint } from '../../types/layout/hover';
|
|
2
|
+
import type { HoverLayerMarker, HoverMarkerConfig } from '../../types/markers/common';
|
|
3
|
+
import type { PlotStylesConfig } from '../../types/configuration/styling';
|
|
4
|
+
type Point = HoverDisplayPoint & {
|
|
5
|
+
row?: unknown;
|
|
6
|
+
};
|
|
7
|
+
/** One marker a hover layer draws, keyed so it keeps its place while the hover moves, and the slice it is moved into. */
|
|
8
|
+
export type HoverLayerPart = {
|
|
9
|
+
key: string;
|
|
10
|
+
marker: HoverLayerMarker;
|
|
11
|
+
slice?: BandSlice;
|
|
12
|
+
};
|
|
13
|
+
/** Some hovered points: of the whole plot, of one series, or of one segment of it, with the one under the pointer. */
|
|
14
|
+
export type HoverPointGroup = {
|
|
15
|
+
key: string;
|
|
16
|
+
points: Point[];
|
|
17
|
+
active: Point | null;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* The markers a `hover` marker draws in its `back` and `front` layers, over the hovered points: each with the
|
|
21
|
+
* points as its rows, unless it has `data` of its own, placed at them, and split by the slice of the band a point
|
|
22
|
+
* sits in (a grouped bar's series), to be moved into it - all but a `band`, which takes the slice itself.
|
|
23
|
+
*/
|
|
24
|
+
export declare class HoverLayers {
|
|
25
|
+
#private;
|
|
26
|
+
/** `points` with their label written as `marker`'s number fields, or its `format`, ask. */
|
|
27
|
+
static labelled<T extends Point>(points: readonly T[], marker: HoverMarkerConfig, cfg: PlotStylesConfig): T[];
|
|
28
|
+
/**
|
|
29
|
+
* The markers of `marker`'s `layer` over a group of points. A marker over points that sit in a slice of their
|
|
30
|
+
* band is one part per slice, which `slice` names, to be moved into it as it is drawn - the move is in pixels,
|
|
31
|
+
* so it is left to the drawing, which knows the band's width.
|
|
32
|
+
*/
|
|
33
|
+
static parts(marker: HoverMarkerConfig, layer: 'back' | 'front', group: HoverPointGroup, cfg: PlotStylesConfig): HoverLayerPart[];
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { NumberFormat } from '../../utils/NumberFormat';
|
|
2
|
+
/**
|
|
3
|
+
* The markers a `hover` marker draws in its `back` and `front` layers, over the hovered points: each with the
|
|
4
|
+
* points as its rows, unless it has `data` of its own, placed at them, and split by the slice of the band a point
|
|
5
|
+
* sits in (a grouped bar's series), to be moved into it - all but a `band`, which takes the slice itself.
|
|
6
|
+
*/
|
|
7
|
+
export class HoverLayers {
|
|
8
|
+
/** The kinds placed by `x` and `y`, which default to the point's. */
|
|
9
|
+
static #PLACED = new Set(['dot', 'text', 'tick', 'image', 'line', 'trail']);
|
|
10
|
+
/** `points` with their label written as `marker`'s number fields, or its `format`, ask. */
|
|
11
|
+
static labelled(points, marker, cfg) {
|
|
12
|
+
const numberOf = NumberFormat.maybe(NumberFormat.displayOf(marker), cfg);
|
|
13
|
+
const number = numberOf ?? NumberFormat.of(undefined, cfg);
|
|
14
|
+
const { format } = marker;
|
|
15
|
+
if (!format && !numberOf)
|
|
16
|
+
return [...points];
|
|
17
|
+
return points.map((point) => {
|
|
18
|
+
if (format)
|
|
19
|
+
return { ...point, label: format(point, number) };
|
|
20
|
+
const value = Number(point.label);
|
|
21
|
+
const written = point.label !== undefined && point.label !== '' && Number.isFinite(value)
|
|
22
|
+
? numberOf(value)
|
|
23
|
+
: point.label;
|
|
24
|
+
return { ...point, label: written ?? '' };
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The markers of `marker`'s `layer` over a group of points. A marker over points that sit in a slice of their
|
|
29
|
+
* band is one part per slice, which `slice` names, to be moved into it as it is drawn - the move is in pixels,
|
|
30
|
+
* so it is left to the drawing, which knows the band's width.
|
|
31
|
+
*/
|
|
32
|
+
static parts(marker, layer, group, cfg) {
|
|
33
|
+
if (group.points.length === 0)
|
|
34
|
+
return [];
|
|
35
|
+
return (marker[layer] ?? []).flatMap((nested, i) => {
|
|
36
|
+
const key = `${layer}-${group.key}-${i}`;
|
|
37
|
+
const { points: which, ...own } = nested;
|
|
38
|
+
if (own.data)
|
|
39
|
+
return [{ key, marker: own }];
|
|
40
|
+
const rows = HoverLayers.#pointsOf(which, group);
|
|
41
|
+
if (rows.length === 0)
|
|
42
|
+
return [];
|
|
43
|
+
const placed = HoverLayers.#placed(HoverLayers.#inHover(own, cfg));
|
|
44
|
+
if (own.type === 'band')
|
|
45
|
+
return [{ key, marker: { ...placed, data: rows } }];
|
|
46
|
+
return HoverLayers.#bySlice(rows).map(({ slice, points }) => ({
|
|
47
|
+
key: `${key}-${slice ? `${slice.start},${slice.end}` : ''}`,
|
|
48
|
+
marker: { ...placed, data: points },
|
|
49
|
+
slice
|
|
50
|
+
}));
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** The points a nested marker draws: all of them, the one under the pointer, or those a function keeps. */
|
|
54
|
+
static #pointsOf(which, group) {
|
|
55
|
+
if (which === 'active')
|
|
56
|
+
return group.active ? [group.active] : [];
|
|
57
|
+
if (typeof which === 'function')
|
|
58
|
+
return group.points.filter(which);
|
|
59
|
+
return group.points;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* `marker` with what it leaves unset taken from the hover: a `rule` at each point along its axis and a `band`
|
|
63
|
+
* around it, in its slice; a `text` writes the point's label; each in the configuration's `hover` look (a `rect`
|
|
64
|
+
* too, in its `area` one), and a `dot` and a `text` in the point's series color.
|
|
65
|
+
*/
|
|
66
|
+
static #inHover(marker, cfg) {
|
|
67
|
+
const own = marker;
|
|
68
|
+
const color = (point) => point.color ?? 'currentColor';
|
|
69
|
+
switch (marker.type) {
|
|
70
|
+
case 'rule':
|
|
71
|
+
return {
|
|
72
|
+
...marker,
|
|
73
|
+
value: own.value ?? ((point) => point[marker.axis]),
|
|
74
|
+
styles: { ...cfg.hover.rule, ...own.styles }
|
|
75
|
+
};
|
|
76
|
+
case 'band':
|
|
77
|
+
return {
|
|
78
|
+
...marker,
|
|
79
|
+
value: own.value ?? ((point) => point[marker.axis]),
|
|
80
|
+
slice: own.slice ?? ((point) => point.areaInset),
|
|
81
|
+
styles: { ...cfg.hover.area, ...own.styles }
|
|
82
|
+
};
|
|
83
|
+
case 'rect':
|
|
84
|
+
return { ...marker, styles: { ...cfg.hover.area, ...own.styles } };
|
|
85
|
+
case 'dot':
|
|
86
|
+
return {
|
|
87
|
+
...marker,
|
|
88
|
+
styles: { ...cfg.hover.dot, dotFill: color, dotStroke: color, ...own.styles }
|
|
89
|
+
};
|
|
90
|
+
case 'text':
|
|
91
|
+
return {
|
|
92
|
+
...marker,
|
|
93
|
+
text: own.text ?? ((point) => point.label),
|
|
94
|
+
styles: { ...cfg.hover.font, fill: color, ...own.styles }
|
|
95
|
+
};
|
|
96
|
+
default:
|
|
97
|
+
return marker;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/** `marker` placed at the points: its own `x` and `y`, else the point's. */
|
|
101
|
+
static #placed(marker) {
|
|
102
|
+
if (!HoverLayers.#PLACED.has(marker.type))
|
|
103
|
+
return marker;
|
|
104
|
+
const own = marker;
|
|
105
|
+
return {
|
|
106
|
+
...marker,
|
|
107
|
+
x: own.x ?? ((point) => point.x),
|
|
108
|
+
y: own.y ?? ((point) => point.y)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** `points` split by the slice of the band each one sits in, in the order they come. */
|
|
112
|
+
static #bySlice(points) {
|
|
113
|
+
const groups = new Map();
|
|
114
|
+
for (const point of points) {
|
|
115
|
+
const slice = point.areaInset;
|
|
116
|
+
const id = slice ? `${slice.start},${slice.end}` : '';
|
|
117
|
+
const group = groups.get(id) ?? groups.set(id, { slice, points: [] }).get(id);
|
|
118
|
+
group.points.push(point);
|
|
119
|
+
}
|
|
120
|
+
return [...groups.values()];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RowContext } from '../../phases/context/RowContext';
|
|
1
2
|
import { PlotAxes } from '../../phases/data/PlotAxes';
|
|
2
3
|
/**
|
|
3
4
|
* A plot's hover as its `tooltip` and hover marker set it up: whether it is on,
|
|
@@ -44,7 +45,9 @@ export class HoverSettings {
|
|
|
44
45
|
sync: settings.sync,
|
|
45
46
|
tooltip: tooltip && {
|
|
46
47
|
...tooltip,
|
|
47
|
-
format: tooltip.format
|
|
48
|
+
format: tooltip.format
|
|
49
|
+
? (row) => tooltip.format(row, number, RowContext.of(row))
|
|
50
|
+
: format,
|
|
48
51
|
...(sort ? { sort } : {})
|
|
49
52
|
},
|
|
50
53
|
...(pointMatching ? { pointMatching } : {})
|