@fundar/data-chart-telling 1.0.0 → 1.1.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 +21 -0
- package/README.md +57 -18
- package/dist/configuration/config.svelte.js +13 -1
- package/dist/configuration/themes/index.d.ts +124 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/layout/base/BasePlotLayout.svelte +18 -5
- package/dist/layout/hover/HoverSettings.d.ts +20 -6
- package/dist/layout/hover/HoverSettings.js +29 -4
- package/dist/layout/legend/LegendState.svelte.d.ts +5 -0
- package/dist/layout/legend/LegendState.svelte.js +4 -0
- package/dist/layout/plot/Plot.svelte +6 -3
- package/dist/layout/plot/PublicPlotContext.d.ts +5 -4
- package/dist/layout/plot/PublicPlotContext.js +7 -3
- package/dist/layout/plot/Slice.js +4 -2
- package/dist/layout/scales/EdgeTicks.d.ts +39 -0
- package/dist/layout/scales/EdgeTicks.js +82 -0
- package/dist/layout/scales/NiceTicks.d.ts +40 -0
- package/dist/layout/scales/NiceTicks.js +72 -0
- package/dist/layout/scales/ScalesLayout.svelte +64 -30
- package/dist/layout/scales/ScalesLayout.svelte.d.ts +5 -0
- package/dist/layout/scales/SveltePlotScale.d.ts +15 -0
- package/dist/layout/scales/SveltePlotScale.js +79 -0
- package/dist/layout/styles/ValueLabels.js +3 -2
- package/dist/layout/timeline/Timeline.svelte +5 -2
- package/dist/layout/timeline/Timeline.svelte.d.ts +2 -0
- package/dist/layout/timeline/TimelineLayout.svelte +38 -12
- package/dist/layout/timeline/TimelineLayout.svelte.d.ts +7 -5
- package/dist/layout/timeline/TimelineRule.svelte +1 -0
- package/dist/layout/timeline/TimelineState.svelte.d.ts +13 -5
- package/dist/layout/timeline/TimelineState.svelte.js +42 -8
- package/dist/layout/timeline/TimelineTime.d.ts +18 -0
- package/dist/layout/timeline/TimelineTime.js +117 -0
- package/dist/layout/tooltip/Tooltip.svelte +6 -3
- package/dist/layout/tooltip/Tooltip.svelte.d.ts +2 -0
- package/dist/layout/tooltip/TooltipState.svelte.d.ts +8 -2
- package/dist/layout/tooltip/TooltipState.svelte.js +22 -3
- package/dist/markers/delta/DeltaMarker.svelte +9 -7
- package/dist/phases/Pipeline.js +3 -2
- package/dist/phases/data/DataPhase.d.ts +5 -11
- package/dist/phases/data/DataPhase.js +11 -8
- package/dist/phases/facet/FacetPanels.d.ts +54 -0
- package/dist/phases/facet/FacetPanels.js +95 -0
- package/dist/phases/facet/FacetPhase.d.ts +1 -42
- package/dist/phases/facet/FacetPhase.js +1 -87
- package/dist/phases/hover/HoverPhase.d.ts +6 -43
- package/dist/phases/hover/HoverPhase.js +19 -54
- package/dist/phases/mapping/MappingPhase.d.ts +1 -1
- package/dist/phases/mapping/MappingPhase.js +2 -4
- package/dist/phases/scales/ScalesPhase.d.ts +1 -3
- package/dist/phases/scales/ScalesPhase.js +17 -21
- package/dist/phases/sharedScales/SharedScalesPhase.d.ts +4 -1
- package/dist/phases/sharedScales/SharedScalesPhase.js +10 -7
- package/dist/phases/statistics/StatisticsPhase.js +3 -4
- package/dist/phases/tooltip/TooltipPhase.d.ts +4 -2
- package/dist/phases/tooltip/TooltipPhase.js +10 -3
- package/dist/phases/transforms/ProcessedPositions.d.ts +30 -0
- package/dist/phases/transforms/ProcessedPositions.js +74 -0
- package/dist/phases/transforms/TransformsPhase.d.ts +5 -42
- package/dist/phases/transforms/TransformsPhase.js +20 -57
- package/dist/plots/area/markers.js +1 -2
- package/dist/plots/bar/defaults.js +6 -10
- package/dist/plots/bar/markers.js +5 -4
- package/dist/plots/box/BoxSummaries.d.ts +19 -0
- package/dist/plots/box/BoxSummaries.js +101 -0
- package/dist/plots/box/Plot.svelte +42 -0
- package/dist/plots/box/Plot.svelte.d.ts +26 -0
- package/dist/plots/box/defaults.d.ts +12 -0
- package/dist/plots/box/defaults.js +34 -0
- package/dist/plots/box/markers.d.ts +12 -0
- package/dist/plots/box/markers.js +34 -0
- package/dist/plots/geo/phases/hover.js +5 -5
- package/dist/plots/geo/phases/markers.js +3 -4
- package/dist/plots/geo/slices.js +6 -3
- package/dist/plots/heatmap/markers.js +2 -1
- package/dist/plots/histogram/defaults.js +1 -1
- package/dist/plots/histogram/markers.js +4 -4
- package/dist/plots/line/markers.js +1 -2
- package/dist/plots/pyramid/defaults.js +3 -2
- package/dist/plots/pyramid/markers.js +3 -6
- package/dist/plots/scatter/defaults.js +3 -2
- package/dist/plots/scatter/markers.js +4 -3
- package/dist/types/configuration/styling.d.ts +24 -2
- package/dist/types/layout/composer.d.ts +5 -2
- package/dist/types/layout/scales.d.ts +16 -0
- package/dist/types/layout/timeline.d.ts +14 -5
- package/dist/types/phases/hover/phase.d.ts +6 -0
- package/dist/types/phases/state.d.ts +5 -2
- package/dist/types/phases/statistics/phase.d.ts +3 -1
- package/dist/types/phases/transforms/phase.d.ts +10 -0
- package/dist/types/plots/box/props.d.ts +10 -0
- package/dist/types/plots/box/props.js +1 -0
- package/dist/types/plots/box/state.d.ts +23 -0
- package/dist/types/plots/box/state.js +1 -0
- package/dist/types/plots/props.d.ts +2 -0
- package/docs/chrome.md +39 -8
- package/docs/composer.md +19 -3
- package/docs/concepts.md +1 -1
- package/docs/development.md +14 -5
- package/docs/facets.md +62 -8
- package/docs/getting-started.md +8 -9
- package/docs/legend.md +62 -15
- package/docs/markers.md +17 -6
- package/docs/plots.md +168 -42
- package/docs/scales.md +36 -19
- package/docs/state.md +1 -1
- package/docs/styles-and-segments.md +85 -31
- package/docs/theming.md +30 -19
- package/docs/timeline.md +62 -28
- package/docs/tooltip-and-hover.md +72 -24
- package/docs/transforms-and-statistics.md +47 -17
- package/examples/BarValues.svelte +2 -2
- package/examples/Box.svelte +7 -0
- package/examples/Chrome.svelte +17 -0
- package/examples/ChromeOrder.svelte +18 -0
- package/examples/Composer.svelte +23 -0
- package/examples/CustomTooltip.svelte +21 -14
- package/examples/Facets.svelte +3 -3
- package/examples/FacetsCarousel.svelte +14 -0
- package/examples/FacetsRowsCols.svelte +23 -0
- package/examples/FirstPlot.svelte +7 -0
- package/examples/Gaps.svelte +21 -0
- package/examples/GroupedBars.svelte +15 -0
- package/examples/Heatmap.svelte +7 -0
- package/examples/HeatmapSegments.svelte +26 -0
- package/examples/Histogram.svelte +14 -0
- package/examples/HorizontalBars.svelte +15 -0
- package/examples/LegendSections.svelte +27 -0
- package/examples/LegendToggle.svelte +3 -3
- package/examples/LineByRegion.svelte +18 -0
- package/examples/LineDates.svelte +15 -0
- package/examples/Markers.svelte +27 -0
- package/examples/MovingAverage.svelte +15 -0
- package/examples/Pyramid.svelte +7 -0
- package/examples/Regression.svelte +14 -0
- package/examples/ResponsiveLine.svelte +7 -7
- package/examples/Scales.svelte +26 -0
- package/examples/Scatter.svelte +16 -0
- package/examples/SegmentHighlight.svelte +22 -0
- package/examples/Segments.svelte +11 -3
- package/examples/SegmentsBySeries.svelte +25 -0
- package/examples/StackedArea.svelte +16 -0
- package/examples/StackedBars.svelte +15 -0
- package/examples/TimelinePlayer.svelte +8 -7
- package/examples/TimelineRule.svelte +19 -0
- package/examples/Tooltip.svelte +3 -3
- package/examples/ValueLabels.svelte +21 -0
- package/examples/data.ts +320 -8
- package/llms-full.txt +33 -5
- package/llms.txt +30 -2
- package/package.json +3 -2
- package/dist/layout/scales/buildScale.d.ts +0 -8
- package/dist/layout/scales/buildScale.js +0 -67
- package/dist/layout/scales/niceDomain.d.ts +0 -23
- package/dist/layout/scales/niceDomain.js +0 -59
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
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.1.0] - 2026-10-20
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `BoxPlot`, a new plot kind for the distribution of values per category. It draws one box per category of each series: the quartiles, the median, whiskers that reach the farthest values within 1.5 times the interquartile range, and the values past them as outlier dots.
|
|
10
|
+
- Boxes stand upright when the categories are on `x` and lie sideways when they are on `y`.
|
|
11
|
+
- `grouping` or `color` gives each group its own box and color, and `facet` compares groups in separate panels.
|
|
12
|
+
- The tooltip reads one box at a time instead of every value inside it. The hovered row carries `category`, `min`, `p25`, `median`, `p75`, `max`, `count` and `outliers` for a custom `format`.
|
|
13
|
+
- Categories keep the order the data gives them, and the value axis fits the values without reaching for zero.
|
|
14
|
+
- It takes the same props as every other plot: `segments` to restyle whole categories, the interactive legend, `markers`, `styles.frame` and the rest.
|
|
15
|
+
- New `box` block in the configuration for the box fill opacity and the spacing between boxes (`fillOpacity`, `paddingInner`, `paddingOuter`).
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Nice axis domains no longer grow a whole extra step when the data ends just past a round value (parts that sum to `100.00000000000001` stay on `100`). `niceTolerance` on a scale sets how far past a tick, as a share of the step, the data may end and still stay on it.
|
|
20
|
+
- Ticks at the data's first and last values no longer crowd the nice tick next to them. `axis.edgeTicks` in the configuration (or `edgeTicks` on a scale) chooses what happens then: `collision` is `'drop-nice'`, `'drop-edge'` or `'extend'`.
|
|
21
|
+
- A tooltip that lists several rows shows them highest value first.
|
|
22
|
+
- The timeline accepts steps given as `Date` objects or date strings (ISO, or any pattern set with `dateFormat`), not only numbers.
|
|
23
|
+
- The `delta` marker's label offset and anchor have defaults per axis in the configuration (`delta.text`).
|
|
24
|
+
- Documentation and examples brought up to date with the current API.
|
|
25
|
+
|
|
5
26
|
## [1.0.0] - 2026-10-16
|
|
6
27
|
|
|
7
28
|
First stable release.
|
package/README.md
CHANGED
|
@@ -18,24 +18,21 @@ Svelte 5 plots for data storytelling, built on [svelteplot](https://svelteplot.d
|
|
|
18
18
|
|
|
19
19
|
It aims for a sweet spot between the flexibility of `d3`, the declarative spirit of the _grammar of graphics_ (data mapped to channels, scales and marks) and the convenience of a classic plotting library, where each plot kind is a first-class component.
|
|
20
20
|
|
|
21
|
+
<!-- example: examples/LineByRegion.svelte -->
|
|
22
|
+
|
|
21
23
|
```svelte
|
|
22
24
|
<script lang="ts">
|
|
23
25
|
import { LinePlot } from '@fundar/data-chart-telling';
|
|
24
|
-
|
|
25
|
-
const rows = [
|
|
26
|
-
{ year: 2020, region: 'North', value: 3.1 },
|
|
27
|
-
{ year: 2021, region: 'North', value: 3.8 },
|
|
28
|
-
{ year: 2020, region: 'South', value: 2.2 },
|
|
29
|
-
{ year: 2021, region: 'South', value: 2.9 }
|
|
30
|
-
];
|
|
26
|
+
import { REGION_VALUES } from './data';
|
|
31
27
|
</script>
|
|
32
28
|
|
|
29
|
+
<!-- One line per region, with a title, the automatic legend, end-of-line values and a tooltip. -->
|
|
33
30
|
<LinePlot
|
|
34
31
|
width={720}
|
|
35
32
|
height={400}
|
|
36
|
-
title="
|
|
37
|
-
data={
|
|
38
|
-
x="
|
|
33
|
+
title="Monthly inflation by region (%)"
|
|
34
|
+
data={REGION_VALUES}
|
|
35
|
+
x="date"
|
|
39
36
|
y="value"
|
|
40
37
|
color="region"
|
|
41
38
|
tooltip
|
|
@@ -44,9 +41,13 @@ It aims for a sweet spot between the flexibility of `d3`, the declarative spirit
|
|
|
44
41
|
/>
|
|
45
42
|
```
|
|
46
43
|
|
|
47
|
-
|
|
44
|
+
<!-- /example -->
|
|
45
|
+
|
|
46
|
+

|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
Every Svelte snippet in this README is a runnable file in [examples/](examples/), and the data comes from [examples/data.ts](examples/data.ts).
|
|
49
|
+
|
|
50
|
+
Nine plot kinds - line, area, bar, histogram, box, heatmap, pyramid, scatter and geographic maps - share one vocabulary: the same channels (`x`, `y`, `color`, `grouping`, `opacity`, `symbol`, `r`), the same `scales`, `styles`, `segments`, `markers`, `transforms`, `tooltip`, `legend`, `timeline` and `facet` props, and one global theme.
|
|
50
51
|
|
|
51
52
|
## Install
|
|
52
53
|
|
|
@@ -62,26 +63,64 @@ The package ships Svelte components, so the app needs the Svelte compiler (`@sve
|
|
|
62
63
|
|
|
63
64
|
`timeline` slices the rows by a field and steps through them. It draws as a **player** by default: play and pause, the current step and a slider, in the figure's chrome.
|
|
64
65
|
|
|
66
|
+
<!-- example: examples/TimelinePlayer.svelte -->
|
|
67
|
+
|
|
65
68
|
```svelte
|
|
66
|
-
<
|
|
69
|
+
<script lang="ts">
|
|
70
|
+
import { BarPlot } from '@fundar/data-chart-telling';
|
|
71
|
+
import { REGION_VALUES } from './data';
|
|
72
|
+
</script>
|
|
73
|
+
|
|
74
|
+
<!--
|
|
75
|
+
`timeline` slices the rows by `accessor`. A timeline is a player by default:
|
|
76
|
+
play/pause, the current step and a slider in the chrome. `progress` sets where
|
|
77
|
+
it starts. `type: 'rule'` draws a guide beside the plot with no controls
|
|
78
|
+
instead (see TimelineRule). To build your own widget, read
|
|
79
|
+
`useFigure().timeline` (seek, play, pause, next, ...).
|
|
80
|
+
-->
|
|
81
|
+
<BarPlot
|
|
82
|
+
width={720}
|
|
83
|
+
height={400}
|
|
84
|
+
data={REGION_VALUES}
|
|
85
|
+
x="region"
|
|
86
|
+
y="value"
|
|
87
|
+
scales={{ y: { domain: [0, 30] } }}
|
|
88
|
+
timeline={{ accessor: 'date', progress: 0.25, player: { autoplay: false, loop: true } }}
|
|
89
|
+
/>
|
|
67
90
|
```
|
|
68
91
|
|
|
92
|
+
<!-- /example -->
|
|
93
|
+
|
|
69
94
|

|
|
70
95
|
|
|
71
96
|
`type: 'rule'` draws a **rule** beside the plot instead, a line with the steps written along it. The page drives it through `progress` (`0` to `1`), from a slider, scroll position or anything else.
|
|
72
97
|
|
|
98
|
+
<!-- example: examples/TimelineRule.svelte -->
|
|
99
|
+
|
|
73
100
|
```svelte
|
|
101
|
+
<script lang="ts">
|
|
102
|
+
import { LinePlot } from '@fundar/data-chart-telling';
|
|
103
|
+
import { REGION_VALUES } from './data';
|
|
104
|
+
|
|
105
|
+
// A rule has no controls of its own: the page moves it through `progress` (0 to 1).
|
|
106
|
+
// One step per year; a line plot shows every row up to the current step.
|
|
107
|
+
let progress = $state(0.5);
|
|
108
|
+
</script>
|
|
109
|
+
|
|
110
|
+
<input type="range" min="0" max="1" step="0.001" bind:value={progress} />
|
|
74
111
|
<LinePlot
|
|
75
|
-
{
|
|
76
|
-
{
|
|
77
|
-
data={
|
|
78
|
-
x="
|
|
112
|
+
width={720}
|
|
113
|
+
height={400}
|
|
114
|
+
data={REGION_VALUES}
|
|
115
|
+
x="date"
|
|
79
116
|
y="value"
|
|
80
117
|
color="region"
|
|
81
|
-
timeline={{ accessor:
|
|
118
|
+
timeline={{ accessor: (row) => row.date.getUTCFullYear(), type: 'rule', progress }}
|
|
82
119
|
/>
|
|
83
120
|
```
|
|
84
121
|
|
|
122
|
+
<!-- /example -->
|
|
123
|
+
|
|
85
124
|

|
|
86
125
|
|
|
87
126
|
See [Timeline](docs/timeline.md) for both in detail.
|
|
@@ -116,7 +116,11 @@ export const DEFAULT_CONFIG = {
|
|
|
116
116
|
yTickPadding: 10,
|
|
117
117
|
grid: false,
|
|
118
118
|
locale: 'es-AR',
|
|
119
|
-
compactDisplay: 'short'
|
|
119
|
+
compactDisplay: 'short',
|
|
120
|
+
edgeTicks: {
|
|
121
|
+
x: { enabled: true, collision: 'drop-nice' },
|
|
122
|
+
y: { enabled: false, collision: 'drop-nice' }
|
|
123
|
+
}
|
|
120
124
|
},
|
|
121
125
|
tooltip: {
|
|
122
126
|
background: '#111827',
|
|
@@ -157,6 +161,7 @@ export const DEFAULT_CONFIG = {
|
|
|
157
161
|
pyramid: { gap: { fillOpacity: 0.5 } },
|
|
158
162
|
area: { fillOpacity: 0.6 },
|
|
159
163
|
histogram: { inset: 1, fillOpacity: 1 },
|
|
164
|
+
box: { fillOpacity: 0.9, paddingInner: 0.4, paddingOuter: 0.2 },
|
|
160
165
|
scatter: { dotRadius: 5 },
|
|
161
166
|
timeline: {
|
|
162
167
|
axisColor: 'currentColor',
|
|
@@ -214,6 +219,13 @@ export const DEFAULT_CONFIG = {
|
|
|
214
219
|
font: { fill: 'currentColor', fontSize: 12, dy: -18 },
|
|
215
220
|
area: { fill: '#94a3b8', fillOpacity: 0.25 }
|
|
216
221
|
},
|
|
222
|
+
// Beside a vertical delta (taken on x), above a horizontal one (on y).
|
|
223
|
+
delta: {
|
|
224
|
+
text: {
|
|
225
|
+
x: { dx: 12, dy: 0, lineAnchor: 'middle', textAnchor: 'start' },
|
|
226
|
+
y: { dx: 0, dy: -10, lineAnchor: 'middle', textAnchor: 'middle' }
|
|
227
|
+
}
|
|
228
|
+
},
|
|
217
229
|
facet: {
|
|
218
230
|
indicator: {
|
|
219
231
|
background: '#111827',
|
|
@@ -116,6 +116,16 @@ export declare const THEMES: {
|
|
|
116
116
|
grid?: boolean | undefined;
|
|
117
117
|
locale?: string | undefined;
|
|
118
118
|
compactDisplay?: "short" | "long" | undefined;
|
|
119
|
+
edgeTicks?: {
|
|
120
|
+
x?: {
|
|
121
|
+
enabled?: boolean | undefined;
|
|
122
|
+
collision?: import("../../types/layout/scales").EdgeTickCollision | undefined;
|
|
123
|
+
} | undefined;
|
|
124
|
+
y?: {
|
|
125
|
+
enabled?: boolean | undefined;
|
|
126
|
+
collision?: import("../../types/layout/scales").EdgeTickCollision | undefined;
|
|
127
|
+
} | undefined;
|
|
128
|
+
} | undefined;
|
|
119
129
|
} | undefined;
|
|
120
130
|
tooltip?: {
|
|
121
131
|
background?: string | undefined;
|
|
@@ -213,6 +223,11 @@ export declare const THEMES: {
|
|
|
213
223
|
inset?: number | undefined;
|
|
214
224
|
fillOpacity?: number | undefined;
|
|
215
225
|
} | undefined;
|
|
226
|
+
box?: {
|
|
227
|
+
fillOpacity?: number | undefined;
|
|
228
|
+
paddingInner?: number | undefined;
|
|
229
|
+
paddingOuter?: number | undefined;
|
|
230
|
+
} | undefined;
|
|
216
231
|
scatter?: {
|
|
217
232
|
dotRadius?: number | undefined;
|
|
218
233
|
} | undefined;
|
|
@@ -315,6 +330,22 @@ export declare const THEMES: {
|
|
|
315
330
|
borderRadius?: number | undefined;
|
|
316
331
|
} | undefined;
|
|
317
332
|
} | undefined;
|
|
333
|
+
delta?: {
|
|
334
|
+
text?: {
|
|
335
|
+
x?: {
|
|
336
|
+
dx?: number | undefined;
|
|
337
|
+
dy?: number | undefined;
|
|
338
|
+
lineAnchor?: import("../../types/plots/constants").LineAnchor | undefined;
|
|
339
|
+
textAnchor?: import("../../types/plots/constants").TextAnchor | undefined;
|
|
340
|
+
} | undefined;
|
|
341
|
+
y?: {
|
|
342
|
+
dx?: number | undefined;
|
|
343
|
+
dy?: number | undefined;
|
|
344
|
+
lineAnchor?: import("../../types/plots/constants").LineAnchor | undefined;
|
|
345
|
+
textAnchor?: import("../../types/plots/constants").TextAnchor | undefined;
|
|
346
|
+
} | undefined;
|
|
347
|
+
} | undefined;
|
|
348
|
+
} | undefined;
|
|
318
349
|
facet?: {
|
|
319
350
|
indicator?: {
|
|
320
351
|
background?: string | undefined;
|
|
@@ -442,6 +473,16 @@ export declare const THEMES: {
|
|
|
442
473
|
grid?: boolean | undefined;
|
|
443
474
|
locale?: string | undefined;
|
|
444
475
|
compactDisplay?: "short" | "long" | undefined;
|
|
476
|
+
edgeTicks?: {
|
|
477
|
+
x?: {
|
|
478
|
+
enabled?: boolean | undefined;
|
|
479
|
+
collision?: import("../../types/layout/scales").EdgeTickCollision | undefined;
|
|
480
|
+
} | undefined;
|
|
481
|
+
y?: {
|
|
482
|
+
enabled?: boolean | undefined;
|
|
483
|
+
collision?: import("../../types/layout/scales").EdgeTickCollision | undefined;
|
|
484
|
+
} | undefined;
|
|
485
|
+
} | undefined;
|
|
445
486
|
} | undefined;
|
|
446
487
|
tooltip?: {
|
|
447
488
|
background?: string | undefined;
|
|
@@ -539,6 +580,11 @@ export declare const THEMES: {
|
|
|
539
580
|
inset?: number | undefined;
|
|
540
581
|
fillOpacity?: number | undefined;
|
|
541
582
|
} | undefined;
|
|
583
|
+
box?: {
|
|
584
|
+
fillOpacity?: number | undefined;
|
|
585
|
+
paddingInner?: number | undefined;
|
|
586
|
+
paddingOuter?: number | undefined;
|
|
587
|
+
} | undefined;
|
|
542
588
|
scatter?: {
|
|
543
589
|
dotRadius?: number | undefined;
|
|
544
590
|
} | undefined;
|
|
@@ -641,6 +687,22 @@ export declare const THEMES: {
|
|
|
641
687
|
borderRadius?: number | undefined;
|
|
642
688
|
} | undefined;
|
|
643
689
|
} | undefined;
|
|
690
|
+
delta?: {
|
|
691
|
+
text?: {
|
|
692
|
+
x?: {
|
|
693
|
+
dx?: number | undefined;
|
|
694
|
+
dy?: number | undefined;
|
|
695
|
+
lineAnchor?: import("../../types/plots/constants").LineAnchor | undefined;
|
|
696
|
+
textAnchor?: import("../../types/plots/constants").TextAnchor | undefined;
|
|
697
|
+
} | undefined;
|
|
698
|
+
y?: {
|
|
699
|
+
dx?: number | undefined;
|
|
700
|
+
dy?: number | undefined;
|
|
701
|
+
lineAnchor?: import("../../types/plots/constants").LineAnchor | undefined;
|
|
702
|
+
textAnchor?: import("../../types/plots/constants").TextAnchor | undefined;
|
|
703
|
+
} | undefined;
|
|
704
|
+
} | undefined;
|
|
705
|
+
} | undefined;
|
|
644
706
|
facet?: {
|
|
645
707
|
indicator?: {
|
|
646
708
|
background?: string | undefined;
|
|
@@ -768,6 +830,16 @@ export declare const THEMES: {
|
|
|
768
830
|
grid?: boolean | undefined;
|
|
769
831
|
locale?: string | undefined;
|
|
770
832
|
compactDisplay?: "short" | "long" | undefined;
|
|
833
|
+
edgeTicks?: {
|
|
834
|
+
x?: {
|
|
835
|
+
enabled?: boolean | undefined;
|
|
836
|
+
collision?: import("../../types/layout/scales").EdgeTickCollision | undefined;
|
|
837
|
+
} | undefined;
|
|
838
|
+
y?: {
|
|
839
|
+
enabled?: boolean | undefined;
|
|
840
|
+
collision?: import("../../types/layout/scales").EdgeTickCollision | undefined;
|
|
841
|
+
} | undefined;
|
|
842
|
+
} | undefined;
|
|
771
843
|
} | undefined;
|
|
772
844
|
tooltip?: {
|
|
773
845
|
background?: string | undefined;
|
|
@@ -865,6 +937,11 @@ export declare const THEMES: {
|
|
|
865
937
|
inset?: number | undefined;
|
|
866
938
|
fillOpacity?: number | undefined;
|
|
867
939
|
} | undefined;
|
|
940
|
+
box?: {
|
|
941
|
+
fillOpacity?: number | undefined;
|
|
942
|
+
paddingInner?: number | undefined;
|
|
943
|
+
paddingOuter?: number | undefined;
|
|
944
|
+
} | undefined;
|
|
868
945
|
scatter?: {
|
|
869
946
|
dotRadius?: number | undefined;
|
|
870
947
|
} | undefined;
|
|
@@ -967,6 +1044,22 @@ export declare const THEMES: {
|
|
|
967
1044
|
borderRadius?: number | undefined;
|
|
968
1045
|
} | undefined;
|
|
969
1046
|
} | undefined;
|
|
1047
|
+
delta?: {
|
|
1048
|
+
text?: {
|
|
1049
|
+
x?: {
|
|
1050
|
+
dx?: number | undefined;
|
|
1051
|
+
dy?: number | undefined;
|
|
1052
|
+
lineAnchor?: import("../../types/plots/constants").LineAnchor | undefined;
|
|
1053
|
+
textAnchor?: import("../../types/plots/constants").TextAnchor | undefined;
|
|
1054
|
+
} | undefined;
|
|
1055
|
+
y?: {
|
|
1056
|
+
dx?: number | undefined;
|
|
1057
|
+
dy?: number | undefined;
|
|
1058
|
+
lineAnchor?: import("../../types/plots/constants").LineAnchor | undefined;
|
|
1059
|
+
textAnchor?: import("../../types/plots/constants").TextAnchor | undefined;
|
|
1060
|
+
} | undefined;
|
|
1061
|
+
} | undefined;
|
|
1062
|
+
} | undefined;
|
|
970
1063
|
facet?: {
|
|
971
1064
|
indicator?: {
|
|
972
1065
|
background?: string | undefined;
|
|
@@ -1094,6 +1187,16 @@ export declare const THEMES: {
|
|
|
1094
1187
|
grid?: boolean | undefined;
|
|
1095
1188
|
locale?: string | undefined;
|
|
1096
1189
|
compactDisplay?: "short" | "long" | undefined;
|
|
1190
|
+
edgeTicks?: {
|
|
1191
|
+
x?: {
|
|
1192
|
+
enabled?: boolean | undefined;
|
|
1193
|
+
collision?: import("../../types/layout/scales").EdgeTickCollision | undefined;
|
|
1194
|
+
} | undefined;
|
|
1195
|
+
y?: {
|
|
1196
|
+
enabled?: boolean | undefined;
|
|
1197
|
+
collision?: import("../../types/layout/scales").EdgeTickCollision | undefined;
|
|
1198
|
+
} | undefined;
|
|
1199
|
+
} | undefined;
|
|
1097
1200
|
} | undefined;
|
|
1098
1201
|
tooltip?: {
|
|
1099
1202
|
background?: string | undefined;
|
|
@@ -1191,6 +1294,11 @@ export declare const THEMES: {
|
|
|
1191
1294
|
inset?: number | undefined;
|
|
1192
1295
|
fillOpacity?: number | undefined;
|
|
1193
1296
|
} | undefined;
|
|
1297
|
+
box?: {
|
|
1298
|
+
fillOpacity?: number | undefined;
|
|
1299
|
+
paddingInner?: number | undefined;
|
|
1300
|
+
paddingOuter?: number | undefined;
|
|
1301
|
+
} | undefined;
|
|
1194
1302
|
scatter?: {
|
|
1195
1303
|
dotRadius?: number | undefined;
|
|
1196
1304
|
} | undefined;
|
|
@@ -1293,6 +1401,22 @@ export declare const THEMES: {
|
|
|
1293
1401
|
borderRadius?: number | undefined;
|
|
1294
1402
|
} | undefined;
|
|
1295
1403
|
} | undefined;
|
|
1404
|
+
delta?: {
|
|
1405
|
+
text?: {
|
|
1406
|
+
x?: {
|
|
1407
|
+
dx?: number | undefined;
|
|
1408
|
+
dy?: number | undefined;
|
|
1409
|
+
lineAnchor?: import("../../types/plots/constants").LineAnchor | undefined;
|
|
1410
|
+
textAnchor?: import("../../types/plots/constants").TextAnchor | undefined;
|
|
1411
|
+
} | undefined;
|
|
1412
|
+
y?: {
|
|
1413
|
+
dx?: number | undefined;
|
|
1414
|
+
dy?: number | undefined;
|
|
1415
|
+
lineAnchor?: import("../../types/plots/constants").LineAnchor | undefined;
|
|
1416
|
+
textAnchor?: import("../../types/plots/constants").TextAnchor | undefined;
|
|
1417
|
+
} | undefined;
|
|
1418
|
+
} | undefined;
|
|
1419
|
+
} | undefined;
|
|
1296
1420
|
facet?: {
|
|
1297
1421
|
indicator?: {
|
|
1298
1422
|
background?: string | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { default as AreaPlot } from './plots/area/Plot.svelte';
|
|
2
2
|
export { default as BarPlot } from './plots/bar/Plot.svelte';
|
|
3
|
+
export { default as BoxPlot } from './plots/box/Plot.svelte';
|
|
3
4
|
export { default as HistogramPlot } from './plots/histogram/Plot.svelte';
|
|
4
5
|
export { default as HeatmapPlot } from './plots/heatmap/Plot.svelte';
|
|
5
6
|
export { default as LinePlot } from './plots/line/Plot.svelte';
|
|
@@ -41,7 +42,7 @@ export type { GeoCustomProjection, GeoCustomProjectionFactory, GeoScalesConfig,
|
|
|
41
42
|
export type { GeoCameraConfig } from './types/plots/camera';
|
|
42
43
|
export type { GeoMarkersConfig } from './types/markers/geo';
|
|
43
44
|
export type { SharedAxisValues } from './types/phases';
|
|
44
|
-
export type {
|
|
45
|
+
export type { TimelineConfig, TimelineType, TimelineCallbacks, PlayerConfig, PlayerControl } from './types/layout/timeline';
|
|
45
46
|
export type { ComposerLayout, ComposerTags, ComposerTimelineConfig, ComposerHoverConfig } from './types/layout/composer';
|
|
46
47
|
export type { GridPlacement, GridInset, GridCellContext, GridCellSnippet } from './types/layout/grid';
|
|
47
48
|
export type { Responsive, FacetConfig, FacetCellContext, FacetIndicatorContext, FacetIndicatorSnippet, FacetNavDirection, FacetNavContext, FacetNavSnippet } from './types/layout/facet';
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// timeline and facets around it.
|
|
4
4
|
export { default as AreaPlot } from './plots/area/Plot.svelte';
|
|
5
5
|
export { default as BarPlot } from './plots/bar/Plot.svelte';
|
|
6
|
+
export { default as BoxPlot } from './plots/box/Plot.svelte';
|
|
6
7
|
export { default as HistogramPlot } from './plots/histogram/Plot.svelte';
|
|
7
8
|
export { default as HeatmapPlot } from './plots/heatmap/Plot.svelte';
|
|
8
9
|
export { default as LinePlot } from './plots/line/Plot.svelte';
|
|
@@ -46,10 +46,11 @@
|
|
|
46
46
|
import { PlotMargins } from '../margins/PlotMargins.svelte';
|
|
47
47
|
import { LegendState } from '../legend/LegendState.svelte';
|
|
48
48
|
import { onDestroy, untrack } from 'svelte';
|
|
49
|
+
import { SvelteMap } from 'svelte/reactivity';
|
|
49
50
|
import type { ComponentProps, Snippet } from 'svelte';
|
|
50
51
|
import { Plot, Pointer, setPlotDefaults } from 'svelteplot';
|
|
51
52
|
import { getConfiguration } from '../../configuration/config.svelte';
|
|
52
|
-
import {
|
|
53
|
+
import { SveltePlotScale } from '../scales/SveltePlotScale';
|
|
53
54
|
import ScalesLayout from '../scales/ScalesLayout.svelte';
|
|
54
55
|
import GeometryLayout from '../geometry/GeometryLayout.svelte';
|
|
55
56
|
import CoordinatesLayout from '../coordinates/CoordinatesLayout.svelte';
|
|
@@ -187,9 +188,20 @@
|
|
|
187
188
|
size: () => ({ width, height })
|
|
188
189
|
});
|
|
189
190
|
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
|
|
191
|
+
/** The domains `ScalesLayout` widens an axis to, for an edge tick's `'extend'` (see `EdgeTicks`). */
|
|
192
|
+
const edgeDomains = new SvelteMap<'x' | 'y', [number, number]>();
|
|
193
|
+
|
|
194
|
+
// `SveltePlotScale.build` already left only svelteplot's own scale options.
|
|
195
|
+
const resolvedX = $derived.by(() => {
|
|
196
|
+
const built = SveltePlotScale.build(scales?.x, data, getX);
|
|
197
|
+
const domain = edgeDomains.get('x');
|
|
198
|
+
return (domain ? { ...built, domain, nice: false } : built) as SveltePlotProps['x'];
|
|
199
|
+
});
|
|
200
|
+
const resolvedY = $derived.by(() => {
|
|
201
|
+
const built = SveltePlotScale.build(scales?.y, data, getY);
|
|
202
|
+
const domain = edgeDomains.get('y');
|
|
203
|
+
return (domain ? { ...built, domain, nice: false } : built) as SveltePlotProps['y'];
|
|
204
|
+
});
|
|
193
205
|
/** Threaded straight into svelteplot's own `r` scale option - see `RScaleConfig`'s own doc comment for why this isn't independently resolved like `color`. */
|
|
194
206
|
const resolvedR = $derived(scales?.r as SveltePlotProps['r']);
|
|
195
207
|
/** Threaded straight into svelteplot's own `length` scale option - see `LengthScaleConfig`'s own doc comment. `GeoPlot`-only in practice (see `scales`'s own doc comment), same mechanism as `r`. */
|
|
@@ -253,7 +265,7 @@
|
|
|
253
265
|
<StylesLayout styles={state.styles} {width} {height} {numericMargins} />
|
|
254
266
|
<!-- Axes for every kind but GeoPlot. -->
|
|
255
267
|
{#if scales !== undefined && coordinates === undefined}
|
|
256
|
-
<ScalesLayout {data} {getX} {getY} {width} {height} {numericMargins} {scales} />
|
|
268
|
+
<ScalesLayout {data} {getX} {getY} {width} {height} {numericMargins} {scales} {edgeDomains} />
|
|
257
269
|
{/if}
|
|
258
270
|
<GeometryLayout
|
|
259
271
|
markers={resolvedMarkers}
|
|
@@ -297,6 +309,7 @@
|
|
|
297
309
|
y={ctrl.tooltipPosition?.y ?? 0}
|
|
298
310
|
rows={ctrl.matchedRows.map((p) => p.row)}
|
|
299
311
|
format={hover.tooltip.format}
|
|
312
|
+
sort={hover.tooltip.sort}
|
|
300
313
|
content={hover.tooltip.content}
|
|
301
314
|
anchorX={hover.tooltip.anchorX}
|
|
302
315
|
anchorY={hover.tooltip.anchorY}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { TooltipProp } from '../../types/layout/tooltip';
|
|
2
|
-
import type { HoverStrategy } from '../../types/layout/hover';
|
|
3
|
-
import
|
|
2
|
+
import type { HoverPoint, HoverStrategy } from '../../types/layout/hover';
|
|
3
|
+
import { PlotAxes } from '../../phases/data/PlotAxes';
|
|
4
|
+
import type { HoverConfig, PointMatchingStrategy, TooltipConfig } from '../../types/plots/props';
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* strategy that matches points (the tooltip's, else the marker's, else the
|
|
8
|
-
* plot kind's `defaultStrategy`) and whether it syncs across plots.
|
|
6
|
+
* A plot's hover as its `tooltip` and hover marker set it up: whether it is on,
|
|
7
|
+
* how it matches points and whether it syncs across plots.
|
|
9
8
|
*/
|
|
10
9
|
export declare class HoverSettings<TRow extends Record<string, unknown>> {
|
|
11
10
|
/** The tooltip, or `undefined` when off. */
|
|
@@ -17,4 +16,19 @@ export declare class HoverSettings<TRow extends Record<string, unknown>> {
|
|
|
17
16
|
constructor(tooltip: TooltipProp<TRow> | TooltipConfig<TRow> | undefined, markers: {
|
|
18
17
|
type: string;
|
|
19
18
|
}[] | undefined, defaultStrategy: HoverStrategy);
|
|
19
|
+
/** The strategy a plot's axes ask for: along the unmeasured axis, or `'punctual'` when both hold categories. */
|
|
20
|
+
static strategyOf(axes: PlotAxes | undefined): HoverStrategy;
|
|
21
|
+
/** A plot's `hover` config; its tooltip reads as `format` unless it sets its own. */
|
|
22
|
+
static buildConfig<TRow extends Record<string, unknown>>(args: {
|
|
23
|
+
tooltip: TooltipConfig<TRow> | undefined;
|
|
24
|
+
format: (row: TRow) => string;
|
|
25
|
+
sort?: (a: TRow, b: TRow) => number;
|
|
26
|
+
markers: {
|
|
27
|
+
type: string;
|
|
28
|
+
}[];
|
|
29
|
+
points: HoverPoint<TRow>[];
|
|
30
|
+
label: (row: TRow) => string;
|
|
31
|
+
defaultStrategy: HoverStrategy;
|
|
32
|
+
pointMatching?: PointMatchingStrategy;
|
|
33
|
+
}): HoverConfig<TRow>;
|
|
20
34
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { PlotAxes } from '../../phases/data/PlotAxes';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* strategy that matches points (the tooltip's, else the marker's, else the
|
|
5
|
-
* plot kind's `defaultStrategy`) and whether it syncs across plots.
|
|
3
|
+
* A plot's hover as its `tooltip` and hover marker set it up: whether it is on,
|
|
4
|
+
* how it matches points and whether it syncs across plots.
|
|
6
5
|
*/
|
|
7
6
|
export class HoverSettings {
|
|
8
7
|
/** The tooltip, or `undefined` when off. */
|
|
@@ -24,4 +23,30 @@ export class HoverSettings {
|
|
|
24
23
|
this.strategy = this.tooltip?.strategy ?? marker?.strategy ?? defaultStrategy;
|
|
25
24
|
this.sync = this.tooltip?.sync ?? marker?.sync ?? false;
|
|
26
25
|
}
|
|
26
|
+
/** The strategy a plot's axes ask for: along the unmeasured axis, or `'punctual'` when both hold categories. */
|
|
27
|
+
static strategyOf(axes) {
|
|
28
|
+
if (!axes)
|
|
29
|
+
return 'x';
|
|
30
|
+
if (axes.isDiscrete('x') && axes.isDiscrete('y'))
|
|
31
|
+
return 'punctual';
|
|
32
|
+
return PlotAxes.other(PlotAxes.valueOf({ axes }));
|
|
33
|
+
}
|
|
34
|
+
/** A plot's `hover` config; its tooltip reads as `format` unless it sets its own. */
|
|
35
|
+
static buildConfig(args) {
|
|
36
|
+
const { tooltip, format, sort, markers, points, label, defaultStrategy, pointMatching } = args;
|
|
37
|
+
const settings = new HoverSettings(tooltip, markers, defaultStrategy);
|
|
38
|
+
return {
|
|
39
|
+
active: settings.active,
|
|
40
|
+
points,
|
|
41
|
+
label,
|
|
42
|
+
strategy: settings.strategy,
|
|
43
|
+
sync: settings.sync,
|
|
44
|
+
tooltip: tooltip && {
|
|
45
|
+
...tooltip,
|
|
46
|
+
format: tooltip.format ?? format,
|
|
47
|
+
...(sort ? { sort } : {})
|
|
48
|
+
},
|
|
49
|
+
...(pointMatching ? { pointMatching } : {})
|
|
50
|
+
};
|
|
51
|
+
}
|
|
27
52
|
}
|
|
@@ -20,6 +20,11 @@ export declare class LegendState {
|
|
|
20
20
|
static provide(): LegendState;
|
|
21
21
|
/** The enclosing figure's legend, or a private one for a legend drawn outside any. Call during component init. */
|
|
22
22
|
static ensure(): LegendState;
|
|
23
|
+
/** Whether `value` lies within `range`; a missing value always does. */
|
|
24
|
+
static inRange(value: number | null | undefined, range: {
|
|
25
|
+
min: number;
|
|
26
|
+
max: number;
|
|
27
|
+
}): boolean;
|
|
23
28
|
/** Whether `series` is turned off. */
|
|
24
29
|
isOff(series: string): boolean;
|
|
25
30
|
/** What turning `series` off does, while it is off. */
|
|
@@ -33,6 +33,10 @@ export class LegendState {
|
|
|
33
33
|
static ensure() {
|
|
34
34
|
return LegendState.current() ?? new LegendState();
|
|
35
35
|
}
|
|
36
|
+
/** Whether `value` lies within `range`; a missing value always does. */
|
|
37
|
+
static inRange(value, range) {
|
|
38
|
+
return value == null || (value >= range.min && value <= range.max);
|
|
39
|
+
}
|
|
36
40
|
/** Whether `series` is turned off. */
|
|
37
41
|
isOff(series) {
|
|
38
42
|
return this.disabled.has(series);
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import { HoverState } from '../hover/HoverState.svelte';
|
|
15
15
|
import { HoverSettings } from '../hover/HoverSettings';
|
|
16
16
|
import { Interpolation } from '../../utils/Interpolation';
|
|
17
|
-
import {
|
|
17
|
+
import { FacetPanels } from '../../phases/facet/FacetPanels';
|
|
18
18
|
import { merge } from '../../utils/merge';
|
|
19
19
|
import { Pipeline } from '../../phases/Pipeline';
|
|
20
20
|
import { Slice } from './Slice';
|
|
@@ -191,7 +191,9 @@
|
|
|
191
191
|
margins: place.margins,
|
|
192
192
|
tooltip: tooltipConfig,
|
|
193
193
|
scales: slicing.facetScales<TScales>(sharedScales, place),
|
|
194
|
-
panel: panels
|
|
194
|
+
panel: panels
|
|
195
|
+
? FacetPanels.buildPanelState(panels, slicing.panelKey(place) ?? '')
|
|
196
|
+
: undefined,
|
|
195
197
|
keep: slicing.keep({ time, facet: place })
|
|
196
198
|
})}
|
|
197
199
|
</HoverScope>
|
|
@@ -246,9 +248,10 @@
|
|
|
246
248
|
<TimelineLayout
|
|
247
249
|
data={rows}
|
|
248
250
|
accessor={timeline.accessor}
|
|
251
|
+
dateFormat={timeline.dateFormat}
|
|
249
252
|
progress={timelineState?.progress ?? timeline.progress ?? 0}
|
|
250
253
|
values={sharedTimeline ? sharedTimeline.steps : timeline.values}
|
|
251
|
-
onsteps={ownTimeline ? (found) => ownTimeline.setSteps(found) : undefined}
|
|
254
|
+
onsteps={ownTimeline ? (found, temporal) => ownTimeline.setSteps(found, temporal) : undefined}
|
|
252
255
|
orientation={timeline.orientation}
|
|
253
256
|
show={false}
|
|
254
257
|
filterMode={slicing.filterMode}
|
|
@@ -8,7 +8,7 @@ import type { Margins } from '../margins/Margins';
|
|
|
8
8
|
import type { PlotAxes } from '../../phases/data/PlotAxes';
|
|
9
9
|
import type { AxisValue } from '../../types/layout/mapping';
|
|
10
10
|
import type { HoverPoint, HoverStrategy } from '../../types/layout/hover';
|
|
11
|
-
import type { PlayerControl,
|
|
11
|
+
import type { PlayerControl, TimeInput, TimelineStep } from '../../types/layout/timeline';
|
|
12
12
|
import type { LegendDisabledAction, LegendEntry, LegendRange } from '../../types/layout/legend';
|
|
13
13
|
/** What the pointer is over, shared by every plot in a figure. Read-only. */
|
|
14
14
|
export declare class PublicHover {
|
|
@@ -69,11 +69,11 @@ export declare class PublicTimeline {
|
|
|
69
69
|
/** Whether the figure has a timeline at all. */
|
|
70
70
|
get enabled(): boolean;
|
|
71
71
|
/** Every step it moves across, ascending. */
|
|
72
|
-
get steps():
|
|
72
|
+
get steps(): TimelineStep[];
|
|
73
73
|
/** The position across the steps, `0`-`1`. */
|
|
74
74
|
get progress(): number;
|
|
75
75
|
/** The step the position lands on, or `undefined` without steps. */
|
|
76
|
-
get value():
|
|
76
|
+
get value(): TimelineStep | undefined;
|
|
77
77
|
get index(): number;
|
|
78
78
|
get playing(): boolean;
|
|
79
79
|
get loop(): boolean;
|
|
@@ -83,7 +83,8 @@ export declare class PublicTimeline {
|
|
|
83
83
|
get controls(): PlayerControl[];
|
|
84
84
|
seek(progress: number): void;
|
|
85
85
|
seekIndex(index: number): void;
|
|
86
|
-
|
|
86
|
+
/** Moves to the step closest to `value`. */
|
|
87
|
+
seekValue(value: TimeInput): void;
|
|
87
88
|
next(): void;
|
|
88
89
|
previous(): void;
|
|
89
90
|
play(): void;
|