@fundar/data-chart-telling 1.17.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 +24 -0
- package/dist/configuration/config.svelte.js +3 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +2 -0
- package/dist/layout/geometry/GeometryLayout.svelte +188 -54
- 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 +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/LegendState.svelte.d.ts +2 -0
- package/dist/layout/legend/LegendState.svelte.js +5 -0
- 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 +12 -4
- package/dist/layout/styles/ValueLabels.js +22 -13
- 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/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 +23 -66
- package/dist/markers/hover/HoverMarker.svelte +7 -265
- package/dist/markers/hover/HoverMarker.svelte.d.ts +4 -27
- package/dist/markers/utils/PointPixel.d.ts +37 -0
- package/dist/markers/utils/PointPixel.js +44 -0
- 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 +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 +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 +15 -0
- package/dist/phases/markers/MarkersPhase.d.ts +4 -4
- package/dist/phases/markers/MarkersPhase.js +4 -4
- 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/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 +2 -2
- package/dist/plots/correlation/heatmap/defaults.d.ts +2 -2
- package/dist/plots/correlation/heatmap/defaults.js +21 -6
- package/dist/plots/correlation/heatmap/markers.d.ts +2 -2
- package/dist/plots/correlation/heatmap/markers.js +4 -3
- 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 +2 -2
- package/dist/plots/correlation/scatter/markers.js +4 -3
- 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 +20 -25
- package/dist/plots/distribution/histogram/markers.d.ts +2 -2
- package/dist/plots/distribution/histogram/markers.js +5 -4
- package/dist/plots/distribution/pyramid/defaults.d.ts +2 -2
- package/dist/plots/distribution/pyramid/defaults.js +4 -1
- package/dist/plots/distribution/pyramid/markers.d.ts +2 -2
- package/dist/plots/distribution/pyramid/markers.js +4 -3
- 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 +3 -3
- 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 +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/defaults.d.ts +2 -2
- package/dist/plots/part-of-a-whole/treemap/defaults.js +37 -21
- package/dist/plots/ranking/bar/defaults.d.ts +2 -2
- package/dist/plots/ranking/bar/defaults.js +13 -7
- package/dist/plots/ranking/bar/markers.d.ts +3 -3
- package/dist/plots/ranking/bar/markers.js +8 -7
- 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 +9 -9
- package/dist/plots/ranking/cleveland/ClevelandMarkers.d.ts +3 -3
- package/dist/plots/ranking/cleveland/ClevelandMarkers.js +11 -10
- 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 +4 -0
- 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/styles/values.d.ts +8 -2
- package/dist/types/layout/tooltip.d.ts +5 -10
- 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 +2 -2
- package/dist/types/markers/axis/hover.d.ts +60 -15
- package/dist/types/markers/channels/commonMarkerConfig.d.ts +6 -2
- package/dist/types/markers/common.d.ts +1 -0
- package/dist/types/markers/common.js +1 -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 -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 +1 -1
- package/dist/types/phases/styles/phase.d.ts +3 -2
- package/dist/types/phases/transforms/phase.d.ts +2 -2
- package/dist/types/plots/constants.d.ts +3 -5
- package/dist/types/plots/correlation/heatmap/state.d.ts +2 -2
- package/dist/types/plots/correlation/scatter/state.d.ts +2 -2
- package/dist/types/plots/distribution/box/props.d.ts +23 -1
- package/dist/types/plots/distribution/box/state.d.ts +6 -17
- package/dist/types/plots/distribution/density/state.d.ts +2 -2
- package/dist/types/plots/distribution/histogram/props.d.ts +14 -1
- package/dist/types/plots/distribution/histogram/state.d.ts +2 -2
- package/dist/types/plots/distribution/pyramid/state.d.ts +2 -2
- package/dist/types/plots/distribution/violin/props.d.ts +2 -1
- package/dist/types/plots/distribution/violin/state.d.ts +2 -2
- package/dist/types/plots/evolution/area/state.d.ts +2 -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/map/geo/state.d.ts +1 -1
- package/dist/types/plots/part-of-a-whole/treemap/props.d.ts +14 -4
- 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/state.d.ts +2 -2
- package/dist/types/plots/ranking/bullet/state.d.ts +2 -2
- package/dist/types/plots/ranking/cleveland/state.d.ts +2 -2
- package/dist/types/plots/ranking/dumbbell/state.d.ts +2 -2
- package/dist/types/plots/ranking/forest/state.d.ts +2 -2
- package/dist/types/plots/ranking/lollipop/state.d.ts +2 -2
- package/docs/markers.md +34 -2
- 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 -2
- package/docs/theming.md +2 -1
- package/docs/tooltip-and-hover.md +81 -3
- 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 +8 -6
- package/llms.txt +2 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## [1.18.0] - 2026-11-09
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- A `band` marker: the band of a category on a band scale, across the whole of the other axis - `{ type: 'band', axis: 'x', value: 'Salta' }`. `value` is a category or a list of them, or with `data` a field key or a function of the row; rows that name the same category draw one band. `slice` fills part of it, as the fractions of its width left out at each end (a grouped bar's series), and a band several rows share fills what all of their slices do. `styles` take `AreaStyle`, each field a value or a function of the row, over the configuration's new `band` (`{ fill: '#94a3b8', fillOpacity: 0.25 }`). It takes the pointer only with a handler of its own, and draws nothing on an axis that is not a band scale.
|
|
10
|
+
- The `hover` marker's `active` and `others` restyle the shapes themselves: the ones the hover matches (by its `strategy`) take `active`, every other one `others`, while the hover is on - `fill`, `fillOpacity`, `stroke`, `strokeWidth`, `strokeOpacity` and `strokeDasharray`, each a value or a function of the row. `markers={[{ type: 'hover', active: { fillOpacity: 1 }, others: { fillOpacity: 0.3 } }]}` lightens the hovered tile of a `TreemapPlot` and fades the rest, and does the same on the cells of a `HeatmapPlot`, the bars of a `BarPlot`, a `BulletPlot` and a `PyramidPlot`, a `HistogramPlot`'s bins, a `ScatterPlot`'s dots and the dots of the Cleveland family, whose own shapes are linked to the hover. On a dot they are its `dotFill`, `dotStroke`... The shape is restyled, not covered: its label stays on top, and one with no `fill` of its own is written in the color that reads best on the new one. They go over `styles` and `segments`; a series the legend dims keeps its dimmed fill and opacities.
|
|
11
|
+
- The `hover` marker's `back` and `front`: the markers it draws behind the plot's shapes and in front of them - any marker but another `hover`, a `component` too, with its styles and events. They draw the hovered points, each a row with its `x`, `y`, `label` (written as the marker's number fields or `format` ask), `series`, `color`, `areaInset` and `row`, unless they have `data` of their own, and what they leave unset comes from the hover: `x` and `y`, a `rule`'s and a `band`'s `value` (and a band's `slice`), a `text`'s `text`, the configuration's `hover` look (`rule`, `dot`, `font`, `area`) and the series color of a `dot` and a `text`. `points: 'active'` draws only the point under the pointer, and a function of the point some of them. On a grouped bar plot each is drawn in its series' slice of the band.
|
|
12
|
+
- Each plot kind has a hover of its own that an author's `hover` marker is laid over: `active` and `others` field by field, `back` and `front` replaced when set (`back: []` draws nothing behind). `LinePlot`, `AreaPlot` and `DensityPlot` draw a crosshair along each axis their strategy matches along, and a dot and the value on each point, as the marker did; `ScatterPlot` a crosshair through the point and its value; `SlopePlot` and the Cleveland family (`ClevelandPlot`, `DumbbellPlot`, `ForestPlot`, `LollipopPlot`) a rule along the value axis, a dot and the value; `BarPlot`, `BulletPlot`, `BoxPlot`, `ViolinPlot` and `PyramidPlot` the hovered category's band behind their shapes; `HistogramPlot` the hovered bin's span; `SparklinePlot` a dot; `TreemapPlot` and `HeatmapPlot` only outline the hovered tile or cell, in the configuration's new `hover.active` (`{ stroke: '#111827', strokeWidth: 2 }`).
|
|
13
|
+
- The hover's point under the pointer is the one nearest it of those the hover reaches: a crosshair at it, and `points: 'active'`, follow the pointer up and down a category from one series' point to another's.
|
|
14
|
+
- A row context: what a plot knows of each row it draws, worked out once as it reads its data and kept on the row - its `series`, its `x` and `y` (its own values, not a stack's running total, else where the transforms put it), the `value` it shows, the `row` itself, and what the plot kind works out for it: a `TreemapPlot` tile's `name`, `path` and `share`; a `HistogramPlot` bin's `count`, `from` and `to`; a `BoxPlot` or `ViolinPlot` value's box (`category`, `min`, `p25`, `median`, `p75`, `max`, `count`, `outliers`); a `DensityPlot` point's estimate as its `value`; a `HeatmapPlot` cell's color value. `tooltip.format`, `styles.values.format`, the `hover` marker's points (`point.context`, in its `format` and its `back` and `front` markers) and `usePlot().contextOf(row)` all read it, and `RowContext.of(row)` reads it anywhere, from a row or a copy of it. A plot kind adds its own with a `context` function in its defaults. `PlotRowContext`, `KindRowContext`, `TreemapRowContext`, `HistogramRowContext` and `BoxRowContext` are exported.
|
|
15
|
+
- A `DensityPlot`'s hovered point and its tooltip read as its estimated density, with three decimals.
|
|
16
|
+
- What a plot's hover draws follows the strategy in force as it is shown: a composer's `hover.strategy` changed while the plot is on screen (a scrolly step) changes the crosshair it draws.
|
|
17
|
+
- A marker's `hover` takes `'trigger'` (a hit area of the plot's hover, what `true` was) and `'style'` (its shapes take the hover marker's `active` and `others`); `true` does both. `HoverMarkerConfig`, `HoverShapeStyle` and `HoverLayerMarker` are exported.
|
|
18
|
+
- `examples/TreemapHover.svelte`, a _Configuration / State_ story reading a histogram's row context, and a `Layout/Hover` section of stories: each plot kind's own hover, the strategies (one changed while a plot is shown), the number fields, the scope, `active` and `others`, `back` and `front`.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **Breaking:** `styles.values.format` is `(value, number, context)`, as a tooltip's `format`: the series is `context.series`, the labelled row `context.row`. `format: (v, name) => `${name}: ${v}`` is `format: (v, _number, { series }) => `${series}: ${v}``.
|
|
23
|
+
- **Breaking:** a `HistogramPlot`'s tooltip rows are its bins as they are, without the `count`, `from`, `to` and `group` they had: those are in the `context`, a `tooltip.format`'s third argument (`group` is `series`).
|
|
24
|
+
- A tooltip's `context` holds the row's `x`, `y`, `value` and `row` along with its `series`, and a `TreemapPlot`'s the tile's `name`, `path` and `value` along with its `share`. `TreemapTooltipContext` is `TreemapRowContext`.
|
|
25
|
+
- **Breaking:** the `hover` marker's `ruleX`, `ruleY`, `areaX`, `areaY`, `showLabels`, `rule`, `area`, `dot` and `text` are gone: what it draws is its `back` and `front` markers. `ruleX: false` is `back: []`; `ruleY: true` a `{ type: 'rule', axis: 'y', points: 'active' }` in `back`; `areaX: true` a `{ type: 'band', axis: 'x' }` in `back`; `showLabels: false` is `front: [{ type: 'dot' }]`; `rule`, `area`, `dot` and `text` are the `styles` of those markers. `text.textAnchor: 'outside'` is two `text` markers, each kept to one side of zero by `points`. On every plot but `LinePlot`, `AreaPlot` and `DensityPlot`, `{ type: 'hover' }` draws something else than the crosshair, dot and label it drew: see the hover each plot kind has of its own, above.
|
|
26
|
+
- A marker with `hover: true` (or `'trigger'`) hovers the row of the shape under the pointer, not the first of its rows.
|
|
27
|
+
- A series the legend dims (`mode: 'dim'`) stays hoverable: it is matched and shows in the tooltip. Only one it hides, omits or rescales away is out of the hover.
|
|
28
|
+
|
|
5
29
|
## [1.17.0] - 2026-11-06
|
|
6
30
|
|
|
7
31
|
### Added
|
|
@@ -161,7 +161,8 @@ export const DEFAULT_CONFIG = {
|
|
|
161
161
|
rule: { stroke: '#e6580d', strokeOpacity: 0.35, strokeWidth: 1.5, strokeDasharray: '4 4' },
|
|
162
162
|
dot: { dotRadius: 5, dotFill: 'currentColor' },
|
|
163
163
|
font: { fill: 'currentColor', fontSize: 12, dy: -18 },
|
|
164
|
-
area: { fill: '#94a3b8', fillOpacity: 0.4 }
|
|
164
|
+
area: { fill: '#94a3b8', fillOpacity: 0.4 },
|
|
165
|
+
active: { stroke: '#111827', strokeWidth: 2 }
|
|
165
166
|
},
|
|
166
167
|
facet: {
|
|
167
168
|
indicator: {
|
|
@@ -247,7 +248,7 @@ export const DEFAULT_CONFIG = {
|
|
|
247
248
|
labelFontSize: 11,
|
|
248
249
|
labelGap: 4
|
|
249
250
|
},
|
|
250
|
-
|
|
251
|
+
band: { fill: '#94a3b8', fillOpacity: 0.25 },
|
|
251
252
|
delta: {
|
|
252
253
|
text: {
|
|
253
254
|
x: { dx: 12, dy: 0, lineAnchor: 'middle', textAnchor: 'start' },
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,11 @@ export { default as GridCell } from './layout/grid/GridCell.svelte';
|
|
|
22
22
|
export { default as Plot } from './layout/plot/Plot.svelte';
|
|
23
23
|
export { default as BasePlotLayout } from './layout/base/BasePlotLayout.svelte';
|
|
24
24
|
export { usePlot, useFigure } from './layout/plot/usePlot';
|
|
25
|
+
export { RowContext } from './phases/context/RowContext';
|
|
26
|
+
export type { PlotRowContext, KindRowContext } from './types/layout/context';
|
|
27
|
+
export type { ContextStageOptions } from './types/phases/context/phase';
|
|
28
|
+
export type { BoxRowContext, BoxSummary } from './types/plots/distribution/box/props';
|
|
29
|
+
export type { HistogramRowContext } from './types/plots/distribution/histogram/props';
|
|
25
30
|
export type { PublicPlotContext, PublicFigureContext, PublicHover, PublicPlotHover, PublicLegend, PublicTimeline } from './layout/plot/PublicPlotContext';
|
|
26
31
|
export { argentinaBicontinental } from './layout/coordinates/projections/argentina';
|
|
27
32
|
export { setConfiguration, getConfiguration, resetConfiguration, configToCssVars, cssVarsStyle, cssVarsRule, DEFAULT_CONFIG } from './configuration/config.svelte';
|
|
@@ -37,7 +42,7 @@ export { Statistics } from './phases/statistics/Statistics';
|
|
|
37
42
|
export type { AxisValue, ChannelValue, ChannelName, AxisChannelName, IndependentChannelName, SizeChannelName, ChannelAccessors, GroupingAccessor } from './types/layout/mapping';
|
|
38
43
|
export type { AxisScale, AxisBasedScalesConfig, ChannelScalesConfig } from './types/layout/scales';
|
|
39
44
|
export type { NumberDisplay } from './types/layout/numbers';
|
|
40
|
-
export type { TreemapPlotProps, TreemapTooltipContext } from './types/plots/part-of-a-whole/treemap/props';
|
|
45
|
+
export type { TreemapPlotProps, TreemapRowContext, TreemapTooltipContext } from './types/plots/part-of-a-whole/treemap/props';
|
|
41
46
|
export type { TreemapTile } from './types/transforms/treemap';
|
|
42
47
|
export type { Accessor, Series, SeriesProps, NonAxisDataProps, SingleAxisDataProps, DualAxisDataProps } from './types/plots/data/common';
|
|
43
48
|
export type { BasePlotProps, PlotCoreProps, PlotChromeProps, FigureBoxProps, SegmentsConfig, ScalesConfig, MarginConfig, TooltipConfig, HoverConfig } from './types/plots/props';
|
|
@@ -47,7 +52,7 @@ export type { LineSegmentStyle, BarSegmentStyle, CellSegmentStyle, GeoSegmentSty
|
|
|
47
52
|
export type { Range, Area, Segment } from './types/plots/segments/config';
|
|
48
53
|
export type { SymbolType } from './types/plots/constants';
|
|
49
54
|
export type { FontStyle, StrokeStyle, DotStyle, AreaStyle } from './types/plots/styling';
|
|
50
|
-
export type { AxisBasedMarkersConfig, BrushSelection } from './types/markers/common';
|
|
55
|
+
export type { AxisBasedMarkersConfig, BrushSelection, HoverMarkerConfig, HoverShapeStyle, HoverLayerMarker } from './types/markers/common';
|
|
51
56
|
export type { StatisticConfig } from './types/layout/statistics';
|
|
52
57
|
export type * from './types/transforms';
|
|
53
58
|
export type { GeoFeature, GeoJsonInput, GeoDataProps, Topology } from './types/plots/data/geo';
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,8 @@ export { default as GridCell } from './layout/grid/GridCell.svelte';
|
|
|
28
28
|
export { default as Plot } from './layout/plot/Plot.svelte';
|
|
29
29
|
export { default as BasePlotLayout } from './layout/base/BasePlotLayout.svelte';
|
|
30
30
|
export { usePlot, useFigure } from './layout/plot/usePlot';
|
|
31
|
+
// What a plot knows of each row it draws, which every format reads.
|
|
32
|
+
export { RowContext } from './phases/context/RowContext';
|
|
31
33
|
// Custom geo projections - usable as `scales.projection.type`.
|
|
32
34
|
export { argentinaBicontinental } from './layout/coordinates/projections/argentina';
|
|
33
35
|
export { setConfiguration, getConfiguration, resetConfiguration, configToCssVars, cssVarsStyle, cssVarsRule, DEFAULT_CONFIG } from './configuration/config.svelte';
|
|
@@ -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';
|
|
@@ -54,6 +55,14 @@
|
|
|
54
55
|
import type { GeoFeature } from '../../types/plots/data/geo';
|
|
55
56
|
import { MarkerGrouping } from '../../phases/statistics/MarkerGrouping';
|
|
56
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';
|
|
57
66
|
|
|
58
67
|
/**
|
|
59
68
|
* Renders every marker in `markers`, in array order, each delegated to the
|
|
@@ -107,9 +116,137 @@
|
|
|
107
116
|
} = $props();
|
|
108
117
|
|
|
109
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
|
+
};
|
|
110
146
|
|
|
111
147
|
// Mounted inside svelteplot's `<Plot>`, the one place the margins it settles on can be read.
|
|
112
|
-
|
|
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
|
+
);
|
|
113
250
|
|
|
114
251
|
const scopedSeriesOf = (marker: MarkerConfig): string | undefined =>
|
|
115
252
|
'series' in marker && typeof marker.series === 'string' && marker.series
|
|
@@ -131,19 +268,20 @@
|
|
|
131
268
|
}
|
|
132
269
|
|
|
133
270
|
/**
|
|
134
|
-
* A marker with `hover: true`, with the plot's hover added to its own pointer handlers: entering or
|
|
135
|
-
* over
|
|
136
|
-
* under a resting pointer - and leaving it ends the hover.
|
|
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.
|
|
137
273
|
*/
|
|
138
274
|
function withHover(marker: MarkerConfig, rows: TData[] | TSeries[]): MarkerConfig {
|
|
139
|
-
if (!('hover' in marker) || marker.hover !== true
|
|
275
|
+
if (!('hover' in marker) || (marker.hover !== true && marker.hover !== 'trigger'))
|
|
276
|
+
return marker;
|
|
140
277
|
const own = marker as CommonMarkerEvents & { data?: unknown[] };
|
|
141
|
-
|
|
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];
|
|
142
280
|
return {
|
|
143
281
|
...marker,
|
|
144
282
|
onpointerenter: (event: Event, row: unknown, index: number) => {
|
|
145
283
|
own.onpointerenter?.(event, row, index);
|
|
146
|
-
ctrl.onPointer(hovered);
|
|
284
|
+
ctrl.onPointer(hovered(row));
|
|
147
285
|
},
|
|
148
286
|
onpointerleave: (event: Event, row: unknown, index: number) => {
|
|
149
287
|
own.onpointerleave?.(event, row, index);
|
|
@@ -151,7 +289,7 @@
|
|
|
151
289
|
},
|
|
152
290
|
onpointermove: (event: Event, row: unknown, index: number) => {
|
|
153
291
|
own.onpointermove?.(event, row, index);
|
|
154
|
-
ctrl.onPointer(hovered);
|
|
292
|
+
ctrl.onPointer(hovered(row));
|
|
155
293
|
}
|
|
156
294
|
} as MarkerConfig;
|
|
157
295
|
}
|
|
@@ -210,6 +348,8 @@
|
|
|
210
348
|
<TextMarker marker={{ ...marker, data: marker.data ?? rows }} />
|
|
211
349
|
{:else if marker.type === 'rule'}
|
|
212
350
|
<RuleMarker {marker} />
|
|
351
|
+
{:else if marker.type === 'band'}
|
|
352
|
+
<BandMarker {marker} />
|
|
213
353
|
{:else if marker.type === 'geo'}
|
|
214
354
|
<GeoFeaturesMarker {marker} />
|
|
215
355
|
{:else if marker.type === 'graticule'}
|
|
@@ -247,15 +387,6 @@
|
|
|
247
387
|
<marker.component {...marker.props} data={marker.data ?? seriesData} />
|
|
248
388
|
{:else if marker.type === 'geo-component'}
|
|
249
389
|
<marker.component {...marker.props} data={marker.data ?? rows} />
|
|
250
|
-
{:else if marker.type === 'hover'}
|
|
251
|
-
<HoverMarker
|
|
252
|
-
{marker}
|
|
253
|
-
data={ctrl.points}
|
|
254
|
-
activePoint={ctrl.activePoint}
|
|
255
|
-
impliesCrosshairX={ctrl.impliesCrosshairX}
|
|
256
|
-
impliesCrosshairY={ctrl.impliesCrosshairY}
|
|
257
|
-
onActivePointPixel={ctrl.reportActivePointPixel}
|
|
258
|
-
/>
|
|
259
390
|
{:else if marker.type === 'geo-hover'}
|
|
260
391
|
<GeoHoverMarker {marker} data={ctrl.points} />
|
|
261
392
|
{:else if marker.type === 'delta'}
|
|
@@ -264,41 +395,16 @@
|
|
|
264
395
|
{/snippet}
|
|
265
396
|
|
|
266
397
|
{#snippet renderMarker(marker: MarkerConfig, rows: TData[] | TSeries[])}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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}
|
|
270
404
|
{/snippet}
|
|
271
405
|
|
|
272
406
|
{#snippet renderScoped(marker: MarkerConfig, group: ScopedMarkerGroup<TSeries>)}
|
|
273
|
-
{#if marker.type === '
|
|
274
|
-
{@const seriesPoints = ctrl.points.filter((p) => p.series === group.name)}
|
|
275
|
-
{#if marker.scope === 'segment'}
|
|
276
|
-
{#each group.segments as seg, segIdx (`${group.name}-hover-segment-${segIdx}`)}
|
|
277
|
-
<!-- p.row (TData) is always a superset of TSeries in practice, not provable across two independent generics. -->
|
|
278
|
-
{@const segPoints = seriesPoints.filter((p) => seg.match(p.row as unknown as TSeries))}
|
|
279
|
-
{#if segPoints.length > 0}
|
|
280
|
-
<HoverMarker
|
|
281
|
-
marker={MarkerGrouping.withHoverSeriesColor(marker, seg.color)}
|
|
282
|
-
data={segPoints}
|
|
283
|
-
activePoint={segPoints[0] ?? null}
|
|
284
|
-
impliesCrosshairX={ctrl.impliesCrosshairX}
|
|
285
|
-
impliesCrosshairY={ctrl.impliesCrosshairY}
|
|
286
|
-
/>
|
|
287
|
-
{/if}
|
|
288
|
-
{/each}
|
|
289
|
-
{:else}
|
|
290
|
-
<HoverMarker
|
|
291
|
-
marker={MarkerGrouping.withHoverSeriesColor(
|
|
292
|
-
marker,
|
|
293
|
-
group.segments[0]?.color ?? group.color
|
|
294
|
-
)}
|
|
295
|
-
data={seriesPoints}
|
|
296
|
-
activePoint={seriesPoints[0] ?? null}
|
|
297
|
-
impliesCrosshairX={ctrl.impliesCrosshairX}
|
|
298
|
-
impliesCrosshairY={ctrl.impliesCrosshairY}
|
|
299
|
-
/>
|
|
300
|
-
{/if}
|
|
301
|
-
{:else if marker.type === 'component'}
|
|
407
|
+
{#if marker.type === 'component'}
|
|
302
408
|
{#if marker.scope === 'segment'}
|
|
303
409
|
{#each group.segments as seg, segIdx (`${group.name}-component-segment-${segIdx}`)}
|
|
304
410
|
{@const segmentData = group.data.filter((row) => seg.match(row))}
|
|
@@ -316,10 +422,35 @@
|
|
|
316
422
|
{/if}
|
|
317
423
|
{/snippet}
|
|
318
424
|
|
|
319
|
-
|
|
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. -->
|
|
320
443
|
{#each markers as marker, i (markerKey(marker, i))}
|
|
321
444
|
{@const scope = scopedSeriesOf(marker)}
|
|
322
|
-
{#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}
|
|
323
454
|
<FrameClip clip={FrameClipping.isClipped(marker)}>
|
|
324
455
|
{@render renderMarker(marker, data)}
|
|
325
456
|
</FrameClip>
|
|
@@ -335,8 +466,11 @@
|
|
|
335
466
|
{#each markers as marker, i (markerKey(marker, i))}
|
|
336
467
|
{@const scope = scopedSeriesOf(marker)}
|
|
337
468
|
{#if 'label' in marker && marker.label && (scope === undefined || groupByName.has(scope))}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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}
|
|
341
475
|
{/if}
|
|
342
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 {};
|