@ggts-sh/skill 0.43.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/LICENSE +21 -0
- package/README.md +80 -0
- package/SKILL.md +196 -0
- package/package.json +39 -0
- package/references/composition-surfaces.md +199 -0
- package/references/geoms-and-stats.md +276 -0
- package/references/grammar.md +111 -0
- package/references/interactions.md +312 -0
- package/references/react.md +101 -0
- package/references/recipes.md +441 -0
- package/references/registration.md +72 -0
- package/references/scales-and-palettes.md +396 -0
- package/references/svelte.md +79 -0
- package/references/themes.md +96 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
<!-- Source of truth: packages/spec/src/schema-names.ts (scheme/shape/linetype names), packages/spec/src/capabilities.ts (SCALE_CAPABILITIES), scripts/gen-scale-children.ts (Scale* component generation), packages/spec/src/scale-*.ts helpers. Inventory tables are asserted complete by scripts/skill-content/inventory.test.ts. -->
|
|
2
|
+
|
|
3
|
+
# Scales and palettes
|
|
4
|
+
|
|
5
|
+
## Scale families
|
|
6
|
+
|
|
7
|
+
`SCALE_CAPABILITIES` declares seven families. `scaleTypes` are the canonical
|
|
8
|
+
post-normalize types; authored aliases never survive `normalize` (e.g. authored
|
|
9
|
+
`type: "log"` becomes `{ "type": "linear", "transform": "log10" }` — trained
|
|
10
|
+
models never report type `log`).
|
|
11
|
+
|
|
12
|
+
| Family | Aesthetics | Canonical types | Transforms | Authored aliases |
|
|
13
|
+
| ------------------- | ---------------------- | --------------------------------------------- | --------------------- | ---------------- |
|
|
14
|
+
| position-continuous | x, y | linear | identity, log10, sqrt | log |
|
|
15
|
+
| position-binned | x, y | binned | identity, log10, sqrt | — |
|
|
16
|
+
| position-temporal | x, y | time | identity | — |
|
|
17
|
+
| position-discrete | x, y | band | — | — |
|
|
18
|
+
| color-fill | color, fill | ordinal, sequential, binned, manual, identity | identity, log10, sqrt | — |
|
|
19
|
+
| numeric-style | size, linewidth, alpha | sequential, ordinal, binned, manual, identity | identity | — |
|
|
20
|
+
| finite-style | shape, linetype | ordinal, binned, manual, identity | — | — |
|
|
21
|
+
|
|
22
|
+
**Ordering contract**: scale transforms run before stats and positions (a
|
|
23
|
+
log10 x reshapes what `stat: "smooth"` sees). Coordinate transforms
|
|
24
|
+
(`coord: {"type": "transform", ...}`) run after stats and preserve stat inputs.
|
|
25
|
+
|
|
26
|
+
### Position scales (x/y)
|
|
27
|
+
|
|
28
|
+
Options on any position scale (`PositionScaleSpec`):
|
|
29
|
+
|
|
30
|
+
| Option | Values / default | Notes |
|
|
31
|
+
| ------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
32
|
+
| `type` | linear, binned, time, band (+ authored alias log) | Omit to infer from field type |
|
|
33
|
+
| `transform` | identity (default), log10 (values > 0), sqrt (values >= 0) | Only identity on time scales |
|
|
34
|
+
| `domain` | `[min, max]` (continuous/time) or full category list (band) | Pins the scale; out-of-domain data drops with a warning |
|
|
35
|
+
| `oob` | censor (default) or squish | Applied to explicit source limits, before stats |
|
|
36
|
+
| `nice` | boolean, default true | Rounds inferred domain to tick-friendly bounds; ignored with `domain` |
|
|
37
|
+
| `zero` | boolean | Bars/cols/areas force true on the measure axis; set false to override |
|
|
38
|
+
| `expand` | `{ mult, add }` | Default `{mult: 0.05, add: 0}` non-temporal; time axes default to zero |
|
|
39
|
+
| `breaks` | numbers, or ISO strings on time scales | Explicit ticks; on binned scales these are bin boundaries, at most 65 (64 bins) |
|
|
40
|
+
| `minorBreaks` | numbers | Minor gridlines; time scales use `dateMinorBreaks` instead |
|
|
41
|
+
| `reverse` | boolean, default false | Flips output direction |
|
|
42
|
+
| `labels` | format string | Time: strftime-style; numeric: `",d"`, `".1f"`, `".0%"`, `"~s"` |
|
|
43
|
+
| `naValue` | number or null (default) | Substitute for missing positional values, after OOB, before transform |
|
|
44
|
+
| `guide` | GuideSpec | Axis styling; band axes accept BandAxisGuideSpec |
|
|
45
|
+
|
|
46
|
+
Helper functions additionally accept `limits` as authoring sugar for `domain`
|
|
47
|
+
(supplying both throws). `scaleXReverse`/`scaleYReverse` omit the `transform`
|
|
48
|
+
and `reverse` options by type. Binned integer ids stay private; guides and
|
|
49
|
+
events use semantic values.
|
|
50
|
+
|
|
51
|
+
```json fragment
|
|
52
|
+
"scales": { "x": { "type": "linear", "transform": "log10", "limits": [1, 1000] } }
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Color and fill scales
|
|
56
|
+
|
|
57
|
+
Five types, each gating its own option set (`ColorScaleSpec`; forbidden
|
|
58
|
+
options fail schema validation):
|
|
59
|
+
|
|
60
|
+
- **ordinal** — discrete categories. `scheme` (categorical name, or a
|
|
61
|
+
sequential name for discrete sampling), `range` (explicit hex list),
|
|
62
|
+
`domain`, `domainMode` (`grow` default preserves assignments across filters;
|
|
63
|
+
`data` rebuilds), `reverse`, `onExhaust`. No transform, breaks, oob, labels.
|
|
64
|
+
- **sequential** — continuous ramp. `scheme` or `range` (>= 2 colors
|
|
65
|
+
interpolated), `transform`, `domain` `[min, max]`, `breaks` (colorbar
|
|
66
|
+
reference ticks), `oob` (`censor` default, `squish`, or `wrap` for
|
|
67
|
+
periodic data). Cyclic `*O` schemes require `wrap` (the default when
|
|
68
|
+
omitted) and an explicit domain period. Guide plan: `colorbar`.
|
|
69
|
+
- **binned** — color steps. Same shape as sequential but `breaks` are ordered
|
|
70
|
+
boundaries (at most 65). Guide plan: `colorsteps`.
|
|
71
|
+
- **manual** — explicit mapping. `range` is required and must supply one color
|
|
72
|
+
per `domain` value (mismatched lengths are the `color-manual-domain-range`
|
|
73
|
+
error). No scheme, breaks, reverse, oob, labels, onExhaust.
|
|
74
|
+
- **identity** — data cells are the colors. Only `naValue`, `unknownValue`,
|
|
75
|
+
and `guide` are allowed. Each source value is validated as `#rgb`/`#rrggbb`;
|
|
76
|
+
invalid cells map to `unknownValue` with a bounded warning. The guide is
|
|
77
|
+
suppressed by default — force it with `"guide": {"type": "legend", "force": true}`.
|
|
78
|
+
|
|
79
|
+
`naValue` colors null/missing cells; `unknownValue` colors invalid,
|
|
80
|
+
out-of-domain, or unmapped cells. Both default to `#999999`. Bounded warnings
|
|
81
|
+
count how many cells fell back. Guide plans are `discrete` (ordinal, manual,
|
|
82
|
+
identity), `colorbar` (sequential), or `colorsteps` (binned); identity and
|
|
83
|
+
single-entry manual guides need `force: true` to appear. When `type` is
|
|
84
|
+
omitted, a named `scheme` selects its family (categorical → ordinal,
|
|
85
|
+
sequential name → sequential).
|
|
86
|
+
|
|
87
|
+
**Headless color registration:** `@ggts-sh/core/render` and `registerBasic()`
|
|
88
|
+
install every color kind. Lean `@ggts-sh/core/headless` does not. Call
|
|
89
|
+
`registerDefaultOrdinalColor()` for the built-in palette or an explicit
|
|
90
|
+
`range`. A named categorical scheme (`observable10`, `Dark2`, …) needs
|
|
91
|
+
`registerOrdinalColor()`. A named sequential or diverging scheme (`viridis`,
|
|
92
|
+
`Blues`, Crameri `batlow`, …) needs `registerSequentialColor()` — a
|
|
93
|
+
sequential name with no `type` infers sequential. Explicit
|
|
94
|
+
`type: "ordinal"` still needs `registerOrdinalColor()`. Other kinds:
|
|
95
|
+
`registerBinnedColor()`, `registerManualColor()`, `registerIdentityColor()`.
|
|
96
|
+
A named scheme on the default-only register throws
|
|
97
|
+
`not registered in this build`. Full inventory: SKILL.md Registration.
|
|
98
|
+
|
|
99
|
+
### Style scales
|
|
100
|
+
|
|
101
|
+
**Headless style registration:** mapped size / linewidth / alpha need
|
|
102
|
+
`registerNumericStyle()`; mapped shape / linetype need
|
|
103
|
+
`registerFiniteStyle()`. `@ggts-sh/core/render` and `registerBasic()`
|
|
104
|
+
install both. Categorical x/y axes also need `registerBandGuide()`.
|
|
105
|
+
|
|
106
|
+
- **numeric-style** (size, linewidth, alpha): sequential, ordinal, binned,
|
|
107
|
+
manual, identity — numeric output ranges instead of colors, identity
|
|
108
|
+
transform only. `sizeUnit` applies to size only (alpha's schema drops it so
|
|
109
|
+
it cannot no-op silently). Manual domain/range length mismatch is
|
|
110
|
+
`style-manual-domain-range`. Extra size helpers: `scaleSizeArea` /
|
|
111
|
+
`scale_size_area` (area-true scaling, ggplot2's recommended default),
|
|
112
|
+
`scaleSizeBinnedArea` / `scale_size_binned_area`, and `scaleRadius` /
|
|
113
|
+
`scale_radius`. Bare ggplot2 names `scale_size`, `scale_linewidth`,
|
|
114
|
+
`scale_alpha` alias the continuous helpers.
|
|
115
|
+
- **finite-style** (shape, linetype): ordinal, binned, manual, identity over a
|
|
116
|
+
closed symbol set (see the tables below) — no transform. Manual ranges and
|
|
117
|
+
identity values must be members of the audited name lists.
|
|
118
|
+
|
|
119
|
+
## The Scale* component system
|
|
120
|
+
|
|
121
|
+
98 generated `.svelte` shells plus 28 alias exports plus the hand-written
|
|
122
|
+
`<Scale>` escape hatch = 127 `Scale*` components exported from
|
|
123
|
+
`@ggts-sh/svelte`. Shells are generated by `bun run scale:children:gen`
|
|
124
|
+
(scripts/gen-scale-children.ts; `--check` is the drift gate). Do not edit them
|
|
125
|
+
by hand.
|
|
126
|
+
|
|
127
|
+
Which variants exist per channel (aliases in parentheses are extra export
|
|
128
|
+
names for the same component):
|
|
129
|
+
|
|
130
|
+
| Variant | X, Y | Color, Fill | Size | Linewidth | Alpha | Shape | Linetype |
|
|
131
|
+
| -------------------------------- | ---- | ----------- | ---------------------- | --------------------------- | ----------------------- | ----------------------- | -------------------------- |
|
|
132
|
+
| Continuous | yes | yes | yes | yes | yes | — | — |
|
|
133
|
+
| Discrete | yes | yes | yes (ScaleSizeOrdinal) | yes (ScaleLinewidthOrdinal) | yes (ScaleAlphaOrdinal) | yes (ScaleShapeOrdinal) | yes (ScaleLinetypeOrdinal) |
|
|
134
|
+
| Binned | yes | yes | yes | yes | yes | yes | yes |
|
|
135
|
+
| Log10, Sqrt | yes | yes | — | — | — | — | — |
|
|
136
|
+
| Reverse | yes | — | — | — | — | — | — |
|
|
137
|
+
| Date, Datetime | yes | yes | yes | yes | yes | — | — |
|
|
138
|
+
| Time | yes | — | — | — | — | — | — |
|
|
139
|
+
| Manual, Identity | — | yes | yes | yes | yes | yes | yes |
|
|
140
|
+
| Ordinal | — | yes | (alias) | (alias) | (alias) | (alias) | (alias) |
|
|
141
|
+
| Brewer, Distiller, Fermenter | — | yes | — | — | — | — | — |
|
|
142
|
+
| Steps, Steps2, Stepsn | — | yes | — | — | — | — | — |
|
|
143
|
+
| Gradient, Gradient2, Gradientn | — | yes | — | — | — | — | — |
|
|
144
|
+
| Hue, Grey | — | yes | — | — | — | — | — |
|
|
145
|
+
| ViridisC, ViridisD, ViridisB | — | yes | — | — | — | — | — |
|
|
146
|
+
| Area, BinnedArea (+ ScaleRadius) | — | — | yes | — | — | — | — |
|
|
147
|
+
|
|
148
|
+
Every `ScaleColor*` component also exports a British `ScaleColour*` alias (24
|
|
149
|
+
aliases; same file, same binding). `ScaleColorOrdinal` is a distinct component
|
|
150
|
+
(explicit ordinal family), unlike the style-channel Ordinal names which are
|
|
151
|
+
re-exports of the Discrete shells.
|
|
152
|
+
|
|
153
|
+
**Function-twin pattern.** Every shell wraps one camelCase helper from
|
|
154
|
+
`@ggts-sh/spec`; the component's props are that helper's options object
|
|
155
|
+
flattened (undefined props are stripped). Each camelCase helper has a
|
|
156
|
+
binding-identical ggplot2 snake_case twin, and every Color helper has a
|
|
157
|
+
binding-identical Colour twin: `scaleXLog10` is `scale_x_log10`;
|
|
158
|
+
`scaleColourBrewer` is `scaleColorBrewer` is `scale_color_brewer` is
|
|
159
|
+
`scale_colour_brewer`. Brewer/Distiller/Fermenter and Viridis helpers accept
|
|
160
|
+
ggplot2's `palette`/`option` (maps to `scheme`) and `direction` (`-1` sets
|
|
161
|
+
`reverse: true`).
|
|
162
|
+
|
|
163
|
+
```svelte fragment
|
|
164
|
+
<GGPlot
|
|
165
|
+
data={rows}
|
|
166
|
+
aes={{ x: "day", y: "kwh", color: "site" }}
|
|
167
|
+
layers={[{ geom: "line" }]}
|
|
168
|
+
>
|
|
169
|
+
<ScaleXDate dateBreaks="1 month" dateLabels="%b %Y" />
|
|
170
|
+
<ScaleColorBrewer palette="Dark2" />
|
|
171
|
+
</GGPlot>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Escape hatch.** `<Scale value={scalesFragment} />` registers a raw `Scales`
|
|
175
|
+
fragment — use it for computed scales or variable references. It is
|
|
176
|
+
byte-identity-preserving: `value` is not routed through any helper.
|
|
177
|
+
|
|
178
|
+
## Palettes
|
|
179
|
+
|
|
180
|
+
### Categorical schemes (47)
|
|
181
|
+
|
|
182
|
+
| Scheme | Description |
|
|
183
|
+
| --------------------- | ------------------------------------------------------------------ |
|
|
184
|
+
| observable10 | Default: 10-hue Observable 10 palette |
|
|
185
|
+
| ipsum | hrbrthemes ipsum palette, published source order |
|
|
186
|
+
| flexoki | Flexoki light-background qualitative palette |
|
|
187
|
+
| colorblind | ggthemes 8-color colorblind-safe palette |
|
|
188
|
+
| stata | ggthemes Stata s2color scheme (15 colors, the default) |
|
|
189
|
+
| economist | ggthemes Economist blues/greens (scale_colour/fill_economist) |
|
|
190
|
+
| solarized | ggthemes Solarized accents, blue first (scale_*_solarized) |
|
|
191
|
+
| few | ggthemes Few "Medium" — the default `scale_colour_few` palette |
|
|
192
|
+
| few_light | ggthemes Few "Light" — for filled areas (`scale_fill_few` default) |
|
|
193
|
+
| few_dark | ggthemes Few "Dark" — for thin lines and highlighting |
|
|
194
|
+
| fivethirtyeight | ggthemes FiveThirtyEight three-color line palette (blue/red/green) |
|
|
195
|
+
| ptol | ggthemes Paul Tol qualitative 12 (full-capacity order) |
|
|
196
|
+
| canva | ggthemes Canva "Fresh and bright" 4 (the `scale_*_canva` default) |
|
|
197
|
+
| wsj | ggthemes WSJ colors6 — the default `scale_*_wsj` palette |
|
|
198
|
+
| wsj_rgby | ggthemes WSJ red/green/blue/yellow |
|
|
199
|
+
| wsj_red_green | ggthemes WSJ green/red good–bad pair |
|
|
200
|
+
| wsj_black_green | ggthemes WSJ black-to-green sentiment scale |
|
|
201
|
+
| wsj_dem_rep | ggthemes WSJ Democrat/Republican/Undecided |
|
|
202
|
+
| tableau20 | ggthemes Tableau 20 (classic paired set) |
|
|
203
|
+
| tableau_colorblind | ggthemes Tableau Color Blind 10 |
|
|
204
|
+
| tableau_seattle_grays | ggthemes Tableau Seattle Grays (5) |
|
|
205
|
+
| tableau_jewel_bright | ggthemes Tableau Jewel Bright (9) |
|
|
206
|
+
| tableau_hue_circle | ggthemes Tableau Hue Circle (19) |
|
|
207
|
+
| pander | ggthemes pander colorblind/printer-friendly 8 (Okabe-Ito order) |
|
|
208
|
+
| Dark2 | ColorBrewer qualitative, dark tones |
|
|
209
|
+
| hue | Evenly spaced HSL hues — the ggplot2-shaped `scale_*_hue` default |
|
|
210
|
+
| actonS | Crameri categorical 10-class prefix (unordered) |
|
|
211
|
+
| bamakoS | Crameri categorical 10-class prefix (unordered) |
|
|
212
|
+
| batlowS | Crameri categorical 10-class prefix (unordered) |
|
|
213
|
+
| batlowWS | Crameri categorical 10-class prefix (unordered) |
|
|
214
|
+
| batlowKS | Crameri categorical 10-class prefix (unordered) |
|
|
215
|
+
| bilbaoS | Crameri categorical 10-class prefix (unordered) |
|
|
216
|
+
| budaS | Crameri categorical 10-class prefix (unordered) |
|
|
217
|
+
| davosS | Crameri categorical 10-class prefix (unordered) |
|
|
218
|
+
| devonS | Crameri categorical 10-class prefix (unordered) |
|
|
219
|
+
| glasgowS | Crameri categorical 10-class prefix (unordered) |
|
|
220
|
+
| grayCS | Crameri categorical 10-class prefix (unordered) |
|
|
221
|
+
| hawaiiS | Crameri categorical 10-class prefix (unordered) |
|
|
222
|
+
| imolaS | Crameri categorical 10-class prefix (unordered) |
|
|
223
|
+
| lajollaS | Crameri categorical 10-class prefix (unordered) |
|
|
224
|
+
| lapazS | Crameri categorical 10-class prefix (unordered) |
|
|
225
|
+
| lipariS | Crameri categorical 10-class prefix (unordered) |
|
|
226
|
+
| naviaS | Crameri categorical 10-class prefix (unordered) |
|
|
227
|
+
| nuukS | Crameri categorical 10-class prefix (unordered) |
|
|
228
|
+
| osloS | Crameri categorical 10-class prefix (unordered) |
|
|
229
|
+
| tokyoS | Crameri categorical 10-class prefix (unordered) |
|
|
230
|
+
| turkuS | Crameri categorical 10-class prefix (unordered) |
|
|
231
|
+
|
|
232
|
+
There is no registered `"grey"` / `"gray"` scheme name. Use
|
|
233
|
+
`<ScaleColorGrey />` / `scaleColorGrey()` (or `start`/`end`) — those bake an
|
|
234
|
+
explicit greyscale `range`. Non-cyclic sequential scheme names are also legal
|
|
235
|
+
on ordinal scales (discrete sampling along the ramp — what `scale_*_viridis_d`
|
|
236
|
+
does). Cyclic `*O` names are sequential only.
|
|
237
|
+
|
|
238
|
+
**Palette exhaustion** (`onExhaust`, ordinal scales only): `cycle` (default)
|
|
239
|
+
restarts the palette and emits the bounded `palette-exhausted` warning once;
|
|
240
|
+
`error` throws the `palette-exhausted` pipeline error instead.
|
|
241
|
+
|
|
242
|
+
### Sequential schemes (60)
|
|
243
|
+
|
|
244
|
+
| Scheme | Description |
|
|
245
|
+
| -------- | ------------------------------------------------------ |
|
|
246
|
+
| viridis | Default sequential: perceptually uniform purple→yellow |
|
|
247
|
+
| magma | Perceptually uniform black→red→pale yellow |
|
|
248
|
+
| plasma | Perceptually uniform blue→magenta→yellow |
|
|
249
|
+
| inferno | Perceptually uniform black→orange→yellow |
|
|
250
|
+
| cividis | Colorblind-optimized blue→yellow |
|
|
251
|
+
| turbo | Google turbo rainbow (high contrast, not uniform) |
|
|
252
|
+
| Blues | ColorBrewer single-hue light→dark blue |
|
|
253
|
+
| Greens | ColorBrewer single-hue light→dark green |
|
|
254
|
+
| Reds | ColorBrewer single-hue light→dark red |
|
|
255
|
+
| Oranges | ColorBrewer single-hue light→dark orange |
|
|
256
|
+
| Purples | ColorBrewer single-hue light→dark purple |
|
|
257
|
+
| Greys | ColorBrewer single-hue light→dark grey |
|
|
258
|
+
| YlOrRd | ColorBrewer multi-hue yellow→orange→red |
|
|
259
|
+
| YlGnBu | ColorBrewer multi-hue yellow→green→blue |
|
|
260
|
+
| BuPu | ColorBrewer multi-hue blue→purple |
|
|
261
|
+
| RdYlBu | ColorBrewer diverging red→yellow→blue |
|
|
262
|
+
| RdBu | ColorBrewer diverging red→white→blue |
|
|
263
|
+
| BrBG | ColorBrewer diverging brown→teal |
|
|
264
|
+
| Spectral | ColorBrewer diverging rainbow |
|
|
265
|
+
| PuOr | ColorBrewer diverging purple→orange |
|
|
266
|
+
| acton | Crameri sequential (scientific, CVD-friendly) |
|
|
267
|
+
| bamako | Crameri sequential (scientific, CVD-friendly) |
|
|
268
|
+
| batlow | Crameri sequential flagship (#UseBatlow) |
|
|
269
|
+
| batlowW | Crameri sequential batlow light end |
|
|
270
|
+
| batlowK | Crameri sequential batlow dark end |
|
|
271
|
+
| bilbao | Crameri sequential (scientific, CVD-friendly) |
|
|
272
|
+
| buda | Crameri sequential (scientific, CVD-friendly) |
|
|
273
|
+
| davos | Crameri sequential (scientific, CVD-friendly) |
|
|
274
|
+
| devon | Crameri sequential (scientific, CVD-friendly) |
|
|
275
|
+
| glasgow | Crameri sequential (scientific, CVD-friendly) |
|
|
276
|
+
| grayC | Crameri sequential greyscale |
|
|
277
|
+
| hawaii | Crameri sequential (scientific, CVD-friendly) |
|
|
278
|
+
| imola | Crameri sequential (scientific, CVD-friendly) |
|
|
279
|
+
| lajolla | Crameri sequential (scientific, CVD-friendly) |
|
|
280
|
+
| lapaz | Crameri sequential (scientific, CVD-friendly) |
|
|
281
|
+
| lipari | Crameri sequential (scientific, CVD-friendly) |
|
|
282
|
+
| navia | Crameri sequential (scientific, CVD-friendly) |
|
|
283
|
+
| naviaW | Crameri sequential navia light end |
|
|
284
|
+
| nuuk | Crameri sequential (scientific, CVD-friendly) |
|
|
285
|
+
| oslo | Crameri sequential (scientific, CVD-friendly) |
|
|
286
|
+
| tokyo | Crameri sequential (scientific, CVD-friendly) |
|
|
287
|
+
| turku | Crameri sequential (scientific, CVD-friendly) |
|
|
288
|
+
| bam | Crameri diverging (scientific, CVD-friendly) |
|
|
289
|
+
| berlin | Crameri diverging (scientific, CVD-friendly) |
|
|
290
|
+
| broc | Crameri diverging (scientific, CVD-friendly) |
|
|
291
|
+
| cork | Crameri diverging (scientific, CVD-friendly) |
|
|
292
|
+
| lisbon | Crameri diverging (scientific, CVD-friendly) |
|
|
293
|
+
| managua | Crameri diverging (scientific, CVD-friendly) |
|
|
294
|
+
| roma | Crameri diverging (scientific, CVD-friendly) |
|
|
295
|
+
| tofino | Crameri diverging (scientific, CVD-friendly) |
|
|
296
|
+
| vanimo | Crameri diverging (scientific, CVD-friendly) |
|
|
297
|
+
| vik | Crameri diverging (scientific, CVD-friendly) |
|
|
298
|
+
| bukavu | Crameri multi-sequential (scientific, CVD-friendly) |
|
|
299
|
+
| fes | Crameri multi-sequential (scientific, CVD-friendly) |
|
|
300
|
+
| oleron | Crameri multi-sequential (scientific, CVD-friendly) |
|
|
301
|
+
| bamO | Crameri cyclic — periodic data only; wrap OOB |
|
|
302
|
+
| brocO | Crameri cyclic — periodic data only; wrap OOB |
|
|
303
|
+
| corkO | Crameri cyclic — periodic data only; wrap OOB |
|
|
304
|
+
| romaO | Crameri cyclic — periodic data only; wrap OOB |
|
|
305
|
+
| vikO | Crameri cyclic — periodic data only; wrap OOB |
|
|
306
|
+
|
|
307
|
+
### Finite symbol sets (default assignment order)
|
|
308
|
+
|
|
309
|
+
| Point shapes (7) | Linetypes (6) |
|
|
310
|
+
| ---------------- | ------------- |
|
|
311
|
+
| circle | solid |
|
|
312
|
+
| triangle | dashed |
|
|
313
|
+
| square | dotted |
|
|
314
|
+
| diamond | dotdash |
|
|
315
|
+
| plus | longdash |
|
|
316
|
+
| cross | twodash |
|
|
317
|
+
| circle-open | |
|
|
318
|
+
|
|
319
|
+
## Temporal scales
|
|
320
|
+
|
|
321
|
+
**Registration:** Temporal scale children (`<ScaleXDate>`, `<ScaleYDatetime>`,
|
|
322
|
+
`<ScaleColorDate>`, …) call `installTemporal()` on import. Spec-driven
|
|
323
|
+
`spec` / `layers` charts have no child: call `installTemporal()` or
|
|
324
|
+
`registerAll()` when they set `type: "time"`, a named parser, timezone, date
|
|
325
|
+
interval, or full Temporal guides. ISO strings with no explicit temporal
|
|
326
|
+
options keep the lean UTC path.
|
|
327
|
+
|
|
328
|
+
**Auto-inference.** ISO dates and date-times, four-digit-year strings,
|
|
329
|
+
year-months, month-years, and year-quarters infer a time scale after bounded
|
|
330
|
+
sampling plus whole-column validation. Ambiguous ordered dates (`01/02/2026`)
|
|
331
|
+
stay discrete — set `"parse": "dmy"` or `"parse": "mdy"`. For year-like
|
|
332
|
+
identifiers that are labels, not instants, force `{"type": "band"}`. Never
|
|
333
|
+
preprocess dates into row indexes. Explicit `linear`/`binned` (including
|
|
334
|
+
authored `log`) disables temporal inference, so numeric strings stay
|
|
335
|
+
quantitative. Explicit ordinal color/fill keeps temporal-looking labels as
|
|
336
|
+
separate groups; sequential temporal color/fill parses domains and uses
|
|
337
|
+
calendar legend labels.
|
|
338
|
+
|
|
339
|
+
**Time-scale options** (position and sequential/binned color scales):
|
|
340
|
+
|
|
341
|
+
| Option | Values / default |
|
|
342
|
+
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
343
|
+
| `parse` | Named parser (`"iso"`, `"year"`, `"ym"`, `"my"`, `"yq"`, `"ymd"`, `"ydm"`, `"mdy"`, `"myd"`, `"dmy"`, `"dym"`, and their `_hm`/`_hms` variants), exact `{ "format": "..." }`, or `{ "epoch": "seconds" \| "milliseconds" }` |
|
|
344
|
+
| `parseFailure` | `error` (default) stops with bounded evidence; `censor` drops invalid values to missing with a warning. Censoring requires an explicit parser |
|
|
345
|
+
| `temporalKind` | `date` (calendar dates), `datetime` (instants), `time` (position only: time of day) |
|
|
346
|
+
| `timezone` | IANA zone for timezone-less input; default `UTC` |
|
|
347
|
+
| `disambiguation` | DST gap/fold policy: `reject` (default), `earlier`, `later`, `compatible` |
|
|
348
|
+
| `dateBreaks`, `dateMinorBreaks` | `"<step> <unit>"`, e.g. `"2 weeks"`; units millisecond…year, step 1–1,000,000 |
|
|
349
|
+
| `dateLabels` | Strict tokens: `%Y %y %m %b %B %d %e %a %A %H %I %M %S %L %p %q %z %Z %%` |
|
|
350
|
+
| `locale` | BCP 47 tag for labels; default `en-US` |
|
|
351
|
+
| `weekStart` | Weekday for week boundaries; default `monday` |
|
|
352
|
+
|
|
353
|
+
**Precedence**: explicit `breaks` outrank `dateBreaks`; `dateLabels` outranks
|
|
354
|
+
`labels`. Authored labels are preserved with a diagnostic — never silently
|
|
355
|
+
rotated, thinned, or truncated. Automatic temporal labels use measured panel
|
|
356
|
+
extent and calendar boundaries; inspect `model.guidePlans` for the selected
|
|
357
|
+
interval and labels.
|
|
358
|
+
|
|
359
|
+
**Authoring surfaces.** The `gg()` builder has `.scaleXDate()`,
|
|
360
|
+
`.scaleXDatetime()`, `.scaleXTime()` (and Y forms), each with component twins
|
|
361
|
+
(`<ScaleXDate/>` …) and function twins (`scaleXDate`/`scale_x_date` …).
|
|
362
|
+
Date helpers serialize mapped authoring `Date` cells as calendar dates;
|
|
363
|
+
datetime helpers preserve instants. `scaleXTime`/`scale_x_time` is time-of-day
|
|
364
|
+
only: portable numbers are **seconds since midnight** (mapped to epoch ms on
|
|
365
|
+
1970-01-01Z), `Date` cells use the UTC clock portion, and default labels are
|
|
366
|
+
`%H:%M:%S`.
|
|
367
|
+
|
|
368
|
+
**Parser helpers** (from `@ggts-sh/spec`): `ymd`, `ydm`, `mdy`, `myd`, `dmy`,
|
|
369
|
+
`dym` (each also as `_hm`/`_hms`, e.g. `dmy_hms`), `ym`, `my`, `yq`,
|
|
370
|
+
`parseTemporalFormat(value, format)`, `fromEpochSeconds`,
|
|
371
|
+
`fromEpochMilliseconds`. Each accepts one value or an array, returns `Date`(s),
|
|
372
|
+
and throws `TemporalParseError` on failure — use them to convert columns at
|
|
373
|
+
authoring time instead of hand-rolled parsing.
|
|
374
|
+
|
|
375
|
+
```json complete
|
|
376
|
+
{
|
|
377
|
+
"data": {
|
|
378
|
+
"values": [
|
|
379
|
+
{ "day": "2026-01-05", "kwh": 12.1, "site": "north" },
|
|
380
|
+
{ "day": "2026-02-02", "kwh": 14.9, "site": "north" },
|
|
381
|
+
{ "day": "2026-01-05", "kwh": 13.4, "site": "south" },
|
|
382
|
+
{ "day": "2026-02-02", "kwh": 16.0, "site": "south" }
|
|
383
|
+
]
|
|
384
|
+
},
|
|
385
|
+
"aes": {
|
|
386
|
+
"x": { "field": "day" },
|
|
387
|
+
"y": { "field": "kwh" },
|
|
388
|
+
"color": { "field": "site" }
|
|
389
|
+
},
|
|
390
|
+
"layers": [{ "geom": "line" }],
|
|
391
|
+
"scales": {
|
|
392
|
+
"x": { "type": "time", "dateBreaks": "1 month", "dateLabels": "%b %Y" },
|
|
393
|
+
"color": { "type": "ordinal", "scheme": "Dark2" }
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
```
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Svelte 5
|
|
2
|
+
|
|
3
|
+
Use this reference for a Svelte target. Shared grammar and validation live in
|
|
4
|
+
[the skill](../SKILL.md). For browser interactions, read
|
|
5
|
+
[interaction rules](interactions.md) before adding Inspect, selection, zoom, or linked plots.
|
|
6
|
+
|
|
7
|
+
## Svelte composition — children are canonical
|
|
8
|
+
|
|
9
|
+
```svelte complete
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import {
|
|
12
|
+
GeomPoint,
|
|
13
|
+
GeomSmooth,
|
|
14
|
+
GGPlot,
|
|
15
|
+
Labs,
|
|
16
|
+
ScaleColorDiscrete,
|
|
17
|
+
ThemeMinimal,
|
|
18
|
+
} from "@ggts-sh/svelte";
|
|
19
|
+
|
|
20
|
+
const cars = [
|
|
21
|
+
{ displ: 1.8, hwy: 29, class: "compact" },
|
|
22
|
+
{ displ: 2.0, hwy: 31, class: "compact" },
|
|
23
|
+
{ displ: 3.5, hwy: 26, class: "midsize" },
|
|
24
|
+
{ displ: 5.3, hwy: 20, class: "suv" },
|
|
25
|
+
{ displ: 5.7, hwy: 17, class: "suv" },
|
|
26
|
+
{ displ: 6.2, hwy: 16, class: "suv" },
|
|
27
|
+
];
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<GGPlot data={cars} aes={{ x: "displ", y: "hwy", color: "class" }} height={400}>
|
|
31
|
+
<GeomSmooth method="loess" se={false} />
|
|
32
|
+
<GeomPoint size={3} alpha={0.85} />
|
|
33
|
+
<ScaleColorDiscrete scheme="observable10" />
|
|
34
|
+
<ThemeMinimal />
|
|
35
|
+
<Labs
|
|
36
|
+
title="Bigger engines, thirstier cars"
|
|
37
|
+
x="Displacement (l)"
|
|
38
|
+
y="Highway mpg"
|
|
39
|
+
color="Class"
|
|
40
|
+
/>
|
|
41
|
+
</GGPlot>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Convention (ggplot2 thinking order): mark layers first, then scales / coords /
|
|
45
|
+
facets, then theme / guides / labs, then host-only `<Inspect>` last. Grammar
|
|
46
|
+
**layers** (theme/scale/coord/facet/guides/labs/legend) render no markup and
|
|
47
|
+
register declaratively as non-mark `Layer` kinds; mark-layer registration
|
|
48
|
+
order is z-order (points above smooth here). Interleave does not change the
|
|
49
|
+
assembled PortableSpec beyond mark z-order and last-wins folds within a
|
|
50
|
+
family. Every geom takes aesthetics through one `aes` object prop
|
|
51
|
+
(bare-string shorthand allowed) and constant style params as direct props
|
|
52
|
+
(`size={3}`); structural props are `data`, `stat`, `position`,
|
|
53
|
+
`positionParams`, `render`.
|
|
54
|
+
|
|
55
|
+
`<GGPlot>` props: `spec`, `data`, `aes`, `layers`, `width`
|
|
56
|
+
(number | "container"), `height`, `a11y`, `ariaLabel`, the interaction props
|
|
57
|
+
(`select`, `zoom`, `tool`, `interaction`, `interactionScope`; prefer
|
|
58
|
+
`<Inspect>` for inspection and `<GuideLegend channel focus>` /
|
|
59
|
+
`<GuideLegend channel filter>` for legend interaction — do not put
|
|
60
|
+
`inspect` / `legendFocus` / `legendFilter` on `<GGPlot>` in new code), the
|
|
61
|
+
`on*` handlers, and `children`. Plot-level `key` is **deprecated** since
|
|
62
|
+
0.21 — prefer `identity` on `<Inspect>`, object-form `select`, or
|
|
63
|
+
`createPlotInteraction` (default: `id` column when present, else row index).
|
|
64
|
+
Instance methods: `resetScales()`, `setZoom()`.
|
|
65
|
+
|
|
66
|
+
Precedence: `spec` wins over everything else. For mark layers, an explicit
|
|
67
|
+
`layers` prop wins over geom children — use it for dynamic layer lists (a keyed
|
|
68
|
+
`{#each}` reorder does not preserve z-order). For grammar families, children
|
|
69
|
+
win. Coord/facet/theme REPLACE (last wins); scales merge per channel;
|
|
70
|
+
labs/guides/legend merge per key. Duplicates emit `DUPLICATE_PLOT_LAYER` /
|
|
71
|
+
`DUPLICATE_SCALE_CHANNEL` / `DUPLICATE_MERGE_KEY` advisories — full semantics
|
|
72
|
+
in
|
|
73
|
+
[references/composition-surfaces.md](composition-surfaces.md).
|
|
74
|
+
|
|
75
|
+
**Removed in 0.13.0** (deprecated since 0.11.0): the seven `<GGPlot>` grammar
|
|
76
|
+
props `facet`, `coord`, `scales`, `guides`, `legend`, `theme`, `labs`. Compose
|
|
77
|
+
them as children instead; `spec`, `data`, `aes`, and `layers` stay first-class.
|
|
78
|
+
Migrate old sources with `npm exec --package=@ggts-sh/svelte -- ggts-codemod --write src` (dry-run without
|
|
79
|
+
`--write`).
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<!-- Source of truth: packages/spec/src/schema-names.ts (THEME_NAMES, THEME_NAME_ALIASES), packages/core/src/theme-builtins.ts (token maps), packages/svelte/src/lib (Theme* shells). Inventory table is asserted complete by scripts/skill-content/inventory.test.ts. -->
|
|
2
|
+
|
|
3
|
+
# Themes
|
|
4
|
+
|
|
5
|
+
JSON form: `"theme": "minimal"` (a registered name) or a theme object —
|
|
6
|
+
optional `"name"` base plus role overrides, e.g.
|
|
7
|
+
`{"name": "dark", "ink": "#eee"}`. `grey` and `gray` are registered aliases of
|
|
8
|
+
`ggplot2` (same token map). Theme is a REPLACE grammar family on `<GGPlot>`
|
|
9
|
+
(last child wins) — merge rules live in
|
|
10
|
+
[composition-surfaces.md](composition-surfaces.md).
|
|
11
|
+
|
|
12
|
+
## Product themes (32)
|
|
13
|
+
|
|
14
|
+
| Name | Look |
|
|
15
|
+
| ----------------------- | -------------------------------------------------------------------------- |
|
|
16
|
+
| default | quiet hrbrthemes-style base: real typography, hairline grid, no axis frame |
|
|
17
|
+
| light | light grid, thin panel border, x/y ticks |
|
|
18
|
+
| dark | dark paper and panel, light ink |
|
|
19
|
+
| minimal | light grid only, no ticks or border |
|
|
20
|
+
| ggplot2 | classic grey panel, white grid |
|
|
21
|
+
| classic | no grid, black axis lines and ticks |
|
|
22
|
+
| bw | white panel, grey grid, black rectangular border (print/B&W) |
|
|
23
|
+
| hrbr | same token map as default |
|
|
24
|
+
| few | no grid, thin panel border (Stephen Few) |
|
|
25
|
+
| clean | dashed y grid only, axis lines and ticks |
|
|
26
|
+
| fivethirtyeight | grey paper and panel, white grid, blue accent |
|
|
27
|
+
| economist | pale blue paper, white grid, x ticks, red accent |
|
|
28
|
+
| tufte | monochrome ink, no grid |
|
|
29
|
+
| linedraw | black-on-white line art: hairline black grid, black border |
|
|
30
|
+
| void | no axes, grid, or panel chrome; marks and legends remain |
|
|
31
|
+
| stata | Stata s2color: bluish-gray plot region, white panel, y-grid |
|
|
32
|
+
| stata_s1color | Stata s1color: white panel with black border, light y-grid |
|
|
33
|
+
| solarized | Solarized light: cream panel, muted base1 chrome, blue accent |
|
|
34
|
+
| solarizeddark | Solarized dark: deep teal panel, muted base01 chrome, blue accent |
|
|
35
|
+
| economist_white | Economist Graphic Detail: white panel, gray grid, light-gray paper |
|
|
36
|
+
| solarized_2 | Solarized grey-style variant: base2 panel, base3 grid, no frame |
|
|
37
|
+
| solarized_2dark | solarized_2 on dark base tones |
|
|
38
|
+
| wsj | Wall Street Journal: brown paper, dotted black y-grid, x line + ticks |
|
|
39
|
+
| hc | Highcharts default: y-only #D8D8D8 grid on white, no border |
|
|
40
|
+
| hcdark | Highcharts darkunica: #2a2a2b paper, #707073 y-grid |
|
|
41
|
+
| pander | pander: dashed grey grid and ticks, bold title on white |
|
|
42
|
+
| base | base R: black frame and ticks, no grid, bold title |
|
|
43
|
+
| igray | inverse gray: white panel, gray90 surround and grid |
|
|
44
|
+
| map | every axis/panel/grid element blank — marks only, for maps |
|
|
45
|
+
| solid | nothing but marks — every non-geom element removed |
|
|
46
|
+
| grey (alias of ggplot2) | UK theme_grey |
|
|
47
|
+
| gray (alias of ggplot2) | US theme_gray |
|
|
48
|
+
|
|
49
|
+
The internal `test` theme exists for snapshots only — not a product surface;
|
|
50
|
+
do not document or recommend it.
|
|
51
|
+
|
|
52
|
+
**Headless named themes:** `@ggts-sh/core/headless` resolves only `default`
|
|
53
|
+
and `void`. A named catalog theme (`dark`, `minimal`, `economist`, …) on that
|
|
54
|
+
entry throws. Use `@ggts-sh/core` or `@ggts-sh/core/render` (or pass the
|
|
55
|
+
full editions table). This is not a `register*()` call. Full inventory:
|
|
56
|
+
SKILL.md Registration.
|
|
57
|
+
|
|
58
|
+
## Svelte shells and overrides
|
|
59
|
+
|
|
60
|
+
One named shell per product theme — `ThemeDefault`, `ThemeLight`,
|
|
61
|
+
`ThemeDark`, `ThemeMinimal`, `ThemeGgplot2`, `ThemeClassic`, `ThemeBw`,
|
|
62
|
+
`ThemeHrbr`, `ThemeFew`, `ThemeClean`, `ThemeFivethirtyeight`,
|
|
63
|
+
`ThemeEconomist`, `ThemeTufte`, `ThemeLinedraw`, `ThemeVoid`, `ThemeStata`,
|
|
64
|
+
`ThemeStatas1color`, `ThemeSolarized`, `ThemeSolarizeddark`,
|
|
65
|
+
`ThemeEconomistwhite`, `ThemeSolarized2`, `ThemeSolarized2dark`, `ThemeWsj`,
|
|
66
|
+
`ThemeHc`, `ThemeHcdark`, `ThemePander`, `ThemeBase`, `ThemeIgray`,
|
|
67
|
+
`ThemeMap`, `ThemeSolid`, `ThemeGrey`, `ThemeGray`. Escape hatch
|
|
68
|
+
`<Theme name={dynamicName} />` for reactive names.
|
|
69
|
+
|
|
70
|
+
Every shell and `<Theme>` also accepts role-override props (`ink`, `paper`,
|
|
71
|
+
`accent`, `grid`, `panel`, `axisText`, `axisLine`, `tickColor`,
|
|
72
|
+
`panelBorder`, tooltip/selection/focus roles, …): `<ThemeDark ink="#eee" />`.
|
|
73
|
+
|
|
74
|
+
```svelte fragment
|
|
75
|
+
<GGPlot data={rows} aes={{ x: "displ", y: "hwy" }} layers={[{ geom: "point" }]}>
|
|
76
|
+
<ThemeEconomist />
|
|
77
|
+
</GGPlot>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```json complete
|
|
81
|
+
{
|
|
82
|
+
"data": {
|
|
83
|
+
"values": [
|
|
84
|
+
{ "displ": 1.8, "hwy": 29 },
|
|
85
|
+
{ "displ": 3.5, "hwy": 26 }
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
"layers": [
|
|
89
|
+
{
|
|
90
|
+
"geom": "point",
|
|
91
|
+
"aes": { "x": { "field": "displ" }, "y": { "field": "hwy" } }
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
"theme": "economist"
|
|
95
|
+
}
|
|
96
|
+
```
|