@fundar/data-chart-telling 1.15.0 → 1.17.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 +38 -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 +18 -4
- package/dist/configuration/themes/dark.js +1 -1
- package/dist/configuration/themes/editorial.js +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +2 -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 +42 -1
- package/dist/layout/hover/HoverSettings.d.ts +3 -1
- package/dist/layout/hover/HoverSettings.js +4 -2
- 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 +12 -2
- package/dist/layout/legend/LegendState.svelte.js +18 -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/Plot.svelte +4 -2
- package/dist/layout/plot/Plot.svelte.d.ts +2 -1
- package/dist/layout/scales/ScalesLayout.svelte +1 -1
- package/dist/layout/styles/ValueLabels.d.ts +33 -2
- package/dist/layout/styles/ValueLabels.js +67 -8
- package/dist/layout/timeline/Timeline.svelte +5 -1
- package/dist/layout/timeline/TimelineLayout.svelte +4 -1
- package/dist/layout/timeline/TimelineSteps.d.ts +6 -2
- package/dist/layout/timeline/TimelineSteps.js +9 -3
- package/dist/markers/area/AreaMarker.svelte +3 -0
- package/dist/markers/arrow/ArrowMarker.svelte +9 -5
- package/dist/markers/bar/BarMarker.svelte +45 -48
- 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 +22 -6
- 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/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 +3 -1
- package/dist/phases/Pipeline.js +1 -0
- package/dist/phases/data/DataPhase.js +51 -10
- package/dist/phases/hover/HoverPhase.js +9 -1
- package/dist/phases/mapping/MappingPhase.js +2 -1
- package/dist/phases/markers/MarkerStyles.d.ts +18 -0
- package/dist/phases/markers/MarkerStyles.js +111 -0
- package/dist/phases/markers/MarkersPhase.d.ts +1 -1
- package/dist/phases/markers/MarkersPhase.js +7 -5
- package/dist/phases/statistics/StatisticsPhase.js +1 -1
- package/dist/phases/transforms/Transforms.js +3 -1
- package/dist/phases/transforms/TransformsPhase.js +58 -4
- 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.js +2 -2
- package/dist/plots/correlation/heatmap/markers.d.ts +0 -8
- package/dist/plots/correlation/heatmap/markers.js +8 -35
- package/dist/plots/correlation/scatter/markers.d.ts +1 -1
- package/dist/plots/correlation/scatter/markers.js +2 -2
- package/dist/plots/distribution/histogram/defaults.js +2 -2
- package/dist/plots/distribution/histogram/markers.d.ts +1 -10
- package/dist/plots/distribution/histogram/markers.js +17 -59
- package/dist/plots/distribution/pyramid/defaults.js +3 -3
- package/dist/plots/distribution/pyramid/markers.d.ts +0 -10
- package/dist/plots/distribution/pyramid/markers.js +13 -64
- package/dist/plots/distribution/violin/markers.js +1 -1
- package/dist/plots/map/geo/phases/markers.js +3 -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 +167 -0
- package/dist/plots/ranking/bar/defaults.js +2 -2
- package/dist/plots/ranking/bar/markers.d.ts +1 -11
- package/dist/plots/ranking/bar/markers.js +38 -80
- package/dist/plots/ranking/bullet/markers.js +2 -3
- package/dist/plots/ranking/cleveland/ClevelandMarkers.js +17 -13
- package/dist/types/configuration/styling.d.ts +33 -2
- 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/tooltip.d.ts +16 -4
- package/dist/types/markers/axis/arrow.d.ts +2 -8
- package/dist/types/markers/axis/bar.d.ts +4 -8
- 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/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 +4 -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/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/data/phase.d.ts +5 -0
- package/dist/types/phases/hover/phase.d.ts +2 -0
- package/dist/types/phases/state.d.ts +7 -0
- package/dist/types/phases/statistics/phase.d.ts +2 -1
- package/dist/types/phases/transforms/phase.d.ts +11 -0
- package/dist/types/plots/constants.d.ts +14 -14
- package/dist/types/plots/correlation/heatmap/props.d.ts +3 -3
- package/dist/types/plots/correlation/scatter/props.d.ts +3 -3
- 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 +3 -3
- package/dist/types/plots/distribution/density/props.d.ts +3 -11
- package/dist/types/plots/distribution/histogram/props.d.ts +3 -11
- package/dist/types/plots/distribution/pyramid/props.d.ts +3 -3
- package/dist/types/plots/distribution/violin/props.d.ts +3 -3
- package/dist/types/plots/evolution/area/props.d.ts +3 -3
- package/dist/types/plots/evolution/line/props.d.ts +3 -3
- package/dist/types/plots/part-of-a-whole/treemap/props.d.ts +19 -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 +7 -4
- package/dist/types/plots/ranking/bar/props.d.ts +3 -3
- package/dist/types/plots/ranking/cleveland/props.d.ts +3 -3
- package/dist/types/plots/ranking/dumbbell/props.d.ts +3 -3
- package/dist/types/plots/ranking/forest/props.d.ts +3 -3
- package/dist/types/plots/ranking/lollipop/props.d.ts +3 -3
- 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 +76 -26
- package/docs/plots/part-of-a-whole/treemap.md +69 -0
- package/docs/plots/ranking/bar.md +1 -1
- package/docs/plots.md +21 -20
- package/docs/scales.md +3 -0
- package/docs/state.md +1 -1
- package/docs/styles-and-segments.md +19 -18
- package/docs/theming.md +5 -12
- package/docs/tooltip-and-hover.md +1 -1
- package/docs/transforms-and-statistics.md +17 -16
- package/examples/Treemap.svelte +13 -0
- package/examples/datasets/economic-activity.ts +40 -0
- package/examples/datasets/index.ts +1 -0
- package/llms-full.txt +5 -5
- package/llms.txt +2 -0
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,44 @@
|
|
|
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.17.0] - 2026-11-06
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- A `rect`, `cell`, `bar` or `waffle` marker takes a `label`: a text in the middle of each shape, with every option of a `text` marker, fitted to the shape - written smaller, down to `minFontSize`; then cut short with an ellipsis on as many lines as it holds; then as its `fallback`, a value alone, say; and left out when nothing fits. It takes no pointer from the shape, unless it has a handler of its own. `anchor` puts it against an edge or in a corner, and `outside` beyond the edge, where `fitMargins` makes room for it. A `text` marker takes the same `fit`, with a box of its own.
|
|
10
|
+
- A `treemap` transform, for a `rect` marker on any plot kind: it lays the rows out as tiles in the unit square with d3-hierarchy - a tile per distinct path of `levels`, its area the sum of its rows' `value` - and gives `x1`/`x2`/`y1`/`y2` (and `x`/`y` at each tile's centre for a `text`). `tile` picks how a rectangle is split (`'squarify'`, `'binary'`, `'slice'`, `'dice'`, `'sliceDice'`) and `aspect` the shape of the box the tiles fill.
|
|
11
|
+
- Every marker takes handlers for the pointer (`onclick`, `onpointerenter`, `onpointerleave`, `onpointermove`...), called with the event and the row of the shape. They are the props svelteplot documents on all its marks, passed on by every marker that draws one (not `brush`, `hover`, `inset`, `delta` or the map's `features`); svelteplot's code wires them up on `Rect`, `Bar`, `Cell`, `Area`, `Arrow`, `Dot`, `Trail`, `Vector`, `Line`, `Link`, `DelaunayLink` and `Voronoi` so far, and the rest will follow it. `rect`'s `styles.borderRadius` rounds its corners.
|
|
12
|
+
- A `text` marker takes the pointer handlers every marker takes (`onclick`, `onpointerenter`...) in place of its own `onPointerEnter` and `onPointerLeave`, which are gone.
|
|
13
|
+
- The `styles` of the markers that draw a shape per row - `rect`, `bar`, `cell`, `waffle`, `dot`, `tick`, `rule`, `arrow`, `voronoi` and `delaunayLink`, and `text` for `fill`, `fillOpacity`, `stroke`, `strokeWidth`, `fontWeight` and `fontStyle` - take a function of the row in place of a value: `styles: { fillOpacity: (row) => (row.selected ? 0.55 : 0.12) }`. A string names a field of the rows instead: a number such as `strokeWidth` or `fillOpacity` always, a color when the rows have a field of that name. A color or an opacity a function returns is drawn as it is.
|
|
14
|
+
- `TreemapPlot`: a tile per row, its area its `value`, nested by `grouping` and laid out with `d3-hierarchy` (a `treemap` entry in `transforms` sets `tile`: `'squarify'`, `'binary'`, `'slice'`, `'dice'` or `'sliceDice'`). `grouping` is the whole path of a tile (`'sector.branch'`) (the last level names it, rows with the same path are one tile, so `grouping: 'sector'` alone is a tile per sector) and its outermost level colors the tiles and fills the legend. The tiles are the `treemap` transform drawn as `rect` markers with a `label`. `segments` can be keyed by the path of a tile (`'Tertiary.Finance'`), the most specific winning, and `tooltip.format(row, number, context)` gets the tile's `share` (0 to 100) in its `context`. A tile is labelled with its name over its share of the whole, as `styles.values` asks, and the label is fitted to the tile: at a smaller font size first, then the name cut short with an ellipsis, then the share alone, then nothing. Hovering a tile matches it alone. `treemap` in the configuration sets the line between tiles and the label's color, size and room.
|
|
15
|
+
- `grouping` takes fields joined by dots (`'region.sex'`): the levels of one grouping, outermost first. A plot that nests its rows (`TreemapPlot`) nests by them; any other splits its rows by the combination of the levels, a series named `'CABA.F'`. A dotted name is a field when the rows have one by that name.
|
|
16
|
+
- `DataProps` is now `DualAxisDataProps`, one of a family by the axes a plot has: `SingleAxisDataProps` (`x` or `y` alone, a histogram's or a density's) and `NonAxisDataProps` (no position channels, a treemap's), which the other two extend. Each takes the channels a plot cannot draw without as a second parameter.
|
|
17
|
+
- `scales.color.depth`: with a `grouping` of several levels, the level the colors reach - each outermost value keeps its categorical color and the values under it, down to that level, take tones of it. A treemap colors its tiles so, and any other plot the series it splits by every level. `ColorTones` (`colorTones`, `hierarchicalColors`) builds the tones, for any plot of a hierarchy.
|
|
18
|
+
- A legend's `disabled: { mode: 'rescale' }`: the series is removed and the parts left of a whole are the new 100% - a stack's categories are scaled back up to their totals, a treemap's tiles laid out and given their shares anew. `'omit'` now leaves a treemap's other tiles in their place and with their share of the whole.
|
|
19
|
+
- The legend makes words of each level of a series grouped by several (`'Americas.Argentina'`).
|
|
20
|
+
- A `value` channel: what a row amounts to as a part of a whole. `TreemapPlot` sizes its tiles by it; the other plots ignore it.
|
|
21
|
+
- `tooltip.format` gets a third argument, `context`: what the plot knows of the row beyond its fields - its `series`, and what its kind adds (a treemap's `share`).
|
|
22
|
+
- A marker's `strokeDasharray` takes a named line style - `'solid'`, `'dashed'`, `'dotted'`, `'dashdot'` - as well as an SVG dash pattern.
|
|
23
|
+
- Every marker takes `hover: true`, which makes it a hit area of the plot's hover: the pointer over any of its shapes hovers its rows.
|
|
24
|
+
- A label inside its shape (`rect`, `cell`, `bar`, `waffle`, and the value labels of every plot written in a shape) with no `fill` of its own is written in the color that reads best on the shape, as it is seen - blended with the plot's background as far as its `fillOpacity` lets it through. It picks from the configuration's new `text.label.contrast` (`['#ffffff', '#111827']`), and takes white or black instead when neither reaches WCAG AA (4.5:1).
|
|
25
|
+
- `CssColor.alpha` and `CssColor.composite`: a color's opacity, and the opaque color it is seen as over a backdrop. `CssColor.contrastText` (and `contrastTextColor`) takes a `minRatio`, WCAG AA by default.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **Breaking:** `continuous.labelColor` and the `--dct-heat-text`, `--dct-heat-min` and `--dct-heat-max` CSS variables are gone: a heatmap's value labels contrast with each cell (`text.label.contrast`), and its ramp is the default continuous one, `continuous.min`/`max` or `continuous.scheme`, set with `setConfiguration`. No style read the variables.
|
|
30
|
+
- The configuration's `--dct-*` CSS variables are set once on the document root (`:where(:root)`), not on each figure, so a variable set on a wrapping element overrides them, as the theming docs say. `cssVarsRule` writes them as that rule.
|
|
31
|
+
- The axes, and what a plot writes in their ink (value labels outside their shape, a violin's box, a bullet's target, a Cleveland connector, a map's outlines), take `--dct-axis-color`; the timeline's current step takes `--dct-timeline-active`. Both fall back to the configuration.
|
|
32
|
+
- `CssColor.contrastText` never returns a candidate under its `minRatio` (WCAG AA, 4.5:1) when white or black does better, and its luminance follows sRGB's own threshold (0.04045).
|
|
33
|
+
- The value labels of `BarPlot`, `BulletPlot`, `PyramidPlot`, `HistogramPlot` and `HeatmapPlot` are the `label` of their own shapes (`bar`, `rect`, `cell`), so they fit them: a label that does not fit is written smaller, cut short, or left out. On those plots `styles.values.anchor` takes the anchors of a shape's label - `'middle'`, `'top'`, `'bottom'`, `'left'`, `'right'`, the corners (`'top-left'`...), and `'tip'` and `'base'`, the end of a bar away from zero and the one on it, on either side of zero - and `'outside'`, beyond the tip, which stays the default. `'start'` and `'end'` are gone from them (they were the top and bottom of the page, or the left and right, whatever the sign); the plots that label a point or the end of a line keep them. `fontStyle.dx` and `dy` now push a label from its anchor rather than replace its gap. A label with `hoverIsolate` still dims the other series and a dimmed series dims its labels. `LabelAnchor` is one type for the anchors of a text marker's `frameAnchor`, a shape's `label` and the plots' `anchor`.
|
|
34
|
+
|
|
35
|
+
- Everything a marker is drawn with now goes in its `styles`, which takes a function of the row for any field: the `stroke`, `strokeWidth` and `strokeOpacity` of `rule` and `arrow` (they took a field key or a function beside `styles`), the `fill` and `fillOpacity` of `text` and the `fill` of `cell`, and the insets - `inset`, `insetLeft`, `insetRight`, `insetTop` and `insetBottom` of `rect`, `bar`, `cell` and `rule`, `inset`, `insetStart` and `insetEnd` of `arrow`. The field keys they took stay, now in `styles`: `styles: { stroke: 'color' }`.
|
|
36
|
+
|
|
37
|
+
## [1.16.0] - 2026-11-04
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- A timeline tweened with `interpolate` is at its last step once `progress` comes within `timeline.snap` (default `1e-4`, a ten-thousandth of the span; `0` turns it off) of it. A scrubber that stops a hair short of `1` - a scrolled step ends at `0.97` - drew the line all the way to the end with its easing, but left out the last row: its dot, and a marker like a `delta` placed on it.
|
|
42
|
+
|
|
5
43
|
## [1.15.0] - 2026-11-04
|
|
6
44
|
|
|
7
45
|
### Fixed
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getConfiguration, configToCssVars, cssVarsRule } from './config.svelte';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The configuration's `--dct-*` custom properties, as one rule on the document root rather than on each element
|
|
6
|
+
* that reads them: an author's own rule - on a wrapping element too - overrides them.
|
|
7
|
+
*/
|
|
8
|
+
const rule = $derived(cssVarsRule(configToCssVars(getConfiguration())));
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<svelte:head>
|
|
12
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
13
|
+
{@html `<style data-dct-config>${rule}</style>`}
|
|
14
|
+
</svelte:head>
|
|
@@ -8,5 +8,10 @@ export declare function setConfiguration(patch: PlotStylesConfigInput): PlotStyl
|
|
|
8
8
|
export declare function resetConfiguration(): void;
|
|
9
9
|
/** Flatten a config into the `--dct-*` custom properties used by the styles. */
|
|
10
10
|
export declare function configToCssVars(c: PlotStylesConfig): Record<string, string>;
|
|
11
|
+
/**
|
|
12
|
+
* A CSS-vars record as one rule on the document root, with no specificity (`:where(:root)`): every element inherits
|
|
13
|
+
* them, and any rule of the author's that sets one - on a wrapping element too - wins over it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function cssVarsRule(vars: Record<string, string>): string;
|
|
11
16
|
/** Serialize a CSS-vars record into a `style` attribute string. */
|
|
12
17
|
export declare function cssVarsStyle(vars: Record<string, string>): string;
|
|
@@ -61,7 +61,7 @@ export const DEFAULT_CONFIG = {
|
|
|
61
61
|
palette: Palette.resolve('tableau10'),
|
|
62
62
|
symbols: ['circle', 'square', 'triangle', 'diamond', 'star', 'cross'],
|
|
63
63
|
// A light tint of the palette's first color up to the color itself.
|
|
64
|
-
continuous: { min: '#eaf0f6', max: '#4e79a7',
|
|
64
|
+
continuous: { min: '#eaf0f6', max: '#4e79a7', opacityRange: [0.2, 1] },
|
|
65
65
|
margins: { top: 'auto', right: 'auto', bottom: 'auto', left: 'auto' },
|
|
66
66
|
frameClip: { tolerance: 2 },
|
|
67
67
|
// ── Features ────────────────────────────────────────────────────────────────
|
|
@@ -179,11 +179,19 @@ export const DEFAULT_CONFIG = {
|
|
|
179
179
|
disabledOpacity: 0.3
|
|
180
180
|
}
|
|
181
181
|
},
|
|
182
|
+
treemap: {
|
|
183
|
+
stroke: '#ffffff',
|
|
184
|
+
strokeWidth: 1.5,
|
|
185
|
+
fontSize: 12,
|
|
186
|
+
padding: 4,
|
|
187
|
+
lineHeight: 1.2
|
|
188
|
+
},
|
|
182
189
|
timeline: {
|
|
183
190
|
axisColor: 'currentColor',
|
|
184
191
|
activeColor: '#4e79a7',
|
|
185
192
|
thickness: 60,
|
|
186
193
|
gap: '12px',
|
|
194
|
+
snap: 1e-4,
|
|
187
195
|
rule: {
|
|
188
196
|
fontSize: 12,
|
|
189
197
|
activeFontSize: 20,
|
|
@@ -247,6 +255,7 @@ export const DEFAULT_CONFIG = {
|
|
|
247
255
|
}
|
|
248
256
|
},
|
|
249
257
|
text: {
|
|
258
|
+
label: { gap: 4, padding: 4, minFontSize: 8, minLetters: 3, contrast: ['#ffffff', '#111827'] },
|
|
250
259
|
declutter: {
|
|
251
260
|
elbowGap: 10,
|
|
252
261
|
laneStep: 7,
|
|
@@ -362,9 +371,6 @@ export function configToCssVars(c) {
|
|
|
362
371
|
'--dct-divider-style': c.divider.style,
|
|
363
372
|
'--dct-divider-margin': c.divider.margin,
|
|
364
373
|
'--dct-row-gap': c.chrome.rowGap,
|
|
365
|
-
'--dct-heat-min': c.continuous.min,
|
|
366
|
-
'--dct-heat-max': c.continuous.max,
|
|
367
|
-
'--dct-heat-text': c.continuous.labelColor,
|
|
368
374
|
'--dct-axis-color': c.axis.color,
|
|
369
375
|
'--dct-legend-font': c.legend.font,
|
|
370
376
|
'--dct-legend-size': c.legend.size,
|
|
@@ -439,6 +445,14 @@ export function configToCssVars(c) {
|
|
|
439
445
|
'--dct-player-toggle-pad': c.timeline.player.toggle.padding
|
|
440
446
|
};
|
|
441
447
|
}
|
|
448
|
+
/**
|
|
449
|
+
* A CSS-vars record as one rule on the document root, with no specificity (`:where(:root)`): every element inherits
|
|
450
|
+
* them, and any rule of the author's that sets one - on a wrapping element too - wins over it.
|
|
451
|
+
*/
|
|
452
|
+
export function cssVarsRule(vars) {
|
|
453
|
+
// A value never closes the `<style>` it is written in.
|
|
454
|
+
return `:where(:root){${cssVarsStyle(vars).replace(/</g, '')}}`;
|
|
455
|
+
}
|
|
442
456
|
/** Serialize a CSS-vars record into a `style` attribute string. */
|
|
443
457
|
export function cssVarsStyle(vars) {
|
|
444
458
|
return Object.entries(vars)
|
|
@@ -9,7 +9,7 @@ export const DARK_THEME = {
|
|
|
9
9
|
caption: { color: '#94a3b8' },
|
|
10
10
|
legend: { gap: '0.5rem 1.5rem', swatchSize: '1rem' },
|
|
11
11
|
palette: ['#38bdf8', '#f472b6', '#a3e635', '#fbbf24', '#c084fc'],
|
|
12
|
-
continuous: { min: '#1e293b', max: '#38bdf8'
|
|
12
|
+
continuous: { min: '#1e293b', max: '#38bdf8' },
|
|
13
13
|
axis: { color: '#94a3b8', fontSize: 13, xTickSize: 6, yTickSize: 6 },
|
|
14
14
|
tooltip: { background: '#e5e7eb', color: '#0f172a' },
|
|
15
15
|
facet: {
|
|
@@ -6,7 +6,7 @@ export const EDITORIAL_THEME = {
|
|
|
6
6
|
subtitle: { color: '#8a6d3b', size: '1.05rem' },
|
|
7
7
|
caption: { color: '#8a6d3b' },
|
|
8
8
|
palette: ['#9b2226', '#606c38', '#6a4c93', '#ee9b00', '#005f73'],
|
|
9
|
-
continuous: { min: '#fff3e0', max: '#bb3e03'
|
|
9
|
+
continuous: { min: '#fff3e0', max: '#bb3e03' },
|
|
10
10
|
axis: { color: '#8a6d3b', fontSize: 13, xTickSize: 6, yTickSize: 6 },
|
|
11
11
|
line: { strokeWidth: 5, dotRadius: 5 },
|
|
12
12
|
timeline: { activeColor: '#bb3e03', axisColor: '#8a6d3b', thickness: 60 },
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export { default as PyramidPlot } from './plots/distribution/pyramid/Plot.svelte
|
|
|
15
15
|
export { default as ScatterPlot } from './plots/correlation/scatter/Plot.svelte';
|
|
16
16
|
export { default as SlopePlot } from './plots/evolution/slope/Plot.svelte';
|
|
17
17
|
export { default as SparklinePlot } from './plots/evolution/sparkline/Plot.svelte';
|
|
18
|
+
export { default as TreemapPlot } from './plots/part-of-a-whole/treemap/Plot.svelte';
|
|
18
19
|
export { default as ViolinPlot } from './plots/distribution/violin/Plot.svelte';
|
|
19
20
|
export { default as PlotComposer } from './layout/composer/PlotComposer.svelte';
|
|
20
21
|
export { default as GridCell } from './layout/grid/GridCell.svelte';
|
|
@@ -23,7 +24,7 @@ export { default as BasePlotLayout } from './layout/base/BasePlotLayout.svelte';
|
|
|
23
24
|
export { usePlot, useFigure } from './layout/plot/usePlot';
|
|
24
25
|
export type { PublicPlotContext, PublicFigureContext, PublicHover, PublicPlotHover, PublicLegend, PublicTimeline } from './layout/plot/PublicPlotContext';
|
|
25
26
|
export { argentinaBicontinental } from './layout/coordinates/projections/argentina';
|
|
26
|
-
export { setConfiguration, getConfiguration, resetConfiguration, configToCssVars, cssVarsStyle, DEFAULT_CONFIG } from './configuration/config.svelte';
|
|
27
|
+
export { setConfiguration, getConfiguration, resetConfiguration, configToCssVars, cssVarsStyle, cssVarsRule, DEFAULT_CONFIG } from './configuration/config.svelte';
|
|
27
28
|
export { THEMES } from './configuration/themes';
|
|
28
29
|
export { SYSTEM_FONT } from './configuration/fonts';
|
|
29
30
|
export type { ThemeName } from './configuration/themes';
|
|
@@ -33,10 +34,12 @@ export { Margins } from './layout/margins/Margins';
|
|
|
33
34
|
export { resolveOpacityScale } from './utils/OpacityScale';
|
|
34
35
|
export { resolveSymbolScale } from './utils/SymbolScale';
|
|
35
36
|
export { Statistics } from './phases/statistics/Statistics';
|
|
36
|
-
export type { AxisValue, ChannelValue, ChannelName, AxisChannelName, IndependentChannelName, SizeChannelName, ChannelAccessors } from './types/layout/mapping';
|
|
37
|
+
export type { AxisValue, ChannelValue, ChannelName, AxisChannelName, IndependentChannelName, SizeChannelName, ChannelAccessors, GroupingAccessor } from './types/layout/mapping';
|
|
37
38
|
export type { AxisScale, AxisBasedScalesConfig, ChannelScalesConfig } from './types/layout/scales';
|
|
38
39
|
export type { NumberDisplay } from './types/layout/numbers';
|
|
39
|
-
export type {
|
|
40
|
+
export type { TreemapPlotProps, TreemapTooltipContext } from './types/plots/part-of-a-whole/treemap/props';
|
|
41
|
+
export type { TreemapTile } from './types/transforms/treemap';
|
|
42
|
+
export type { Accessor, Series, SeriesProps, NonAxisDataProps, SingleAxisDataProps, DualAxisDataProps } from './types/plots/data/common';
|
|
40
43
|
export type { BasePlotProps, PlotCoreProps, PlotChromeProps, FigureBoxProps, SegmentsConfig, ScalesConfig, MarginConfig, TooltipConfig, HoverConfig } from './types/plots/props';
|
|
41
44
|
export type { AxisBasedStylesConfig, ConnectorBasedStylesConfig, BulletStylesConfig, GapsAwarePlotStylesConfig, CurveAwarePlotStylesConfig, GeoStylesConfig, GeoTileLayerConfig } from './types/layout/styles';
|
|
42
45
|
export type { GapsConfig } from './types/plots/gaps';
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ export { default as PyramidPlot } from './plots/distribution/pyramid/Plot.svelte
|
|
|
18
18
|
export { default as ScatterPlot } from './plots/correlation/scatter/Plot.svelte';
|
|
19
19
|
export { default as SlopePlot } from './plots/evolution/slope/Plot.svelte';
|
|
20
20
|
export { default as SparklinePlot } from './plots/evolution/sparkline/Plot.svelte';
|
|
21
|
+
export { default as TreemapPlot } from './plots/part-of-a-whole/treemap/Plot.svelte';
|
|
21
22
|
export { default as ViolinPlot } from './plots/distribution/violin/Plot.svelte';
|
|
22
23
|
// ── Composition ─────────────────────────────────────────────────────────────
|
|
23
24
|
// Separate plots combined into one figure, with chrome of its own.
|
|
@@ -29,7 +30,7 @@ export { default as BasePlotLayout } from './layout/base/BasePlotLayout.svelte';
|
|
|
29
30
|
export { usePlot, useFigure } from './layout/plot/usePlot';
|
|
30
31
|
// Custom geo projections - usable as `scales.projection.type`.
|
|
31
32
|
export { argentinaBicontinental } from './layout/coordinates/projections/argentina';
|
|
32
|
-
export { setConfiguration, getConfiguration, resetConfiguration, configToCssVars, cssVarsStyle, DEFAULT_CONFIG } from './configuration/config.svelte';
|
|
33
|
+
export { setConfiguration, getConfiguration, resetConfiguration, configToCssVars, cssVarsStyle, cssVarsRule, DEFAULT_CONFIG } from './configuration/config.svelte';
|
|
33
34
|
export { THEMES } from './configuration/themes';
|
|
34
35
|
export { SYSTEM_FONT } from './configuration/fonts';
|
|
35
36
|
// ── Utils ─────────────────────────────────────────────────────────────────────
|
|
@@ -317,7 +317,7 @@
|
|
|
317
317
|
<div
|
|
318
318
|
class="dct-plot"
|
|
319
319
|
bind:this={containerEl}
|
|
320
|
-
style:color={cfg.axis.color}
|
|
320
|
+
style:color={`var(--dct-axis-color, ${cfg.axis.color})`}
|
|
321
321
|
style:touch-action={touchAction}
|
|
322
322
|
onpointermove={hover.active ? onMove : undefined}
|
|
323
323
|
onpointerleave={hover.active ? ctrl.onLeave : undefined}
|
|
@@ -6,11 +6,8 @@
|
|
|
6
6
|
import TimelineRule from '../timeline/TimelineRule.svelte';
|
|
7
7
|
import { TimelineState } from '../timeline/TimelineState.svelte';
|
|
8
8
|
import { GridCellsRegistry } from '../grid/GridCellsRegistry.svelte';
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
configToCssVars,
|
|
12
|
-
cssVarsStyle
|
|
13
|
-
} from '../../configuration/config.svelte';
|
|
9
|
+
import ConfigVars from '../../configuration/ConfigVars.svelte';
|
|
10
|
+
import { getConfiguration } from '../../configuration/config.svelte';
|
|
14
11
|
import { HoverState } from '../hover/HoverState.svelte';
|
|
15
12
|
import { LegendState } from '../legend/LegendState.svelte';
|
|
16
13
|
import { LegendLabels } from '../legend/LegendLabels';
|
|
@@ -165,18 +162,14 @@
|
|
|
165
162
|
plot={body}
|
|
166
163
|
/>
|
|
167
164
|
{:else}
|
|
168
|
-
|
|
169
|
-
<div
|
|
170
|
-
style={cssVarsStyle(configToCssVars(cfg))}
|
|
171
|
-
style:font-family="var(--dct-font, inherit)"
|
|
172
|
-
style:width="{w}px"
|
|
173
|
-
style:height="{h}px"
|
|
174
|
-
>
|
|
165
|
+
<div style:font-family="var(--dct-font, inherit)" style:width="{w}px" style:height="{h}px">
|
|
175
166
|
{@render body({ width: w, height: h })}
|
|
176
167
|
</div>
|
|
177
168
|
{/if}
|
|
178
169
|
{/snippet}
|
|
179
170
|
|
|
171
|
+
<ConfigVars />
|
|
172
|
+
|
|
180
173
|
{#if grid}
|
|
181
174
|
<GridCell class="dct-grid-cell--figure" {area} {inset}>
|
|
182
175
|
{#snippet children(cell)}
|
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { PlotBoxSnippet } from '../../types/layout/figure';
|
|
4
4
|
import type { PlotChromeEntry, PlotChromeItem } from '../../types/plots/props';
|
|
5
|
-
import {
|
|
6
|
-
getConfiguration,
|
|
7
|
-
configToCssVars,
|
|
8
|
-
cssVarsStyle
|
|
9
|
-
} from '../../configuration/config.svelte';
|
|
5
|
+
import { getConfiguration } from '../../configuration/config.svelte';
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
* A figure's chrome - a plot's or a composer's - drawn by its `Figure`. It owns the fixed footprint (`width`/`height`),
|
|
@@ -175,10 +171,6 @@
|
|
|
175
171
|
|
|
176
172
|
let bodyWidth = $state(0);
|
|
177
173
|
let bodyHeight = $state(0);
|
|
178
|
-
|
|
179
|
-
// Stamp every `--dct-*` custom property on the root so the scoped styles below
|
|
180
|
-
// (and any nested plot/legend/timeline) resolve them from the live config.
|
|
181
|
-
const themeStyle = $derived(cssVarsStyle(configToCssVars(getConfiguration())));
|
|
182
174
|
</script>
|
|
183
175
|
|
|
184
176
|
{#snippet cell(block: Cell)}
|
|
@@ -217,7 +209,7 @@
|
|
|
217
209
|
{/if}
|
|
218
210
|
{/snippet}
|
|
219
211
|
|
|
220
|
-
<div class="dct-figure-chrome" style
|
|
212
|
+
<div class="dct-figure-chrome" style:width="{width}px" style:height="{height}px">
|
|
221
213
|
{#each blocks as block (block.key)}
|
|
222
214
|
{#if block.type === 'divider'}
|
|
223
215
|
<hr class="dct-figure-chrome__divider" />
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
import ContourMarker from '../../markers/contour/ContourMarker.svelte';
|
|
40
40
|
import ContourClipMarker from '../../markers/contour/ContourClipMarker.svelte';
|
|
41
41
|
import InsetMarker from '../../markers/inset/InsetMarker.svelte';
|
|
42
|
+
import MarkerLabel from '../../markers/utils/MarkerLabel.svelte';
|
|
42
43
|
import FrameClip from './FrameClip.svelte';
|
|
43
44
|
import MarkerOffset from './MarkerOffset.svelte';
|
|
44
45
|
import { getConfiguration } from '../../configuration/config.svelte';
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
import { PlotMargins } from '../margins/PlotMargins.svelte';
|
|
47
48
|
import type { Series } from '../../types/plots/data/common';
|
|
48
49
|
import type { MarkerConfig } from '../../types/markers/all';
|
|
50
|
+
import type { CommonMarkerEvents } from '../../types/markers/channels/commonMarkerEvents';
|
|
49
51
|
import type { TooltipAnchorX, TooltipAnchorY } from '../../types/layout/tooltip';
|
|
50
52
|
import type { PlotHover } from '../hover/PlotHover.svelte';
|
|
51
53
|
import type { ScopedMarkerGroup } from '../../types/layout/geometry';
|
|
@@ -127,6 +129,32 @@
|
|
|
127
129
|
if (marker.type === 'bar') return `bar-${marker.role}-${i}`;
|
|
128
130
|
return `${marker.type}-${i}`;
|
|
129
131
|
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A marker with `hover: true`, with the plot's hover added to its own pointer handlers: entering or moving
|
|
135
|
+
* over any of its shapes hovers its rows - as they are drawn now, should the plot have been laid out again
|
|
136
|
+
* under a resting pointer - and leaving it ends the hover.
|
|
137
|
+
*/
|
|
138
|
+
function withHover(marker: MarkerConfig, rows: TData[] | TSeries[]): MarkerConfig {
|
|
139
|
+
if (!('hover' in marker) || marker.hover !== true) return marker;
|
|
140
|
+
const own = marker as CommonMarkerEvents & { data?: unknown[] };
|
|
141
|
+
const hovered = (own.data ?? rows) as TData[];
|
|
142
|
+
return {
|
|
143
|
+
...marker,
|
|
144
|
+
onpointerenter: (event: Event, row: unknown, index: number) => {
|
|
145
|
+
own.onpointerenter?.(event, row, index);
|
|
146
|
+
ctrl.onPointer(hovered);
|
|
147
|
+
},
|
|
148
|
+
onpointerleave: (event: Event, row: unknown, index: number) => {
|
|
149
|
+
own.onpointerleave?.(event, row, index);
|
|
150
|
+
ctrl.onLeave();
|
|
151
|
+
},
|
|
152
|
+
onpointermove: (event: Event, row: unknown, index: number) => {
|
|
153
|
+
own.onpointermove?.(event, row, index);
|
|
154
|
+
ctrl.onPointer(hovered);
|
|
155
|
+
}
|
|
156
|
+
} as MarkerConfig;
|
|
157
|
+
}
|
|
130
158
|
</script>
|
|
131
159
|
|
|
132
160
|
{#snippet drawMarker(marker: MarkerConfig, rows: TData[] | TSeries[])}
|
|
@@ -237,7 +265,7 @@
|
|
|
237
265
|
|
|
238
266
|
{#snippet renderMarker(marker: MarkerConfig, rows: TData[] | TSeries[])}
|
|
239
267
|
<MarkerOffset {marker}>
|
|
240
|
-
{@render drawMarker(marker, rows)}
|
|
268
|
+
{@render drawMarker(withHover(marker, rows), rows)}
|
|
241
269
|
</MarkerOffset>
|
|
242
270
|
{/snippet}
|
|
243
271
|
|
|
@@ -299,3 +327,16 @@
|
|
|
299
327
|
{@render renderScoped(marker, groupByName.get(scope)!)}
|
|
300
328
|
{/if}
|
|
301
329
|
{/each}
|
|
330
|
+
|
|
331
|
+
<!--
|
|
332
|
+
The labels the shapes write in themselves, after every marker - the hover's hit areas too, which are the last of them -
|
|
333
|
+
so a label that listens for the pointer is not covered, and one outside its shape is not clipped with it.
|
|
334
|
+
-->
|
|
335
|
+
{#each markers as marker, i (markerKey(marker, i))}
|
|
336
|
+
{@const scope = scopedSeriesOf(marker)}
|
|
337
|
+
{#if 'label' in marker && marker.label && (scope === undefined || groupByName.has(scope))}
|
|
338
|
+
<MarkerOffset {marker}>
|
|
339
|
+
<MarkerLabel marker={{ ...marker, data: marker.data ?? data }} />
|
|
340
|
+
</MarkerOffset>
|
|
341
|
+
{/if}
|
|
342
|
+
{/each}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TooltipProp } from '../../types/layout/tooltip';
|
|
1
|
+
import type { TooltipContext, TooltipProp } from '../../types/layout/tooltip';
|
|
2
2
|
import type { HoverPoint, HoverStrategy } from '../../types/layout/hover';
|
|
3
3
|
import { PlotAxes } from '../../phases/data/PlotAxes';
|
|
4
4
|
import type { HoverConfig, PointMatchingStrategy, TooltipConfig } from '../../types/plots/props';
|
|
@@ -31,5 +31,7 @@ export declare class HoverSettings<TRow extends Record<string, unknown>> {
|
|
|
31
31
|
defaultStrategy: HoverStrategy;
|
|
32
32
|
pointMatching?: PointMatchingStrategy;
|
|
33
33
|
number?: (value: number) => string;
|
|
34
|
+
/** What the plot knows of a row, the third argument of the author's own `format` - see {@link TooltipContext}. */
|
|
35
|
+
context?: (row: TRow) => TooltipContext;
|
|
34
36
|
}): HoverConfig<TRow>;
|
|
35
37
|
}
|
|
@@ -33,7 +33,7 @@ export class HoverSettings {
|
|
|
33
33
|
}
|
|
34
34
|
/** A plot's `hover` config; its tooltip reads as `format` unless it sets its own. */
|
|
35
35
|
static buildConfig(args) {
|
|
36
|
-
const { tooltip, format, sort, markers, points, label, defaultStrategy, pointMatching } = args;
|
|
36
|
+
const { tooltip, format, sort, markers, points, label, defaultStrategy, pointMatching, context } = args;
|
|
37
37
|
const number = args.number ?? String;
|
|
38
38
|
const settings = new HoverSettings(tooltip, markers, defaultStrategy);
|
|
39
39
|
return {
|
|
@@ -44,7 +44,9 @@ export class HoverSettings {
|
|
|
44
44
|
sync: settings.sync,
|
|
45
45
|
tooltip: tooltip && {
|
|
46
46
|
...tooltip,
|
|
47
|
-
format: tooltip.format
|
|
47
|
+
format: tooltip.format
|
|
48
|
+
? (row) => tooltip.format(row, number, context?.(row) ?? {})
|
|
49
|
+
: format,
|
|
48
50
|
...(sort ? { sort } : {})
|
|
49
51
|
},
|
|
50
52
|
...(pointMatching ? { pointMatching } : {})
|
|
@@ -6,7 +6,7 @@ import type { DotStyle, StrokeStyle } from '../../types/plots/styling';
|
|
|
6
6
|
* a call site slots it in as one more `??` layer ahead of its own style chain.
|
|
7
7
|
*/
|
|
8
8
|
export declare class DisabledStyle {
|
|
9
|
-
/** The style `action` draws a mark with - `'hide'` and `'
|
|
9
|
+
/** The style `action` draws a mark with - `'hide'`, `'omit'` and `'rescale'` are fully transparent. */
|
|
10
10
|
static of(action: LegendDisabledAction | undefined, fallbackOpacity: number): LegendDisabledStyle | undefined;
|
|
11
11
|
/** The style a legend item draws with while off - it stays visible, so it can be turned back on. */
|
|
12
12
|
static ofItem(action: LegendDisabledAction | undefined, fallbackOpacity: number): LegendDisabledStyle | undefined;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* a call site slots it in as one more `??` layer ahead of its own style chain.
|
|
5
5
|
*/
|
|
6
6
|
export class DisabledStyle {
|
|
7
|
-
/** The style `action` draws a mark with - `'hide'` and `'
|
|
7
|
+
/** The style `action` draws a mark with - `'hide'`, `'omit'` and `'rescale'` are fully transparent. */
|
|
8
8
|
static of(action, fallbackOpacity) {
|
|
9
9
|
if (!action)
|
|
10
10
|
return undefined;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
/**
|
|
9
9
|
* The `interactive.legendStyle: 'badge'` item look: a pill with the series
|
|
10
10
|
* color, symbol icon, label, and a toggle icon - an eye (crossed out when
|
|
11
|
-
* `disabled`) for `'dim'` and `'hide'`, or a plus/cross pair for `'omit'`.
|
|
11
|
+
* `disabled`) for `'dim'` and `'hide'`, or a plus/cross pair for `'omit'` and `'rescale'`.
|
|
12
12
|
*/
|
|
13
13
|
let {
|
|
14
14
|
item,
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
{#snippet discreteItem(item: LegendItem, i: number)}
|
|
162
162
|
{@const action = interaction.actionOf(item.name)}
|
|
163
163
|
{@const isDisabled = action != null}
|
|
164
|
-
{@const omitMode = (action ?? disabledAction).mode
|
|
164
|
+
{@const omitMode = ['omit', 'rescale'].includes((action ?? disabledAction).mode)}
|
|
165
165
|
{@const disabledStyle = DisabledStyle.ofItem(action, cfg.legend.disabledOpacity)}
|
|
166
166
|
{@const color =
|
|
167
167
|
disabledStyle?.fill ??
|
|
@@ -48,12 +48,22 @@ export declare class LegendState {
|
|
|
48
48
|
* off any other way, is left alone.
|
|
49
49
|
*/
|
|
50
50
|
setOff(targets: Map<string, LegendDisabledAction>): void;
|
|
51
|
-
/** Whether any series is off with `'omit'` - which
|
|
51
|
+
/** Whether any series is off with `'omit'` or `'rescale'` - which change the plot's own rows, not just how they draw. */
|
|
52
52
|
get omits(): boolean;
|
|
53
|
-
/** `series` without those turned off with `'omit'`. */
|
|
53
|
+
/** `series` without those turned off with `'omit'` or `'rescale'`. */
|
|
54
54
|
withoutOmitted<S extends {
|
|
55
55
|
name: string;
|
|
56
56
|
}>(series: S[]): S[];
|
|
57
|
+
/**
|
|
58
|
+
* The series of `series` taken out of the plot's rows, and how: `'omit'` or `'rescale'` - one mode for every
|
|
59
|
+
* series of a plot, as its legend sets it. `undefined` while none is.
|
|
60
|
+
*/
|
|
61
|
+
removed<S extends {
|
|
62
|
+
name: string;
|
|
63
|
+
}>(series: S[]): {
|
|
64
|
+
mode: 'omit' | 'rescale';
|
|
65
|
+
series: S[];
|
|
66
|
+
} | undefined;
|
|
57
67
|
/**
|
|
58
68
|
* Records what the plot `source` draws, replacing what it recorded before.
|
|
59
69
|
* A series or mark that is off keeps its entry, in its place, even when
|
|
@@ -119,13 +119,27 @@ export class LegendState {
|
|
|
119
119
|
this.#managed = new SvelteMap(targets);
|
|
120
120
|
});
|
|
121
121
|
}
|
|
122
|
-
/** Whether any series is off with `'omit'` - which
|
|
122
|
+
/** Whether any series is off with `'omit'` or `'rescale'` - which change the plot's own rows, not just how they draw. */
|
|
123
123
|
get omits() {
|
|
124
|
-
return [...this.disabled.values()].some(
|
|
124
|
+
return [...this.disabled.values()].some(LegendState.#removes);
|
|
125
125
|
}
|
|
126
|
-
/** `series` without those turned off with `'omit'`. */
|
|
126
|
+
/** `series` without those turned off with `'omit'` or `'rescale'`. */
|
|
127
127
|
withoutOmitted(series) {
|
|
128
|
-
return series.filter((s) => this.actionOf(s.name)
|
|
128
|
+
return series.filter((s) => !LegendState.#removes(this.actionOf(s.name)));
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The series of `series` taken out of the plot's rows, and how: `'omit'` or `'rescale'` - one mode for every
|
|
132
|
+
* series of a plot, as its legend sets it. `undefined` while none is.
|
|
133
|
+
*/
|
|
134
|
+
removed(series) {
|
|
135
|
+
const off = series.filter((s) => LegendState.#removes(this.actionOf(s.name)));
|
|
136
|
+
if (!off.length)
|
|
137
|
+
return undefined;
|
|
138
|
+
return { mode: this.actionOf(off[0].name).mode, series: off };
|
|
139
|
+
}
|
|
140
|
+
/** Whether `action` takes a series out of the plot's rows. */
|
|
141
|
+
static #removes(action) {
|
|
142
|
+
return action?.mode === 'omit' || action?.mode === 'rescale';
|
|
129
143
|
}
|
|
130
144
|
/**
|
|
131
145
|
* Records what the plot `source` draws, replacing what it recorded before.
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { PlotStylesConfig } from '../../types/configuration/styling';
|
|
2
2
|
/** How a legend shows the names it reads off the data. */
|
|
3
3
|
export declare class LegendText {
|
|
4
|
+
#private;
|
|
4
5
|
/** `name` as the legend shows it: as words, unless `legend.pretty` is off. */
|
|
5
6
|
static of(name: string, cfg: Pick<PlotStylesConfig, 'legend'>): string;
|
|
6
7
|
/**
|
|
7
8
|
* A field or category name as words: `_` and camel-case humps split it,
|
|
8
9
|
* all lowercase but the first letter - `gdp_per_capita` and `gdpPerCapita`
|
|
9
|
-
* both read "Gdp per capita". All-caps words (acronyms) keep their case.
|
|
10
|
+
* both read "Gdp per capita". All-caps words (acronyms) keep their case. The
|
|
11
|
+
* levels of a series grouped by several (`'Americas.Argentina'`) are made
|
|
12
|
+
* words each.
|
|
10
13
|
*/
|
|
11
14
|
static humanize(name: string): string;
|
|
12
15
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Grouping } from '../../utils/grouping';
|
|
1
2
|
/** How a legend shows the names it reads off the data. */
|
|
2
3
|
export class LegendText {
|
|
3
4
|
/** `name` as the legend shows it: as words, unless `legend.pretty` is off. */
|
|
@@ -7,9 +8,14 @@ export class LegendText {
|
|
|
7
8
|
/**
|
|
8
9
|
* A field or category name as words: `_` and camel-case humps split it,
|
|
9
10
|
* all lowercase but the first letter - `gdp_per_capita` and `gdpPerCapita`
|
|
10
|
-
* both read "Gdp per capita". All-caps words (acronyms) keep their case.
|
|
11
|
+
* both read "Gdp per capita". All-caps words (acronyms) keep their case. The
|
|
12
|
+
* levels of a series grouped by several (`'Americas.Argentina'`) are made
|
|
13
|
+
* words each.
|
|
11
14
|
*/
|
|
12
15
|
static humanize(name) {
|
|
16
|
+
return name.split(Grouping.SEPARATOR).map(LegendText.#words).join(Grouping.SEPARATOR);
|
|
17
|
+
}
|
|
18
|
+
static #words(name) {
|
|
13
19
|
const words = name
|
|
14
20
|
.replace(/_+/g, ' ')
|
|
15
21
|
.replace(/([a-z\d])([A-Z])/g, '$1 $2')
|
|
@@ -56,7 +56,7 @@ export declare class PlotMargins {
|
|
|
56
56
|
/**
|
|
57
57
|
* Measures `el`'s rendered box once its readings settle - again whenever
|
|
58
58
|
* the plot's area or `deps` change - and reports how far it reaches past
|
|
59
|
-
* that area: to `
|
|
59
|
+
* that area: to `onoverflow`, and, when `grow` holds, into the room the
|
|
60
60
|
* margins grow by. The area is where svelteplot draws the marks (see
|
|
61
61
|
* {@link follow}), not the {@link contentBox}'s estimate: an `'auto'` side
|
|
62
62
|
* is only its estimate until svelteplot sizes its axes, and what a label
|
|
@@ -64,7 +64,7 @@ export declare class PlotMargins {
|
|
|
64
64
|
*/
|
|
65
65
|
watch(el: () => SVGGraphicsElement | undefined, options: {
|
|
66
66
|
grow?: () => boolean;
|
|
67
|
-
|
|
67
|
+
onoverflow?: (overflow: Margins) => void;
|
|
68
68
|
deps?: () => unknown;
|
|
69
69
|
}): void;
|
|
70
70
|
/** Grows the labels' room to fit what reached `overflow` px past the content box. */
|
|
@@ -57,7 +57,7 @@ export class PlotMargins {
|
|
|
57
57
|
/**
|
|
58
58
|
* Measures `el`'s rendered box once its readings settle - again whenever
|
|
59
59
|
* the plot's area or `deps` change - and reports how far it reaches past
|
|
60
|
-
* that area: to `
|
|
60
|
+
* that area: to `onoverflow`, and, when `grow` holds, into the room the
|
|
61
61
|
* margins grow by. The area is where svelteplot draws the marks (see
|
|
62
62
|
* {@link follow}), not the {@link contentBox}'s estimate: an `'auto'` side
|
|
63
63
|
* is only its estimate until svelteplot sizes its axes, and what a label
|
|
@@ -92,7 +92,7 @@ export class PlotMargins {
|
|
|
92
92
|
frame = requestAnimationFrame(measure);
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
|
-
options.
|
|
95
|
+
options.onoverflow?.(overflow);
|
|
96
96
|
if (options.grow?.())
|
|
97
97
|
this.reportOverflow(overflow);
|
|
98
98
|
};
|
|
@@ -74,7 +74,8 @@
|
|
|
74
74
|
slice?: (cell: PlotCellContext<TRow, TScales>) => TCore;
|
|
75
75
|
cell?: PlotCellSnippet<TRow, TScales>;
|
|
76
76
|
margins?: MarginConfig;
|
|
77
|
-
tooltip
|
|
77
|
+
/** The plot's `tooltip`, whose `format` gets whatever context its kind gives. */
|
|
78
|
+
tooltip?: TooltipProp<TRow, never>;
|
|
78
79
|
/** The rows `timeline` and `facet` slice. Defaults to `core.data`. */
|
|
79
80
|
data?: TRow[];
|
|
80
81
|
width?: number;
|
|
@@ -89,7 +90,8 @@
|
|
|
89
90
|
const pipeline = $derived(defaults ? Pipeline.of(defaults()) : undefined);
|
|
90
91
|
const hoverSettings = $derived(
|
|
91
92
|
new HoverSettings(
|
|
92
|
-
|
|
93
|
+
// A kind's own context reaches `format` as the hover phase gives it.
|
|
94
|
+
tooltip as TooltipProp<TRow> | undefined,
|
|
93
95
|
markers ?? core?.markers,
|
|
94
96
|
pipeline?.hoverStrategy(core ?? {}, cfg) ?? 'x'
|
|
95
97
|
)
|
|
@@ -14,7 +14,8 @@ declare function $$render<TRow extends Record<string, unknown>, TScales extends
|
|
|
14
14
|
slice?: (cell: PlotCellContext<TRow, TScales>) => TCore;
|
|
15
15
|
cell?: PlotCellSnippet<TRow, TScales>;
|
|
16
16
|
margins?: MarginConfig;
|
|
17
|
-
tooltip
|
|
17
|
+
/** The plot's `tooltip`, whose `format` gets whatever context its kind gives. */
|
|
18
|
+
tooltip?: TooltipProp<TRow, never>;
|
|
18
19
|
/** The rows `timeline` and `facet` slice. Defaults to `core.data`. */
|
|
19
20
|
data?: TRow[];
|
|
20
21
|
width?: number;
|