@fundar/data-chart-telling 0.0.8 → 0.0.10
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/README.md +19 -0
- package/dist/charts/Chart.svelte +7 -0
- package/dist/charts/Chart.svelte.d.ts +3 -0
- package/dist/charts/bar/Chart.svelte +4 -0
- package/dist/charts/container/ChartContainer.svelte +10 -2
- package/dist/charts/container/ChartContainer.svelte.d.ts +2 -0
- package/dist/charts/heatmap/Chart.svelte +4 -0
- package/dist/charts/line/Chart.svelte +4 -0
- package/dist/charts/pyramid/Chart.svelte +4 -0
- package/dist/plots/utils/segments.js +22 -1
- package/dist/types/charts/props.d.ts +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -157,6 +157,8 @@ Plots accept either `series` (pre-built `Series[]`) or the `data` + `x`/`y`/`z`
|
|
|
157
157
|
| `title` | `string` | | ✅ | ✅ | ✅ | ✅ |
|
|
158
158
|
| `subtitle` | `string` | | ✅ | ✅ | ✅ | ✅ |
|
|
159
159
|
| `caption` | `string` | | ✅ | ✅ | ✅ | ✅ |
|
|
160
|
+
| `header` | `Snippet` | | ✅ | ✅ | ✅ | ✅ |
|
|
161
|
+
| `footer` | `Snippet` | | ✅ | ✅ | ✅ | ✅ |
|
|
160
162
|
| `legend` | `LegendSection[]` | | ✅ | ✅ | ✅ | ✅ |
|
|
161
163
|
| `segments` | `Segments<TStyle>` | `[]` | ✅ | ✅ | ✅ | ✅ |
|
|
162
164
|
| `markers` | `Marker[]` | `[]` | ✅ | ✅ | ✅ | ✅ |
|
|
@@ -167,6 +169,23 @@ Plots accept either `series` (pre-built `Series[]`) or the `data` + `x`/`y`/`z`
|
|
|
167
169
|
| `tooltip` | `TooltipProp` | | ✅ | ✅ | ✅ | ✅ |
|
|
168
170
|
| `styles` | `PlotStyles` | | ✅ | ✅ | ✅ | ✅ |
|
|
169
171
|
|
|
172
|
+
`header` and `footer` are Svelte 5 snippets that replace the string props when richer markup is needed (custom styles, logos, links, etc.). When `header` is provided it takes full precedence over `title`/`subtitle`; when `footer` is provided it takes full precedence over `caption`. Use the natural snippet syntax:
|
|
173
|
+
|
|
174
|
+
```svelte
|
|
175
|
+
<LineChart ...>
|
|
176
|
+
{#snippet header()}
|
|
177
|
+
<div style="display:flex; justify-content:space-between">
|
|
178
|
+
<h3 style="color:#2563eb">My Chart</h3>
|
|
179
|
+
<img src="/logo.svg" alt="Logo" />
|
|
180
|
+
</div>
|
|
181
|
+
{/snippet}
|
|
182
|
+
|
|
183
|
+
{#snippet footer()}
|
|
184
|
+
<small>Source: <a href="...">Dataset</a> · Updated Q3 2024</small>
|
|
185
|
+
{/snippet}
|
|
186
|
+
</LineChart>
|
|
187
|
+
```
|
|
188
|
+
|
|
170
189
|
See the [PlotStyles sub-properties table](#plotstyles-sub-properties-plots) above — charts accept the same `styles` shape and pass it through to their underlying plot.
|
|
171
190
|
|
|
172
191
|
---
|
package/dist/charts/Chart.svelte
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import LegendLayout from '../layout/legend/LegendLayout.svelte';
|
|
6
6
|
import { getConfiguration } from '../configuration/config.svelte';
|
|
7
7
|
import { provideHover } from '../layout/tooltip/hover.svelte';
|
|
8
|
+
import type { Snippet } from 'svelte';
|
|
8
9
|
import type { LegendSection } from '../types/charts/legend';
|
|
9
10
|
import type { HoverStrategy } from '../types/layout/tooltip';
|
|
10
11
|
import type {
|
|
@@ -32,6 +33,8 @@
|
|
|
32
33
|
subtitle,
|
|
33
34
|
caption,
|
|
34
35
|
legend,
|
|
36
|
+
header,
|
|
37
|
+
footer,
|
|
35
38
|
data,
|
|
36
39
|
facet,
|
|
37
40
|
timeline,
|
|
@@ -44,6 +47,8 @@
|
|
|
44
47
|
subtitle?: string;
|
|
45
48
|
caption?: string;
|
|
46
49
|
legend?: LegendSection[];
|
|
50
|
+
header?: Snippet;
|
|
51
|
+
footer?: Snippet;
|
|
47
52
|
data: TRow[];
|
|
48
53
|
facet?: FacetConfig<TRow>;
|
|
49
54
|
timeline?: TimelineConfig<TRow>;
|
|
@@ -98,6 +103,8 @@
|
|
|
98
103
|
{title}
|
|
99
104
|
{subtitle}
|
|
100
105
|
{caption}
|
|
106
|
+
{header}
|
|
107
|
+
{footer}
|
|
101
108
|
legend={legend && legend.length > 0 ? legendSnippet : undefined}
|
|
102
109
|
>
|
|
103
110
|
{#snippet plot({ width: w, height: h })}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
1
2
|
import type { LegendSection } from '../types/charts/legend';
|
|
2
3
|
import type { HoverStrategy } from '../types/layout/tooltip';
|
|
3
4
|
import type { ChartPlotSnippet, FacetConfig, TimelineConfig } from '../types/charts/common';
|
|
@@ -9,6 +10,8 @@ declare function $$render<TRow extends Record<string, unknown>>(): {
|
|
|
9
10
|
subtitle?: string;
|
|
10
11
|
caption?: string;
|
|
11
12
|
legend?: LegendSection[];
|
|
13
|
+
header?: Snippet;
|
|
14
|
+
footer?: Snippet;
|
|
12
15
|
data: TRow[];
|
|
13
16
|
facet?: FacetConfig<TRow>;
|
|
14
17
|
timeline?: TimelineConfig<TRow>;
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
subtitle,
|
|
18
18
|
caption,
|
|
19
19
|
legend,
|
|
20
|
+
header,
|
|
21
|
+
footer,
|
|
20
22
|
plot,
|
|
21
23
|
}: {
|
|
22
24
|
width: number;
|
|
@@ -25,6 +27,8 @@
|
|
|
25
27
|
subtitle?: string;
|
|
26
28
|
caption?: string;
|
|
27
29
|
legend?: Snippet;
|
|
30
|
+
header?: Snippet;
|
|
31
|
+
footer?: Snippet;
|
|
28
32
|
plot: ChartBoxSnippet;
|
|
29
33
|
} = $props();
|
|
30
34
|
|
|
@@ -37,7 +41,9 @@
|
|
|
37
41
|
</script>
|
|
38
42
|
|
|
39
43
|
<div class="dct-chart" style={themeStyle} style:width="{width}px" style:height="{height}px">
|
|
40
|
-
{#if
|
|
44
|
+
{#if header}
|
|
45
|
+
<div class="dct-chart__header">{@render header()}</div>
|
|
46
|
+
{:else if title || subtitle}
|
|
41
47
|
<div class="dct-chart__header">
|
|
42
48
|
{#if title}<h3 class="dct-chart__title">{title}</h3>{/if}
|
|
43
49
|
{#if subtitle}<span class="dct-chart__subtitle">{subtitle}</span>{/if}
|
|
@@ -58,7 +64,9 @@
|
|
|
58
64
|
{/if}
|
|
59
65
|
</div>
|
|
60
66
|
|
|
61
|
-
{#if
|
|
67
|
+
{#if footer}
|
|
68
|
+
<div class="dct-chart__caption">{@render footer()}</div>
|
|
69
|
+
{:else if caption}
|
|
62
70
|
<div class="dct-chart__caption">
|
|
63
71
|
<span>{caption}</span>
|
|
64
72
|
</div>
|
|
@@ -68,6 +68,27 @@ export function validateSegments(segments) {
|
|
|
68
68
|
check(key === DEFAULT_KEY ? '(default)' : `"${key}"`, segs);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
+
function isPlainObject(v) {
|
|
72
|
+
return v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Merges two style objects one level deep: for any key where both base and
|
|
76
|
+
* override hold plain objects (e.g. `stroke`, `dots`), their fields are
|
|
77
|
+
* merged — override wins on conflict. Primitive fields are overridden directly.
|
|
78
|
+
*/
|
|
79
|
+
function mergeStyles(base, override) {
|
|
80
|
+
const result = { ...base };
|
|
81
|
+
for (const [key, val] of Object.entries(override)) {
|
|
82
|
+
const baseVal = result[key];
|
|
83
|
+
if (isPlainObject(val) && isPlainObject(baseVal)) {
|
|
84
|
+
result[key] = { ...baseVal, ...val };
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
result[key] = val;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
71
92
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
93
|
function resolveSeriesSegments(series, segs) {
|
|
73
94
|
if (!segs.length) {
|
|
@@ -143,7 +164,7 @@ function resolveSeriesSegments(series, segs) {
|
|
|
143
164
|
// keys fill in whatever the area segment omits; the area wins on conflict.
|
|
144
165
|
const isAreaSpecific = seg.areas != null && seg.areas.length > 0;
|
|
145
166
|
const resolvedStyle = isAreaSpecific && catchAll?.style
|
|
146
|
-
?
|
|
167
|
+
? mergeStyles(catchAll.style, segStyle)
|
|
147
168
|
: segStyle;
|
|
148
169
|
userVisual.push({ data: run.data, style: resolvedStyle });
|
|
149
170
|
// When the next run is also a user segment (no unmatched data between them),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
1
2
|
import type { Accessor, AxisValue, ScalesConfig, MarginConfig } from '../plots/common';
|
|
2
3
|
import type { PlotStyles, Segments } from '../plots/styles';
|
|
3
4
|
import type { Marker } from '../plots/markers';
|
|
@@ -19,6 +20,8 @@ export type ChartProps<TRow extends Record<string, unknown>, TSegmentStyle exten
|
|
|
19
20
|
title?: string;
|
|
20
21
|
subtitle?: string;
|
|
21
22
|
caption?: string;
|
|
23
|
+
header?: Snippet;
|
|
24
|
+
footer?: Snippet;
|
|
22
25
|
legend?: LegendSection[];
|
|
23
26
|
data: TRow[];
|
|
24
27
|
x: Accessor<TRow, AxisValue>;
|