@blueprint-chart/docs 0.3.0 → 1.0.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/dist/manifest.json +7 -0
- package/package.json +3 -3
- package/src/charts/bar-vertical.md +7 -7
- package/src/guide/data-transforms.md +6 -6
- package/src/guide/getting-started.md +3 -3
- package/src/guide/palettes.md +11 -13
- package/src/guide/rendering.md +56 -0
- package/src/guide/scenes.md +60 -36
- package/src/handbook/accessibility.md +4 -4
- package/src/handbook/axes.md +14 -0
- package/src/handbook/choosing.md +1 -1
- package/src/handbook/color.md +1 -1
- package/src/handbook/design-principles.md +7 -10
- package/src/handbook/labels.md +6 -10
- package/src/handbook/tooltips.md +1 -1
- package/src/handbook/typography.md +0 -1
- package/src/reference/api/index.md +53 -0
- package/src/reference/dsl/annotations.md +3 -3
- package/src/reference/dsl/scenes-and-transforms.md +14 -11
package/dist/manifest.json
CHANGED
|
@@ -126,6 +126,13 @@
|
|
|
126
126
|
"blurb": "> 50+ curated categorical palettes, plus the helpers to resolve, audit, and adjust them for the background you render against.",
|
|
127
127
|
"mdPath": "guide/palettes.md"
|
|
128
128
|
},
|
|
129
|
+
{
|
|
130
|
+
"slug": "rendering",
|
|
131
|
+
"group": "guide",
|
|
132
|
+
"title": "rendering",
|
|
133
|
+
"blurb": "The `render()` function is the primary programmatic entry point for `@blueprint-chart/lib`. It accepts a BPC source string and returns a **chart handle** — an object with methods to produce SVG, PNG, ",
|
|
134
|
+
"mdPath": "guide/rendering.md"
|
|
135
|
+
},
|
|
129
136
|
{
|
|
130
137
|
"slug": "scenes",
|
|
131
138
|
"group": "guide",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blueprint-chart/docs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Public documentation for Blueprint Chart — handbook, guide, BPC DSL spec, and lib API reference.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"vitepress": "^1.5.0",
|
|
50
50
|
"vitest": "^3.2.4",
|
|
51
51
|
"vue": "^3.5",
|
|
52
|
-
"@blueprint-chart/lib": "0.
|
|
53
|
-
"@blueprint-chart/ui": "0.
|
|
52
|
+
"@blueprint-chart/lib": "1.0.0",
|
|
53
|
+
"@blueprint-chart/ui": "1.0.0"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"dev": "vitepress dev src --host 0.0.0.0 --port 4445",
|
|
@@ -26,19 +26,19 @@ title: Vertical bar chart
|
|
|
26
26
|
chart bar-vertical {
|
|
27
27
|
title = "Brazil produces more coffee than the next three countries combined"
|
|
28
28
|
description = "Million 60-kg bags, 2023/24 crop year"
|
|
29
|
-
source = "
|
|
30
|
-
sourceUrl = "https://
|
|
29
|
+
source = "USDA Foreign Agricultural Service"
|
|
30
|
+
sourceUrl = "https://www.fas.usda.gov/data/coffee-world-markets-and-trade"
|
|
31
31
|
colorPalette = "Harvey"
|
|
32
32
|
valueLabels = true
|
|
33
33
|
valueLabelPosition = "auto"
|
|
34
34
|
|
|
35
35
|
data {
|
|
36
36
|
"Brazil" = 66.4
|
|
37
|
-
"Vietnam" =
|
|
38
|
-
"Colombia" =
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"Honduras" =
|
|
37
|
+
"Vietnam" = 27.5
|
|
38
|
+
"Colombia" = 12.76
|
|
39
|
+
"Ethiopia" = 9.13
|
|
40
|
+
"Indonesia" = 7.65
|
|
41
|
+
"Honduras" = 5.5
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
colorize "Brazil" {
|
|
@@ -23,11 +23,11 @@ chart bar-vertical {
|
|
|
23
23
|
|
|
24
24
|
data {
|
|
25
25
|
"Brazil" = 66.4
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
26
|
+
"Colombia" = 12.76
|
|
27
|
+
"Ethiopia" = 9.13
|
|
28
|
+
"Honduras" = 5.5
|
|
29
|
+
"Indonesia" = 7.65
|
|
30
|
+
"Vietnam" = 27.5
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
colorize "Brazil" {
|
|
@@ -42,7 +42,7 @@ chart bar-vertical {
|
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
::: tip From the sample library
|
|
45
|
-
|
|
45
|
+
Adapted from `packages/lib/src/samples/coffee-production.bpc`, the only sample currently shipping with a `transform` block. The rows are shown here unsorted; `transform sort` reorders them to descending before the bar-vertical renderer reads them.
|
|
46
46
|
:::
|
|
47
47
|
|
|
48
48
|
In the editor, the same pipeline is built interactively in the Data panel — each step appears as a card, can be reordered by drag, and is re-applied on every keystroke.
|
|
@@ -152,9 +152,9 @@ make dev-docs # these docs at http://localhost:4445
|
|
|
152
152
|
The lib ships ~40 ready-to-run `.bpc` files under `packages/lib/src/samples/`. They double as canonical examples and as integration-test fixtures. A handful worth opening first:
|
|
153
153
|
|
|
154
154
|
- `bitcoin-price.bpc` — single-series line with a brand colour, year-by-year diamond symbols, and an annotation on the 2021 peak.
|
|
155
|
-
- `co2-emissions-story.bpc` — a bar chart with
|
|
156
|
-
- `farm-compass.bpc` — a multi-scene narrative where later scenes swap the chart type (area → line → area-
|
|
157
|
-
- `browser-market.bpc` — a donut driven by the named `
|
|
155
|
+
- `co2-emissions-story.bpc` — a bar chart with four scenes, each highlighting a different country to walk a reader through the same data.
|
|
156
|
+
- `farm-compass.bpc` — a multi-scene narrative where later scenes swap the chart type (area-stacked → line → area → line-multi) without rewriting the source.
|
|
157
|
+
- `browser-market.bpc` — a donut driven by the named `Imperator` palette, with right-anchored legend and percentage display.
|
|
158
158
|
- `medal-count.bpc` — `bar-multi` with a gold / silver / bronze custom palette, sorted descending, top-anchored legend.
|
|
159
159
|
- `temperature-anomaly.bpc` — single-series line tuned for dark mode (`autoContrast = false`, `allowDarkMode = true`) with a curved annotation calling out the 2015 Paris Agreement.
|
|
160
160
|
|
package/src/guide/palettes.md
CHANGED
|
@@ -16,28 +16,26 @@ Pick a palette by name in a `.bpc` document:
|
|
|
16
16
|
|
|
17
17
|
```bpc
|
|
18
18
|
chart donut {
|
|
19
|
-
title = "
|
|
20
|
-
description = "
|
|
21
|
-
source = "
|
|
22
|
-
sourceUrl = "https://
|
|
23
|
-
colorPalette = "
|
|
19
|
+
title = "The richest 1% own more wealth than the entire bottom 90% combined"
|
|
20
|
+
description = "Share of global wealth by group, 2021"
|
|
21
|
+
source = "World Inequality Report 2022"
|
|
22
|
+
sourceUrl = "https://wir2022.wid.world"
|
|
23
|
+
colorPalette = "Imperator"
|
|
24
24
|
legendPosition = "right"
|
|
25
|
-
tooltips = true
|
|
26
25
|
displayAsPercentage = true
|
|
26
|
+
tooltips = true
|
|
27
27
|
|
|
28
28
|
data {
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"Opera" = 3.1
|
|
34
|
-
"Others" = 2.9
|
|
29
|
+
"Top 1%" = 38
|
|
30
|
+
"Next 9%" = 38
|
|
31
|
+
"Middle 40%" = 22
|
|
32
|
+
"Bottom 50%" = 2
|
|
35
33
|
}
|
|
36
34
|
}
|
|
37
35
|
```
|
|
38
36
|
|
|
39
37
|
::: tip From the sample library
|
|
40
|
-
|
|
38
|
+
Excerpted from `packages/lib/src/samples/browser-market.bpc` — a donut chart driven entirely by the named `Imperator` palette. Each slice picks up the next colour from the resolved palette array.
|
|
41
39
|
:::
|
|
42
40
|
|
|
43
41
|
Or pull the colours into TypeScript:
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Rendering in code
|
|
2
|
+
|
|
3
|
+
The `render()` function is the primary programmatic entry point for `@blueprint-chart/lib`. It accepts a BPC source string and returns a **chart handle** — an object with methods to produce SVG, PNG, or a live DOM mount.
|
|
4
|
+
|
|
5
|
+
## Node — write SVG and PNG to disk
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { render } from '@blueprint-chart/lib'
|
|
9
|
+
import { writeFile } from 'node:fs/promises'
|
|
10
|
+
|
|
11
|
+
const chart = await render(bpc)
|
|
12
|
+
await writeFile('chart.svg', await chart.toSvg())
|
|
13
|
+
await writeFile('chart.png', await chart.toPng({ width: 1200 }))
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
PNG export and headless SVG in Node require optional native deps (`jsdom`, `@napi-rs/canvas`, `@resvg/resvg-js`). These are installed automatically as `optionalDependencies`. If a binary failed to install, the Node methods throw `MissingNodeRenderDepsError` naming what to reinstall.
|
|
17
|
+
|
|
18
|
+
## Browser — mount and step scenes
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
const { mount, scene } = await render(bpc)
|
|
22
|
+
mount('#chart') // element or selector
|
|
23
|
+
scene(2) // advance to scene index 2
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`mount` accepts an `HTMLElement` or a CSS selector string and returns the handle for chaining. `scene(n)` steps to scene index `n` and is also chainable.
|
|
27
|
+
|
|
28
|
+
## Options
|
|
29
|
+
|
|
30
|
+
Pass a second argument to `render()` to control the output:
|
|
31
|
+
|
|
32
|
+
| Option | Default | Description |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `theme` | system | `'light'` or `'dark'` |
|
|
35
|
+
| `scene` | `0` | Initial scene index |
|
|
36
|
+
| `width` | `640` | Output width in px (headless only) |
|
|
37
|
+
| `height` | `400` | Output height in px (headless only) |
|
|
38
|
+
| `frame` | `true` | `false` renders frameless (no title/source/etc.) |
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
const chart = await render(bpc, { theme: 'dark', width: 1200, height: 630 })
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## The handle
|
|
45
|
+
|
|
46
|
+
`render()` resolves to a `ChartHandle`. Its methods are **bound** — destructure freely — and `mount`/`scene` are **chainable**.
|
|
47
|
+
|
|
48
|
+
| Method | Browser | Node | Returns |
|
|
49
|
+
| --- | --- | --- | --- |
|
|
50
|
+
| `toSvg(opts?)` | ✅ | ✅ | `Promise<string>` |
|
|
51
|
+
| `toHtml(opts?)` | ✅ | ✅ | `Promise<string>` |
|
|
52
|
+
| `toPng(opts?)` | ❌ throws `PngBrowserUnsupportedError` | ✅ | `Promise<Uint8Array>` |
|
|
53
|
+
| `mount(target)` | ✅ | no-op (warns) | `ChartHandle` |
|
|
54
|
+
| `scene(n)` | ✅ | ✅ | `ChartHandle` |
|
|
55
|
+
|
|
56
|
+
See the [API reference](/reference/api/) for the full surface of `@blueprint-chart/lib`, including low-level rendering primitives and the chart-type registry.
|
package/src/guide/scenes.md
CHANGED
|
@@ -12,58 +12,64 @@ Journalism rarely sits still on a single chart. A finding has a build-up, a turn
|
|
|
12
12
|
|
|
13
13
|
## Quickstart
|
|
14
14
|
|
|
15
|
-
A bar chart with
|
|
15
|
+
A bar chart with four narrative beats — the first three re-spotlight a different country, and the last reframes the same story per capita:
|
|
16
16
|
|
|
17
17
|
```bpc
|
|
18
18
|
chart bar-horizontal {
|
|
19
|
-
title = "
|
|
19
|
+
title = "China emits more CO₂ than the US and India combined"
|
|
20
20
|
description = "Annual emissions in billion tonnes, 2023"
|
|
21
|
-
source = "
|
|
22
|
-
sourceUrl = "https://
|
|
23
|
-
|
|
24
|
-
valueLabels = true
|
|
25
|
-
horizontalGridStyle = none
|
|
26
|
-
showVerticalAxis = true
|
|
27
|
-
showVerticalTicks = false
|
|
28
|
-
verticalGridStyle = none
|
|
21
|
+
source = "Our World in Data"
|
|
22
|
+
sourceUrl = "https://ourworldindata.org/co2-emissions"
|
|
23
|
+
byline = "Pierre Romera"
|
|
29
24
|
|
|
30
25
|
data {
|
|
31
|
-
"China" =
|
|
32
|
-
"United States" = 4.
|
|
33
|
-
"India" =
|
|
34
|
-
"Russia" = 1.
|
|
35
|
-
"Japan" =
|
|
26
|
+
"China" = 12.17
|
|
27
|
+
"United States" = 4.92
|
|
28
|
+
"India" = 3.06
|
|
29
|
+
"Russia" = 1.73
|
|
30
|
+
"Japan" = 0.99
|
|
31
|
+
"Germany" = 0.59
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
scene "China spotlight" {
|
|
39
|
-
title = "China emits more than the US and India
|
|
40
|
-
|
|
35
|
+
title = "China alone emits more than the US and India together"
|
|
41
36
|
highlight "China"
|
|
42
37
|
}
|
|
43
38
|
|
|
44
39
|
scene "India rising" {
|
|
45
|
-
title = "India
|
|
46
|
-
|
|
40
|
+
title = "India passed the EU to become the third-largest emitter"
|
|
47
41
|
highlight "India"
|
|
48
42
|
}
|
|
49
43
|
|
|
50
44
|
scene "Japan declining" {
|
|
51
|
-
title = "Japan's emissions
|
|
52
|
-
|
|
45
|
+
title = "Japan's emissions have fallen since their 2013 peak"
|
|
53
46
|
highlight "Japan"
|
|
54
47
|
}
|
|
48
|
+
|
|
49
|
+
scene "Per capita reframe" {
|
|
50
|
+
title = "Per person, Gulf states dwarf the biggest emitters"
|
|
51
|
+
description = "CO₂ emissions per capita, tonnes per person, 2023"
|
|
52
|
+
highlight "Qatar"
|
|
53
|
+
data {
|
|
54
|
+
"Qatar" = 40.13
|
|
55
|
+
"United Arab Emirates" = 19.77
|
|
56
|
+
"United States" = 14.32
|
|
57
|
+
"China" = 8.56
|
|
58
|
+
"India" = 2.13
|
|
59
|
+
}
|
|
60
|
+
}
|
|
55
61
|
}
|
|
56
62
|
```
|
|
57
63
|
|
|
58
64
|
::: tip From the sample library
|
|
59
|
-
This is `packages/lib/src/samples/co2-emissions-story.bpc` verbatim
|
|
65
|
+
This is `packages/lib/src/samples/co2-emissions-story.bpc` verbatim. The first three scenes keep the same base data and only shift the title and highlight; the fourth swaps in per-capita data for a closing reframe.
|
|
60
66
|
:::
|
|
61
67
|
|
|
62
68
|
Open this in the editor to see the scene timeline appear automatically; embed it on a page and readers get a Previous / Next nav.
|
|
63
69
|
|
|
64
70
|
## How it works
|
|
65
71
|
|
|
66
|
-
A scene block accepts the same member set as the top-level chart
|
|
72
|
+
A scene block accepts the same member set as the top-level chart. At parse time, each `scene` becomes a `SceneNode` in the AST. The DSL converter merges scene members on top of the base chart to produce the **effective** `ChartData` and `ChartOptions` for that scene.
|
|
67
73
|
|
|
68
74
|
At render time:
|
|
69
75
|
|
|
@@ -82,13 +88,13 @@ The short-form `highlight "<name>"` is the workhorse. Drop one per scene and the
|
|
|
82
88
|
|
|
83
89
|
```bpc
|
|
84
90
|
scene "China spotlight" {
|
|
85
|
-
title = "China emits more than the US and India
|
|
91
|
+
title = "China alone emits more than the US and India together"
|
|
86
92
|
|
|
87
93
|
highlight "China"
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
scene "India rising" {
|
|
91
|
-
title = "India
|
|
97
|
+
title = "India passed the EU to become the third-largest emitter"
|
|
92
98
|
|
|
93
99
|
highlight "India"
|
|
94
100
|
}
|
|
@@ -104,8 +110,8 @@ Any scene can carry its own `data` block, which **replaces** the base data for t
|
|
|
104
110
|
|
|
105
111
|
```bpc
|
|
106
112
|
scene "Bulgaria: subsidies explode" {
|
|
107
|
-
title = "
|
|
108
|
-
description = "
|
|
113
|
+
title = "Bulgarian farmers received almost nothing before 2007 accession"
|
|
114
|
+
description = "More than three-quarters of Bulgarian subsidies are direct payments — the highest share among new members"
|
|
109
115
|
|
|
110
116
|
data {
|
|
111
117
|
series = "Indirect subsidies","Direct subsidies"
|
|
@@ -145,25 +151,43 @@ scene "Bulgarian farms grew" {
|
|
|
145
151
|
```
|
|
146
152
|
|
|
147
153
|
::: tip From the sample library
|
|
148
|
-
Scene #
|
|
154
|
+
Scene #4 of `packages/lib/src/samples/farm-compass.bpc`. The story changes chart type four times across its nine scenes — `area-stacked` → `line` → `area` → `area-stacked` → `line-multi` — all from one document.
|
|
149
155
|
:::
|
|
150
156
|
|
|
151
|
-
###
|
|
157
|
+
### Control how long an annotation stays
|
|
152
158
|
|
|
153
|
-
|
|
159
|
+
By default an annotation shows only in the scene where it is declared. Use
|
|
160
|
+
`repeat` to carry it into later scenes:
|
|
154
161
|
|
|
155
162
|
```bpc
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
scene "Crash" {
|
|
164
|
+
range {
|
|
165
|
+
start = 2008
|
|
166
|
+
end = 2009
|
|
167
|
+
text = "Financial crisis"
|
|
168
|
+
repeat = 1 // this scene plus the next one (2 scenes total)
|
|
169
|
+
}
|
|
159
170
|
}
|
|
160
171
|
|
|
161
|
-
scene "
|
|
162
|
-
|
|
172
|
+
scene "Recovery" {
|
|
173
|
+
annotation "2015" {
|
|
174
|
+
text = "Paris Agreement"
|
|
175
|
+
repeat = true // this scene and every scene after it
|
|
176
|
+
}
|
|
163
177
|
}
|
|
164
178
|
```
|
|
165
179
|
|
|
166
|
-
|
|
180
|
+
`repeat` accepts three forms:
|
|
181
|
+
|
|
182
|
+
- `false` or omitted (the default): show only in this scene.
|
|
183
|
+
- a positive integer `N`: show in this scene plus the next `N` scenes, so
|
|
184
|
+
`repeat = 1` spans 2 scenes and `repeat = 3` spans 4.
|
|
185
|
+
- `true`: show in this scene and every scene after it.
|
|
186
|
+
|
|
187
|
+
A top-level annotation (declared on the chart itself, outside any scene)
|
|
188
|
+
anchors at the base chart frame, the first thing a reader sees. With no
|
|
189
|
+
`repeat` it appears only there; `repeat` carries it forward into the scenes
|
|
190
|
+
that follow.
|
|
167
191
|
|
|
168
192
|
### Drive playback from your own UI
|
|
169
193
|
|
|
@@ -82,9 +82,9 @@ chart bar-vertical {
|
|
|
82
82
|
|
|
83
83
|
data {
|
|
84
84
|
"Brazil" = 66.4
|
|
85
|
-
"Vietnam" =
|
|
86
|
-
"Colombia" =
|
|
87
|
-
"Indonesia" =
|
|
85
|
+
"Vietnam" = 27.5
|
|
86
|
+
"Colombia" = 12.76
|
|
87
|
+
"Indonesia" = 7.65
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
colorize "Brazil" {
|
|
@@ -93,7 +93,7 @@ chart bar-vertical {
|
|
|
93
93
|
}
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
::: info
|
|
96
|
+
::: info Adapted from `packages/lib/src/samples/coffee-production.bpc`
|
|
97
97
|
Coffee uses two encodings for the highlighted bar: a distinct hue (`#a4432d` red-brown vs. the muted Harvey palette) and clear *lightness* contrast against its neighbours. Convert the chart to greyscale and Brazil still reads as the darkest bar — the second encoding (lightness) carries the story even when CVD removes the first (hue). Compare with `valueLabels = true`, which adds a *third* encoding (the literal number).
|
|
98
98
|
:::
|
|
99
99
|
|
package/src/handbook/axes.md
CHANGED
|
@@ -27,6 +27,18 @@ Truncating the y-axis on a bar or area chart visually exaggerates differences. T
|
|
|
27
27
|
- Remove grid lines entirely when value labels are shown directly on data
|
|
28
28
|
- Grid lines are reference aids, not primary content — they should never compete with data
|
|
29
29
|
|
|
30
|
+
## Bar charts default to no value axis
|
|
31
|
+
|
|
32
|
+
Bar charts label each bar directly, so the value axis is redundant. Every bar
|
|
33
|
+
variant — vertical, horizontal, grouped, stacked, split — defaults to **no
|
|
34
|
+
value-axis line, no value ticks/numbers, and no value gridlines**. Only the zero
|
|
35
|
+
baseline and the category names remain.
|
|
36
|
+
|
|
37
|
+
When a segment is too small to hold its label legibly, the label is suppressed
|
|
38
|
+
and the value falls back to the tooltip. To restore a value axis, set
|
|
39
|
+
`showVerticalAxis` / `showHorizontalAxis`, `verticalGridStyle` /
|
|
40
|
+
`horizontalGridStyle`, or turn `valueLabels` off explicitly.
|
|
41
|
+
|
|
30
42
|
## Tick marks
|
|
31
43
|
|
|
32
44
|
- Subtle or no ticks are preferred in modern chart design
|
|
@@ -63,6 +75,8 @@ A trend that looks alarming at 3:1 can look flat at 3:4. When showing rate of ch
|
|
|
63
75
|
|
|
64
76
|
Blueprint Chart's `AxisOptions` exposes scale type (linear / log), tick count, tick format, and baseline behavior. D3 scales drive the tick layout, and a shared number formatter is used by the axis, tooltip, and direct labels so the same value is rendered identically wherever it appears.
|
|
65
77
|
|
|
78
|
+
Bar charts ship with the value axis suppressed by default — direct value labels replace it. The category axis always remains. See [Bar charts default to no value axis](#bar-charts-default-to-no-value-axis) above for the complete rule.
|
|
79
|
+
|
|
66
80
|
See the [API reference](/reference/api/) for the public options that toggle grid lines, tick density, and baseline zero.
|
|
67
81
|
|
|
68
82
|
## Worked example: number format on the axis
|
package/src/handbook/choosing.md
CHANGED
|
@@ -108,7 +108,7 @@ chart donut {
|
|
|
108
108
|
}
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
::: info
|
|
111
|
+
::: info When a donut fits
|
|
112
112
|
Six categories summing to 100 % — the question is "how big a slice does Chrome own?" A donut answers it directly; a line chart cannot.
|
|
113
113
|
:::
|
|
114
114
|
|
package/src/handbook/color.md
CHANGED
|
@@ -106,7 +106,7 @@ chart donut {
|
|
|
106
106
|
}
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
::: info
|
|
109
|
+
::: info A categorical palette at the 7-color limit
|
|
110
110
|
Six unordered categories, so a categorical palette ("Heep") is the right tool — its hues vary in lightness, which means the donut survives a grayscale conversion. The rule "maximum 7 categorical colors" is exactly at the limit here.
|
|
111
111
|
:::
|
|
112
112
|
|
|
@@ -71,17 +71,14 @@ chart bar-vertical {
|
|
|
71
71
|
description = "Million 60-kg bags, 2023/24 crop year"
|
|
72
72
|
source = "International Coffee Organization"
|
|
73
73
|
colorPalette = "Harvey"
|
|
74
|
-
valueLabels = true
|
|
75
|
-
verticalGridStyle = "none"
|
|
76
|
-
horizontalGridStyle = "none"
|
|
77
74
|
|
|
78
75
|
data {
|
|
79
76
|
"Brazil" = 66.4
|
|
80
|
-
"Vietnam" =
|
|
81
|
-
"Colombia" =
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"Honduras" =
|
|
77
|
+
"Vietnam" = 27.5
|
|
78
|
+
"Colombia" = 12.76
|
|
79
|
+
"Ethiopia" = 9.13
|
|
80
|
+
"Indonesia" = 7.65
|
|
81
|
+
"Honduras" = 5.5
|
|
85
82
|
}
|
|
86
83
|
|
|
87
84
|
colorize "Brazil" {
|
|
@@ -95,8 +92,8 @@ chart bar-vertical {
|
|
|
95
92
|
}
|
|
96
93
|
```
|
|
97
94
|
|
|
98
|
-
::: info
|
|
99
|
-
Five bars stay in muted neutrals; the `colorize "Brazil"` block lifts the one bar the title is about.
|
|
95
|
+
::: info Adapted from `packages/lib/src/samples/coffee-production.bpc`
|
|
96
|
+
Five bars stay in muted neutrals; the `colorize "Brazil"` block lifts the one bar the title is about. Direct labels carry the precise numbers by default, removing the need for a y-axis altogether, and gridlines drop out entirely. Restraint, purposefulness, and "start with grey" applied in a single chart.
|
|
100
97
|
:::
|
|
101
98
|
|
|
102
99
|
## How Blueprint Chart applies these principles
|
package/src/handbook/labels.md
CHANGED
|
@@ -36,8 +36,10 @@ Place labels directly on or adjacent to data elements instead of using a separat
|
|
|
36
36
|
|
|
37
37
|
## Value labels
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
For bar charts, value labels are **on by default** — they replace the value axis entirely, so each bar carries its number directly. The renderer uses an "auto: label if it fits" rule: when a bar or stack segment is too narrow to hold its label legibly, the label is suppressed and the value falls back to the tooltip instead. See [Axes & Grid Lines](/handbook/axes) for the no-value-axis default.
|
|
40
|
+
|
|
41
|
+
For other chart types:
|
|
42
|
+
|
|
41
43
|
- On line charts: at key data points only, not every point
|
|
42
44
|
- On pie / donut charts: outside for small slices, inside for large ones
|
|
43
45
|
- Position labels to avoid overlap; use tooltips as a fallback for dense data
|
|
@@ -65,9 +67,6 @@ chart bar-vertical {
|
|
|
65
67
|
title = "E is the most frequent letter in English"
|
|
66
68
|
description = "How often each letter appears in typical English text"
|
|
67
69
|
sort = descending
|
|
68
|
-
valueLabels = true
|
|
69
|
-
verticalLabelPosition = off
|
|
70
|
-
verticalGridStyle = none
|
|
71
70
|
|
|
72
71
|
data {
|
|
73
72
|
"E" = 12.70
|
|
@@ -80,7 +79,7 @@ chart bar-vertical {
|
|
|
80
79
|
```
|
|
81
80
|
|
|
82
81
|
::: info From `packages/lib/src/samples/letter-frequency.bpc`
|
|
83
|
-
|
|
82
|
+
Value labels appear at the end of every bar by default, so the y-axis label position can be set to `off` and the gridlines removed entirely. Direct labelling replaces both the legend and the axis labels — a clean application of the data-ink rule.
|
|
84
83
|
:::
|
|
85
84
|
|
|
86
85
|
## Worked example: legend at the top, direct value labels at the bar end
|
|
@@ -91,9 +90,6 @@ chart bar-multi {
|
|
|
91
90
|
description = "2024 Paris Summer Games — top six nations"
|
|
92
91
|
colors = "#eeca3b, #c0c0c0, #cd7f32"
|
|
93
92
|
legendPosition = "top"
|
|
94
|
-
valueLabels = true
|
|
95
|
-
verticalGridStyle = none
|
|
96
|
-
verticalLabelPosition = off
|
|
97
93
|
sort = descending
|
|
98
94
|
|
|
99
95
|
data {
|
|
@@ -106,7 +102,7 @@ chart bar-multi {
|
|
|
106
102
|
```
|
|
107
103
|
|
|
108
104
|
::: info From `packages/lib/src/samples/medal-count.bpc`
|
|
109
|
-
A multi-series bar chart needs a legend to map the three hues to Gold / Silver / Bronze — placed at the top so the eye reaches it before scanning the bars. Inside each bar,
|
|
105
|
+
A multi-series bar chart needs a legend to map the three hues to Gold / Silver / Bronze — placed at the top so the eye reaches it before scanning the bars. Inside each bar, value labels print the exact count by default, eliminating the need to read against a vertical scale.
|
|
110
106
|
:::
|
|
111
107
|
|
|
112
108
|
## See also
|
package/src/handbook/tooltips.md
CHANGED
|
@@ -86,7 +86,7 @@ chart line-multi {
|
|
|
86
86
|
}
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
::: info
|
|
89
|
+
::: info Progressive disclosure without hiding the story
|
|
90
90
|
The annotation carries the headline (`"Great Recession peak"`) so the chart stands on its own. `tooltips = true` plus `crosshair = true` then layer progressive disclosure on top: hover anywhere on the x-axis and a dashed vertical line aligns the cursor with all four series at once, while the tooltip shows the four percentages for that year. The essential story is never trapped behind a hover.
|
|
91
91
|
:::
|
|
92
92
|
|
|
@@ -6,6 +6,59 @@ Public surface of [`@blueprint-chart/lib`](https://www.npmjs.com/package/@bluepr
|
|
|
6
6
|
This page mirrors [`packages/lib/src/index.ts`](https://github.com/blueprint-chart/blueprint-chart/blob/main/packages/lib/src/index.ts). It will be progressively replaced by automatically-generated TypeDoc output; for now, treat the source file as canonical when a symbol is missing here.
|
|
7
7
|
:::
|
|
8
8
|
|
|
9
|
+
## Rendering a chart
|
|
10
|
+
|
|
11
|
+
The fastest path: one function returns a chart **handle**.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { render } from '@blueprint-chart/lib'
|
|
15
|
+
|
|
16
|
+
const chart = await render(bpcSource, { theme: 'dark' })
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Node — write SVG and PNG to disk
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { render } from '@blueprint-chart/lib'
|
|
23
|
+
import { writeFile } from 'node:fs/promises'
|
|
24
|
+
|
|
25
|
+
const chart = await render(bpc)
|
|
26
|
+
await writeFile('chart.svg', await chart.toSvg())
|
|
27
|
+
await writeFile('chart.png', await chart.toPng({ width: 1200 }))
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Browser — mount and step scenes
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
const { mount, scene } = await render(bpc)
|
|
34
|
+
mount('#chart') // element or selector
|
|
35
|
+
scene(2) // advance to scene index 2
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### The handle
|
|
39
|
+
|
|
40
|
+
`render(source, options?)` resolves to a `ChartHandle`. Its methods are **bound** — destructure them freely (`const { toSvg } = await render(bpc)`) — and `mount`/`scene` are **chainable** (`(await render(bpc)).scene(1).toSvg()`).
|
|
41
|
+
|
|
42
|
+
| Method | Browser | Node | Returns |
|
|
43
|
+
| --- | --- | --- | --- |
|
|
44
|
+
| `toSvg(opts?)` | ✅ | ✅ | `Promise<string>` |
|
|
45
|
+
| `toHtml(opts?)` | ✅ | ✅ | `Promise<string>` |
|
|
46
|
+
| `toPng(opts?)` | ❌ throws `PngBrowserUnsupportedError` | ✅ | `Promise<Uint8Array>` |
|
|
47
|
+
| `mount(target)` | ✅ | no-op (warns) | `ChartHandle` |
|
|
48
|
+
| `scene(n)` | ✅ | ✅ | `ChartHandle` |
|
|
49
|
+
|
|
50
|
+
`toHtml()` returns the `.bc-frame` outerHTML (the complete framed chart markup). When `frame: false` was passed to `render()`, it falls back to the bare chart SVG.
|
|
51
|
+
|
|
52
|
+
`RenderApiOptions`: `theme?`, `scene?` (initial scene), `width?`/`height?` (default `640×400`, used for headless output only), `frame?` (default `true`; `false` renders frameless). `OutputOptions` on `toSvg`/`toPng`: `width?`, `height?`.
|
|
53
|
+
|
|
54
|
+
### Node dependencies
|
|
55
|
+
|
|
56
|
+
PNG export and headless SVG in Node require optional native deps (`jsdom`, `@napi-rs/canvas`, `@resvg/resvg-js`), installed automatically as `optionalDependencies`. If a binary failed to install, the Node methods throw `MissingNodeRenderDepsError` naming what to reinstall. Browser bundles never include these.
|
|
57
|
+
|
|
58
|
+
> SVG produced headlessly carries inline data colors and renders fonts via bundled DejaVu during PNG rasterization. It does not inline the full `charts.scss` theme; opening the bare `.svg` outside an app with that stylesheet may lack some structural styling.
|
|
59
|
+
|
|
60
|
+
## Low-level surface
|
|
61
|
+
|
|
9
62
|
## Entrypoints
|
|
10
63
|
|
|
11
64
|
| Entrypoint | Purpose |
|
|
@@ -41,19 +41,19 @@ The short form `highlight "<name>"` (no body) is the common case — useful insi
|
|
|
41
41
|
|
|
42
42
|
```bpc
|
|
43
43
|
scene "China spotlight" {
|
|
44
|
-
title = "China emits more than the US and India
|
|
44
|
+
title = "China alone emits more than the US and India together"
|
|
45
45
|
|
|
46
46
|
highlight "China"
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
scene "India rising" {
|
|
50
|
-
title = "India
|
|
50
|
+
title = "India passed the EU to become the third-largest emitter"
|
|
51
51
|
|
|
52
52
|
highlight "India"
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
scene "Japan declining" {
|
|
56
|
-
title = "Japan's emissions
|
|
56
|
+
title = "Japan's emissions have fallen since their 2013 peak"
|
|
57
57
|
|
|
58
58
|
highlight "Japan"
|
|
59
59
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# DSL — Scenes & transforms
|
|
2
2
|
|
|
3
|
-
Story-level constructs: **scenes** compose multiple visualisation states into a stepable narrative, and **transforms** describe data-pipeline operations applied before rendering. Scenes can override almost any chart member
|
|
3
|
+
Story-level constructs: **scenes** compose multiple visualisation states into a stepable narrative, and **transforms** describe data-pipeline operations applied before rendering. Scenes can override almost any chart member, including chart `type` and `data`. Annotation lifetime is controlled with the `repeat` property on the annotation itself.
|
|
4
4
|
|
|
5
5
|
## Scenes
|
|
6
6
|
|
|
@@ -10,26 +10,26 @@ A simple "highlight tour" — each scene swaps the title and emphasises one bar:
|
|
|
10
10
|
|
|
11
11
|
```bpc
|
|
12
12
|
scene "China spotlight" {
|
|
13
|
-
title = "China emits more than the US and India
|
|
13
|
+
title = "China alone emits more than the US and India together"
|
|
14
14
|
|
|
15
15
|
highlight "China"
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
scene "India rising" {
|
|
19
|
-
title = "India
|
|
19
|
+
title = "India passed the EU to become the third-largest emitter"
|
|
20
20
|
|
|
21
21
|
highlight "India"
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
scene "Japan declining" {
|
|
25
|
-
title = "Japan's emissions
|
|
25
|
+
title = "Japan's emissions have fallen since their 2013 peak"
|
|
26
26
|
|
|
27
27
|
highlight "Japan"
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
::: info From `packages/lib/src/samples/co2-emissions-story.bpc`
|
|
32
|
-
Three scenes
|
|
32
|
+
Three scenes from a `bar-horizontal` story. Each scene inherits the chart's data and styling, and only overrides what changes — `title` plus a `highlight` target.
|
|
33
33
|
:::
|
|
34
34
|
|
|
35
35
|
Scenes can also override the chart's **type** and **data** wholesale, switching from one visualisation to another mid-story:
|
|
@@ -68,14 +68,17 @@ scene "Cash crops replaced vegetables" {
|
|
|
68
68
|
A "story" can transition between chart types — here from a stacked area to a single-series line, then to a different stacked area — by setting `type` and supplying fresh `data` inside the scene.
|
|
69
69
|
:::
|
|
70
70
|
|
|
71
|
-
Scenes accept the same member set as the top-level chart
|
|
71
|
+
Scenes accept the same member set as the top-level chart.
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
Annotation lifetime is governed by the `repeat` property on each annotation, not by scene-level verbs:
|
|
74
|
+
|
|
75
|
+
| Value | Meaning |
|
|
74
76
|
| --- | --- |
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
|
|
77
|
+
| `repeat = false` (or omitted) | Show only in the scene where the annotation is declared (default). |
|
|
78
|
+
| `repeat = N` | Show in the declaring scene plus the next `N` scenes, so `repeat = 1` spans 2 scenes and `repeat = 3` spans 4. `N` must be a positive integer. |
|
|
79
|
+
| `repeat = true` | Show in the declaring scene and every scene after it. |
|
|
80
|
+
|
|
81
|
+
A top-level annotation (declared on the chart, outside any scene) anchors at the base chart frame: with no `repeat` it shows only on that first frame, and `repeat` carries it forward into the following scenes.
|
|
79
82
|
|
|
80
83
|
## Transforms
|
|
81
84
|
|