@ponchia/ui 0.11.0 → 0.12.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.
@@ -0,0 +1,100 @@
1
+ # Renderer tokens
2
+
3
+ `@ponchia/ui/renderer` resolves the live bronto theme for renderers that cannot
4
+ read CSS: Vega, xterm.js, a canvas or WebGL graph, a map, a 3D scene. Those
5
+ engines take literal colours, so a page that switches theme, skin, contrast or
6
+ the OLED surface has to resolve its tokens again before each repaint that
7
+ matters.
8
+
9
+ ```js
10
+ import { readTokens, observeTokens, vegaConfig, xtermTheme } from '@ponchia/ui/renderer';
11
+
12
+ const tokens = readTokens(); // { scheme, bg, panel, text, line, accent, categorical, … }
13
+ view = await embed(el, spec, { config: vegaConfig(tokens, { narrow: el.clientWidth < 480 }) });
14
+ terminal.options.theme = xtermTheme(tokens);
15
+
16
+ const stop = observeTokens((next) => {
17
+ terminal.options.theme = xtermTheme(next);
18
+ rebuildChart(vegaConfig(next));
19
+ });
20
+ ```
21
+
22
+ The static exports serve a different host. [`charts.json`](./theming.md#data-viz-palette)
23
+ and [`tokens/vega.js`](./vega.md) are snapshots per light/dark theme for a
24
+ report, a `file://` document or a build step. They cannot follow a skin or the
25
+ OLED preset; this module reads the page.
26
+
27
+ ## What `readTokens()` returns
28
+
29
+ Every colour is a renderer literal: `#rrggbb` when opaque, `rgba(r, g, b, a)`
30
+ when translucent. Canvas, SVG, d3-color, xterm.js, three.js and MapLibre all
31
+ accept both.
32
+
33
+ | Field | Token | Use |
34
+ | --- | --- | --- |
35
+ | `scheme` | luminance of `--bg` | `'light'` or `'dark'` |
36
+ | `bg`, `bgElevated`, `panel`, `panelStrong` | `--bg`, `--bg-elevated`, `--panel`, `--panel-strong` | Backgrounds; draw on `panel` |
37
+ | `text`, `textSoft`, `textDim` | `--text`, `--text-soft`, `--text-dim` | Labels, secondary and tertiary ink |
38
+ | `line`, `lineStrong` | `--line`, `--line-strong` | Grid and hairlines; axes and rules |
39
+ | `accent`, `accentText`, `onAccent`, `focus` | accent family | The one emphasis, its text forms, focus |
40
+ | `selection` | `--accent` at 27% | A translucent selection wash |
41
+ | `success`, `warning`, `danger`, `info` | status tier | Status only, never categories |
42
+ | `sans`, `mono` | `--sans`, `--mono` | Font stacks for a canvas renderer |
43
+ | `categorical` | `--cat-1..8` | Eight hues in fixed order |
44
+ | `categoricalTint` | `--cat-N-tint` | Each hue as a wash over `panel` |
45
+ | `categoricalInk` | `--cat-N-ink` | Each hue as text, 4.5:1 on panel and tint |
46
+ | `sequential`, `diverging` | `--chart-seq-*`, `--chart-div-*` | Ramps for magnitude and ± data |
47
+
48
+ `readTokens(element)` reads the custom properties as computed on `element`, so a
49
+ subtree that re-points tokens is honoured. Without `css/dataviz.css` on the
50
+ page, the categorical set and the ramps fall back to the packaged palette for
51
+ the resolved scheme, and the tint is computed over the live panel. Without a
52
+ DOM (SSR, tests) it returns the packaged values; pass `{ scheme: 'dark' }` to
53
+ choose.
54
+
55
+ ## Following changes
56
+
57
+ `observeTokens(callback, { element, signal })` calls back with fresh tokens
58
+ when the root's `data-theme`, `data-bronto-skin`, `data-contrast`,
59
+ `data-surface`, `data-density`, `class` or `style` changes and a token's value
60
+ moved with it, or when the system colour-scheme or contrast preference flips.
61
+ A host that writes its own inline properties on the root every frame (a canvas
62
+ zoom, say) costs one computed-style read per frame and no callback. Calls are
63
+ coalesced to one per animation frame. It returns a stop function; an
64
+ `AbortSignal` also stops it.
65
+
66
+ A host that already announces its own settled appearance change can read
67
+ `readTokens()` on that event instead and skip the observer.
68
+
69
+ ## Mappings
70
+
71
+ - **`vegaConfig(tokens, { mode, narrow, background })`** — a Vega-Lite (default)
72
+ or Vega `config`. Quiet chrome in the bronto inks, no plot frame, the
73
+ categorical palette as `range.category` (a single series takes its first
74
+ hue), the sequential ramp for `ordinal`/`ramp`/`heatmap`, the diverging ramp
75
+ for `diverging`. `narrow` moves the legend under the plot and thins ticks;
76
+ `background` defaults to transparent so the host panel shows. A spec's own
77
+ `config` still wins where Vega merges it. The static
78
+ [`tokens/vega.js`](./vega.md) is this mapping applied to each theme's
79
+ packaged tokens.
80
+ - **`xtermTheme(tokens)`** — an xterm.js `ITheme`: page ink on the page
81
+ background, the accent as cursor, the status colours for red, green, yellow
82
+ and blue, and the categorical magenta and aqua inks for magenta and cyan, so
83
+ all six ANSI hues differ.
84
+
85
+ For any other engine, map the fields yourself: they are already the roles a
86
+ renderer needs.
87
+
88
+ ## Conversions
89
+
90
+ - **`parseColor(value)`** — a resolved CSS colour to `{ r, g, b, alpha }`,
91
+ clipped into sRGB: hex, `rgb()`, `hsl()`, `oklch()`, `oklab()`, `lab()`,
92
+ `lch()` and `color(srgb | srgb-linear | display-p3 | xyz-d65 | xyz-d50 …)`.
93
+ It returns null for `var()`, `color-mix()`, `light-dark()` and named colours,
94
+ which only a browser can compute.
95
+ - **`formatColor(rgba)`** — `#rrggbb` or `rgba(r, g, b, a)`.
96
+ - **`resolveColor(value, { element })`** — any colour expression to a literal,
97
+ asking the browser for what `parseColor()` cannot compute.
98
+
99
+ The module is SSR-safe: it touches the DOM only inside a call that needs it.
100
+ It owns no renderer and imports none.
package/docs/reporting.md CHANGED
@@ -60,18 +60,18 @@ No install? Link the same files from a CDN. Pin the version — pre-1.0, breakin
60
60
  changes ship in the minor (see [stability.md](./stability.md)):
61
61
 
62
62
  ```html
63
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.11.0/dist/bronto.css" />
64
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.11.0/dist/css/report-kit.css" />
63
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.12.0/dist/bronto.css" />
64
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.12.0/dist/css/report-kit.css" />
65
65
  ```
66
66
 
67
67
  Leaf-by-leaf CDN imports use the same `dist/css/` paths:
68
68
 
69
69
  ```html
70
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.11.0/dist/bronto.css" />
71
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.11.0/dist/css/report.css" />
72
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.11.0/dist/css/dataviz.css" />
73
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.11.0/dist/css/annotations.css" />
74
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.11.0/dist/css/legend.css" />
70
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.12.0/dist/bronto.css" />
71
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.12.0/dist/css/report.css" />
72
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.12.0/dist/css/dataviz.css" />
73
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.12.0/dist/css/annotations.css" />
74
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.12.0/dist/css/legend.css" />
75
75
  ```
76
76
 
77
77
  The CDN serves the package's own `fonts/` next to the CSS, so font URLs resolve
@@ -649,7 +649,7 @@ directly; for a Vega chart, the same colours arrive through
649
649
  `brontoVegaConfig`'s `range.*` ramps, projected from `@ponchia/ui/charts.json`.
650
650
 
651
651
  For a **sequential** figure (a heatmap, a choropleth, a magnitude ramp) fill the
652
- cells from the single-hue ramp tokens `--chart-seq-1` … `--chart-seq-6`
652
+ cells from the single-hue ramp tokens `--chart-seq-1` … `--chart-seq-5`
653
653
  (low → high); for a **diverging** figure (−…0…+) use `--chart-div-1` …
654
654
  `--chart-div-7` (the middle band is the neutral midpoint). Both ramps live in
655
655
  `css/dataviz.css`, and their resolved per-theme hexes are in
@@ -885,7 +885,7 @@ or validation runtime.
885
885
 
886
886
  ```json
887
887
  {
888
- "$schema": "https://cdn.jsdelivr.net/npm/@ponchia/ui@0.11.0/schemas/report-claims.v1.schema.json",
888
+ "$schema": "https://cdn.jsdelivr.net/npm/@ponchia/ui@0.12.0/schemas/report-claims.v1.schema.json",
889
889
  "schemaVersion": "bronto-report-claims.v1",
890
890
  "report": { "title": "Decision readiness", "type": "decision" },
891
891
  "claims": [
package/docs/stability.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Public API stability
2
2
 
3
3
  `@ponchia/ui` is pre-1.0. Breaking changes ship in the minor (`0.x.0`), and
4
- patches are non-breaking. In practical terms: **PATCH releases (`0.11.x`) are
4
+ patches are non-breaking. In practical terms: **PATCH releases (`0.12.x`) are
5
5
  non-breaking bug-fixes and additive changes — safe to upgrade without review;
6
6
  MINOR releases (`0.x.0`) may include breaking changes and consumers should
7
7
  review the CHANGELOG before upgrading.** Pin `~0.x` (tilde) to accept only
@@ -93,7 +93,8 @@ current public-surface matrix and the release policy above still applies.
93
93
  | Glyph registry/renderers (`@ponchia/ui/glyphs`) | Stable additive | Existing glyph names stay valid. New glyphs are additive. Renderer option names and accessibility defaults are public. |
94
94
  | `.ui-icon` mask renderer | Stable | Class name, `--icon-size`, currentColor inheritance, and `--icon-mask` contract are public. The internal data URL encoding is not. |
95
95
  | Skins (`@ponchia/ui/skins`, `css/skins.css`) | Stable additive | Existing skin names stay valid. New skins are additive. Skins are root-level choices. Skin CSS is opt-in, not in the default bundle. |
96
- | Charts (`@ponchia/ui/charts`, `charts.json`, `css/dataviz.css`) | Stable additive | Token names, JSON shape, and 8 categorical slots are public. `css/dataviz.css` is opt-in, not in the default bundle. Exact palette values may tune if gates and release notes justify it. |
96
+ | Charts (`@ponchia/ui/charts`, `charts.json`, `css/dataviz.css`) | Stable additive | Token names (`--chart-*`, `--cat-N`, `--cat-N-tint`, `--cat-N-ink`), `CATEGORICAL_HUES`, the JSON shape, and the 8 categorical slots in fixed hue order are public. `css/dataviz.css` is opt-in, not in the default bundle. Exact palette values may tune if gates and release notes justify it. |
97
+ | Renderer tokens (`@ponchia/ui/renderer`) | Stable additive | Function names, option names and the `RendererTokens` field names are public; new fields are additive. Colours are returned as `#rrggbb` or `rgba()` literals. The exact Vega/xterm mapping may tune with the token model. |
97
98
  | External renderer themes (`@ponchia/ui/mermaid`, `@ponchia/ui/mermaid.json`, `@ponchia/ui/d2`, `@ponchia/ui/d2.json`, `@ponchia/ui/vega`, `@ponchia/ui/vega.json`) | Stable additive | Theme helper names, JSON shapes, and supported renderer theme slots are public. Values are resolved colours because Mermaid, D2, and Vega cannot consume Bronto CSS variables directly. Exact colours may tune with token changes, but `check:mermaid`, `check:d2`, and `check:vega` must prove every exported theme resolves with no `var()` leaks. No renderer runtime ships. |
98
99
  | Shiki theme data (`@ponchia/ui/shiki/nothing.json`) | Stable additive | The bundled Shiki theme JSON shape and token-derived scope roles are public for syntax-highlighting consumers. Exact colours may tune with the token model and must stay generated from the governed palette. |
99
100
  | Reports (`css/report.css`, `.ui-report*`, print utilities) | Stable additive | Report class names, BEM part names, and print utility names are public. Report CSS is opt-in and not imported by the default bundle. The data key now lives in the standalone Legends layer (below), not `css/report.css`; charting is via the Vega theme target (`@ponchia/ui/vega`, see [vega](./vega.md)) or a token-themed inline SVG, not a shipped renderer. |
package/docs/theming.md CHANGED
@@ -309,9 +309,11 @@ you have, so the one-accent discipline holds.
309
309
 
310
310
  ## Data-viz palette
311
311
 
312
- Opt-in Tier-4 chart colours for dashboards — **charts only, never UI chrome**
313
- (a build gate fails on `var(--chart-*)` in component CSS), and never in the
314
- default bundle.
312
+ Opt-in Tier-4 categorical colour — **never UI chrome** (a build gate fails on
313
+ `var(--chart-*)` or `var(--cat-*)` in component CSS), and never in the default
314
+ bundle. One leaf carries eight fixed hues in two namespaces: `--chart-*` for
315
+ data-viz series and ramps, and `--cat-*` for categorical **identity** — a tag,
316
+ a participant, a user-chosen tint.
315
317
 
316
318
  ```html
317
319
  <link rel="stylesheet" href="@ponchia/ui/css/dataviz.css" />
@@ -320,28 +322,36 @@ default bundle.
320
322
  ```js
321
323
  // resolved hex for canvas / SVG / Chart.js etc.
322
324
  import charts from '@ponchia/ui/charts.json' with { type: 'json' };
323
- const series = charts.dark.categorical; // ['#ff3b41', '#e69f00', …] — series 0 = accent
325
+ const series = charts.dark.categorical; // ['#3987e5', '#d95926', …] — blue first
324
326
  ```
325
327
 
326
- - **Categorical `--chart-1..8`** — hybrid accent-led: series 1 is the live
327
- `var(--accent)` (your brand leads), series 2–8 are the Okabe-Ito
328
- colourblind-safe set. The set is **gated for mutual distinguishability under
329
- normal + simulated protanopia/deuteranopia/tritanopia** (OKLab ΔE).
330
- **Caveat — the CVD gate measures the SHIPPED default accent.** Series 1 is
331
- `var(--accent)`, so if you re-skin `--accent` you change series 1 but not the
332
- Okabe-Ito 2–8, and the gate never re-checks your custom hue: a brand close to
333
- series 3's orange can collide for a deuteranope. If a re-brand drives data-viz,
334
- re-verify your accent against the set, or pin `--chart-1` to a fixed Okabe-Ito
335
- value (`--chart-1: #0072b2`) and let your brand lead the UI only.
336
- - **Sequential `--chart-seq-1..6`** — single-hue light→dark, for
337
- heatmaps/intensity. **Diverging `--chart-div-1..7`** — blue↔neutral↔orange,
338
- for ±/gains-losses.
328
+ For a page that switches theme, skin, contrast or the OLED surface at runtime,
329
+ read the live values with [`@ponchia/ui/renderer`](renderer.md) instead of the
330
+ static JSON.
331
+
332
+ - **Categorical `--chart-1..8` = `--cat-1..8`** — blue, orange, aqua, yellow,
333
+ magenta, green, violet, red, in that fixed order (`CATEGORICAL_HUES` names
334
+ them). No slot is the accent, so an ordinary first series never reads as an
335
+ alert. `check:charts` measures each theme against the panel, the page and
336
+ the OLED surfaces: OKLCH lightness inside the theme's band, chroma above the
337
+ grey floor, adjacent slots separated under simulated protanopia and
338
+ deuteranopia and in normal vision. Slots under 3:1 against a surface are
339
+ reported in the gate output; relief is the pattern fill or a direct label.
340
+ Any two slots can meet in a scatter or a map, so pair colour with pattern
341
+ there.
342
+ - **Identity `--cat-N-tint` / `--cat-N-ink`** — a 16% wash of the hue over
343
+ `--panel` (it follows a skin's or OLED's panel) and a text colour that holds
344
+ 4.5:1 on the panel, the page and its own tint. Use them for a tag chip, a
345
+ participant's name, or a user-chosen highlight — never for status.
346
+ - **Sequential `--chart-seq-1..5`** — one blue hue; step 1 sits nearest the
347
+ surface (pale in light, deep in dark), for heatmaps/intensity. **Diverging
348
+ `--chart-div-1..7`** — blue↔neutral↔orange, for ±/gains-losses.
339
349
  - **Pattern fills `--chart-pattern-1..8`** — a dot-matrix second channel so
340
350
  colour is never the sole signal (WCAG 1.4.1). Pair colour N with pattern N:
341
351
  `background: var(--chart-2); background-image: var(--chart-pattern-2); background-size: var(--chart-pattern-size); --chart-pattern-ink: rgb(0 0 0 / .34);`
342
352
  - A chart colour's WCAG ratio vs the background is published **advisory** in
343
- [contrast.md](contrast.md) (a fill is not body text) — pick a darker series
344
- for thin lines/points, or lean on the pattern.
353
+ [contrast.md](contrast.md) (a fill is not body text) — for thin lines or
354
+ points use the slot's `--cat-N-ink`, or lean on the pattern.
345
355
 
346
356
  ## Accessibility markup contracts
347
357
 
package/docs/usage.md CHANGED
@@ -584,18 +584,22 @@ phosphor-green | e-ink"` — a **root-level** colorway (apply on `<html>`, like
584
584
 
585
585
  `@ponchia/ui/css/dataviz.css` (opt-in) adds a Tier-4 chart palette for
586
586
  dashboards: `--chart-1..8` (categorical), `--chart-seq-*` (sequential),
587
- `--chart-div-*` (diverging), and `--chart-pattern-1..8` (dot-matrix fills).
588
-
589
- - **Use it for charts only.** These are not UI tokens — a build gate fails if
590
- `var(--chart-*)` appears in component CSS. Style buttons/badges with the
591
- accent/status tiers, not chart colours.
592
- - **Series 1 is the accent**, so your brand leads the palette; series 2–8 are a
593
- colourblind-safe set (gated for distinctness under protan/deutan/tritan).
587
+ `--chart-div-*` (diverging), and `--chart-pattern-1..8` (dot-matrix fills), plus
588
+ the same eight hues as categorical identity: `--cat-N`, `--cat-N-tint` and
589
+ `--cat-N-ink` for tags, participants and user-chosen tints.
590
+
591
+ - **Use it for categories, never for chrome or status.** A build gate fails if
592
+ `var(--chart-*)` or `var(--cat-*)` appears in component CSS. Style buttons
593
+ and badges with the accent/status tiers.
594
+ - **No slot is the accent.** The order is fixed (blue, orange, aqua, yellow,
595
+ magenta, green, violet, red) and adjacent slots are gated for separation
596
+ under simulated protanopia/deuteranopia and in normal vision.
594
597
  - **Always pair colour with pattern** (`--chart-pattern-N`) and/or a direct
595
598
  label — never colour alone (WCAG 1.4.1):
596
599
  `background: var(--chart-3); background-image: var(--chart-pattern-3); background-size: var(--chart-pattern-size);`
597
600
  - **In JS** (Chart.js, canvas, SVG): import resolved hex from
598
- `@ponchia/ui/charts.json` (`{ light, dark }`, series 1 = the resolved accent).
601
+ `@ponchia/ui/charts.json` (`{ hues, light, dark }`), or read the live page
602
+ with [`@ponchia/ui/renderer`](renderer.md) when it can change skin or theme.
599
603
  Cap a chart at ~8 series. Full detail in [theming.md](theming.md) →
600
604
  "Data-viz palette".
601
605
 
package/docs/vega.md CHANGED
@@ -113,18 +113,23 @@ colours are **baked into the output** and parsed by `d3-color`, which understand
113
113
  real hex/rgb but **not** `var()` (nor `oklch()`). So the config ships **resolved
114
114
  hex per theme**, projected from the same token source as
115
115
  [`tokens/resolved.json`](./architecture.md) / [`charts.json`](./theming.md).
116
- Re-call `brontoVegaConfig()` when the theme toggles and re-embed.
116
+ Re-call `brontoVegaConfig()` when the theme toggles and re-embed. A page that
117
+ switches skin, contrast or the OLED surface at runtime cannot be served by a
118
+ per-theme snapshot: build the config from the live page with
119
+ [`@ponchia/ui/renderer`](./renderer.md) — `vegaConfig(readTokens())` is the
120
+ same mapping these files are generated from.
117
121
 
118
122
  ### What the slots paint
119
123
 
120
- The config keeps a chart **monochrome by default** — the rationed accent is the
121
- one chromatic default (series 1 / the lone mark), never the chrome:
124
+ The chrome stays quiet and neutral; colour is spent on data. The plot has no
125
+ frame (a chart already sits on a panel), and a single series takes the first
126
+ categorical hue rather than the alert accent:
122
127
 
123
128
  | Slot | Paint | bronto token |
124
129
  | --- | --- | --- |
125
- | `background` | Chart canvas | `--bg` |
126
- | `view.stroke` | Plot frame | `--line` |
127
- | `mark.color` | Default / single-series mark | `--accent` |
130
+ | `background` | Chart canvas | `--bg` (runtime default: transparent) |
131
+ | `view.stroke` | Plot frame | none (`null`) |
132
+ | `mark.color` | Default / single-series mark | `--chart-1` |
128
133
  | `rule.color` | Reference rules, annotations | `--line-strong` |
129
134
  | `axis.domainColor` · `tickColor` | Axis line · ticks | `--line-strong` |
130
135
  | `axis.gridColor` | Gridlines | `--line` |
@@ -132,7 +137,8 @@ one chromatic default (series 1 / the lone mark), never the chrome:
132
137
  | `text.color` | Free `text`/`label` marks | `--text` |
133
138
  | `legend.*` · `header.*` · `title.*` | Legend, facet headers, title | `--text-soft` / `--text` / `--text-dim` |
134
139
  | `*.font` / `*Font` | All text | `--sans` |
135
- | `range.category` | 8-series categorical palette | `charts.json` categorical (series 1 = accent) |
140
+ | `rect`/`arc`/`area` `.stroke` | Gap between adjacent fills | `--panel` |
141
+ | `range.category` | 8-series categorical palette | `charts.json` categorical (blue first) |
136
142
  | `range.ordinal` · `ramp` · `heatmap` | Single-hue sequential ramp | `charts.json` sequential |
137
143
  | `range.diverging` | − … neutral … + ramp | `charts.json` diverging |
138
144
 
@@ -143,14 +149,12 @@ series needs the redundant second channel, drive the mark's fill from the
143
149
 
144
150
  ### Spending the accent
145
151
 
146
- Series 1 of `range.category` resolves to the accent (per theme), so a single-series
147
- chart and the first category carry the accent automatically — baked into the
148
- generated `config`, so regenerate the config and re-render to change it (Vega output
149
- does not live-reskin from `--accent`). To emphasise one mark in a
150
- multi-series chart, paint just that mark with the accent and leave the rest
151
- neutral — the same "reserve the accent for the one thing a reader must not miss"
152
- rule the rest of the system follows. Two small helpers hand you the exact
153
- per-theme hexes so you never hard-code a palette array index:
152
+ No categorical slot is the accent, so an ordinary chart never reads as an
153
+ alert. To emphasise one mark, paint just that mark with the accent and leave
154
+ the rest neutral — the same "reserve the accent for the one thing a reader must
155
+ not miss" rule the rest of the system follows. Two small helpers hand you the
156
+ exact per-theme hexes (baked into the generated files; Vega output does not
157
+ live-reskin from `--accent`):
154
158
 
155
159
  ```js
156
160
  import { brontoVegaAccent, brontoVegaNeutral } from '@ponchia/ui/vega';
@@ -171,14 +175,11 @@ const spec = {
171
175
  };
172
176
  ```
173
177
 
174
- `brontoVegaAccent(theme)` is `range.category[0]` (the resolved accent) and
175
- `brontoVegaNeutral(theme)` is the last category (the quiet neutral); re-read both
176
- when the theme toggles. Prefer them over digging the hex out of
177
- `tokens/resolved.json` — they are guaranteed to match the palette the config
178
- already ships. In token terms the accent is `--chart-1` and the neutral is
179
- `--chart-8`, so a [legend](./legends.md#swatch-colour) for an accent-rationed
180
- chart keys those two series with `ui-legend__swatch--1` and
181
- `ui-legend__swatch--8` — the swatches mirror the marks exactly.
178
+ `brontoVegaAccent(theme)` is the resolved `--accent` and `brontoVegaNeutral(theme)`
179
+ the resolved `--text-dim`; re-read both when the theme toggles. A
180
+ [legend](./legends.md#swatch-colour) for an accent-rationed chart keys the two
181
+ with inline swatch colours (`style="--chart-color: …"`), not with categorical
182
+ slots.
182
183
 
183
184
  ### Selecting the themed ramp in a spec
184
185
 
package/llms.txt CHANGED
@@ -45,7 +45,7 @@ the path changes from source `css/` to built `dist/css/`:
45
45
  <!-- installed locally -->
46
46
  <link rel="stylesheet" href="./node_modules/@ponchia/ui/dist/css/<leaf>.css" />
47
47
  <!-- or from a CDN; pin the version (pre-1.0, breaking changes ship in the minor) -->
48
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.11.0/dist/css/<leaf>.css" />
48
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.12.0/dist/css/<leaf>.css" />
49
49
  ```
50
50
 
51
51
  The flattened default bundle is `dist/bronto.css` (bundler shorthand
@@ -183,7 +183,9 @@ Charting is the same path: bronto does NOT ship a chart component (a chart needs
183
183
  scales + data binding, which the analytical layer refuses). For charts, recommend
184
184
  Vega-Lite — a declarative JSON spec an external system can emit — themed by the
185
185
  on-brand `config` (resolved hex; Vega bakes colours into SVG/canvas, can't read
186
- `var()`). `range.category` is the `--chart-*` palette, series 1 = accent:
186
+ `var()`). `range.category` is the `--chart-*` palette (blue first; no slot is the
187
+ accent). For a live page that switches skin or theme, build the same config at
188
+ runtime with `vegaConfig(readTokens())` from `@ponchia/ui/renderer`:
187
189
 
188
190
  ```js
189
191
  import { brontoVegaConfig, brontoVegaAccent, brontoVegaNeutral } from '@ponchia/ui/vega';
@@ -204,8 +206,10 @@ accent-filled DOM control, set `--button-text`. Details: `docs/vega.md`. (Observ
204
206
  Plot works too — it inherits the page CSS, so it needs even less theming;
205
207
  Vega-Lite is the recommended LLM-emittable path.)
206
208
 
207
- `--chart-1..8` (categorical; series 1 = accent; colourblind-safe, gated under
208
- simulated protan/deutan/tritan), `--chart-seq-*` (sequential), `--chart-div-*`
209
+ `--chart-1..8` (categorical: blue, orange, aqua, yellow, magenta, green, violet,
210
+ red; adjacent slots gated under simulated protan/deutan), `--cat-N` /
211
+ `--cat-N-tint` / `--cat-N-ink` (the same hues as tag/participant identity),
212
+ `--chart-seq-*` (sequential), `--chart-div-*`
209
213
  (diverging), and `--chart-pattern-1..8` (dot-matrix fills — pair colour N with
210
214
  pattern N; colour is never the sole signal). Details in `docs/theming.md`.
211
215
 
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@ponchia/ui",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "type": "module",
5
- "description": "CSS-first identity and UI layer for services, tools, sites, and reports \u2014 works in HTML, every framework, and PDF, no component runtime. Shared app shell, forms, tables, workflow chrome, plus opt-in analytical/report primitives. Monochrome with one rationed accent. Zero runtime dependencies.",
5
+ "description": "CSS-first identity and UI layer for services, tools, sites, and reports — works in HTML, every framework, and PDF, no component runtime. Shared app shell, forms, tables, workflow chrome, plus opt-in analytical/report primitives. Monochrome with one rationed accent. Zero runtime dependencies.",
6
6
  "keywords": [
7
7
  "css",
8
8
  "ui",
@@ -58,6 +58,7 @@
58
58
  "schemas",
59
59
  "annotations",
60
60
  "connectors",
61
+ "renderer",
61
62
  "shiki",
62
63
  "llms.txt",
63
64
  "CHANGELOG.md",
@@ -82,6 +83,7 @@
82
83
  "docs/legends.md",
83
84
  "docs/marks.md",
84
85
  "docs/connectors.md",
86
+ "docs/renderer.md",
85
87
  "docs/spotlight.md",
86
88
  "docs/crosshair.md",
87
89
  "docs/selection.md",
@@ -119,7 +121,8 @@
119
121
  "docs/adr/0005-productive-tools-and-editorial-reports.md",
120
122
  "docs/migrations/0.9-to-0.10.md",
121
123
  "docs/adr/0006-trusted-publishing.md",
122
- "docs/migrations/0.10-to-0.11.md"
124
+ "docs/migrations/0.10-to-0.11.md",
125
+ "docs/migrations/0.11-to-0.12.md"
123
126
  ],
124
127
  "style": "./dist/bronto.css",
125
128
  "scripts": {
@@ -364,6 +367,7 @@
364
367
  "./docs/legends.md": "./docs/legends.md",
365
368
  "./docs/marks.md": "./docs/marks.md",
366
369
  "./docs/connectors.md": "./docs/connectors.md",
370
+ "./docs/renderer.md": "./docs/renderer.md",
367
371
  "./docs/spotlight.md": "./docs/spotlight.md",
368
372
  "./docs/crosshair.md": "./docs/crosshair.md",
369
373
  "./docs/selection.md": "./docs/selection.md",
@@ -500,6 +504,10 @@
500
504
  "types": "./connectors/index.d.ts",
501
505
  "default": "./connectors/index.js"
502
506
  },
507
+ "./renderer": {
508
+ "types": "./renderer/index.d.ts",
509
+ "default": "./renderer/index.js"
510
+ },
503
511
  "./skins": {
504
512
  "types": "./tokens/skins.d.ts",
505
513
  "default": "./tokens/skins.js"
@@ -530,6 +538,7 @@
530
538
  "./docs/migrations/0.9-to-0.10.md": "./docs/migrations/0.9-to-0.10.md",
531
539
  "./docs/adr/0006-trusted-publishing.md": "./docs/adr/0006-trusted-publishing.md",
532
540
  "./docs/migrations/0.10-to-0.11.md": "./docs/migrations/0.10-to-0.11.md",
541
+ "./docs/migrations/0.11-to-0.12.md": "./docs/migrations/0.11-to-0.12.md",
533
542
  "./css/discussion.css": "./dist/css/discussion.css",
534
543
  "./css/unlayered/discussion.css": "./css/discussion.css",
535
544
  "./docs/discussion.md": "./docs/discussion.md"