@ponchia/ui 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +552 -8
- package/MIGRATIONS.json +106 -0
- package/README.md +34 -8
- package/annotations/index.d.ts +402 -0
- package/annotations/index.d.ts.map +1 -0
- package/annotations/index.js +792 -0
- package/behaviors/carousel.js +198 -0
- package/behaviors/combobox.js +226 -0
- package/behaviors/command.js +190 -0
- package/behaviors/connectors.js +95 -0
- package/behaviors/crosshair.js +57 -0
- package/behaviors/dialog.js +74 -0
- package/behaviors/disclosure.js +26 -0
- package/behaviors/dismissible.js +25 -0
- package/behaviors/forms.js +186 -0
- package/behaviors/glyph.js +108 -0
- package/behaviors/index.d.ts +79 -0
- package/behaviors/index.js +18 -1409
- package/behaviors/internal.js +97 -0
- package/behaviors/legend.js +67 -0
- package/behaviors/menu.js +47 -0
- package/behaviors/popover.js +179 -0
- package/behaviors/spotlight.js +52 -0
- package/behaviors/table.js +136 -0
- package/behaviors/tabs.js +103 -0
- package/behaviors/theme.js +84 -0
- package/behaviors/toast.js +164 -0
- package/classes/classes.json +1857 -0
- package/classes/index.d.ts +306 -13
- package/classes/index.js +339 -12
- package/classes/vscode.css-custom-data.json +12 -0
- package/connectors/index.d.ts +191 -0
- package/connectors/index.d.ts.map +1 -0
- package/connectors/index.js +275 -0
- package/css/analytical.css +21 -0
- package/css/annotations.css +292 -0
- package/css/app.css +43 -13
- package/css/base.css +15 -10
- package/css/command.css +97 -0
- package/css/connectors.css +110 -0
- package/css/content.css +7 -1
- package/css/crosshair.css +100 -0
- package/css/dataviz.css +5 -1
- package/css/disclosure.css +38 -6
- package/css/dots.css +57 -0
- package/css/feedback.css +111 -2
- package/css/fonts.css +11 -7
- package/css/forms.css +42 -1
- package/css/generated.css +117 -0
- package/css/legend.css +272 -0
- package/css/marks.css +174 -0
- package/css/motion.css +24 -44
- package/css/navigation.css +7 -0
- package/css/overlay.css +31 -1
- package/css/primitives.css +109 -5
- package/css/report.css +39 -81
- package/css/selection.css +46 -0
- package/css/site.css +16 -2
- package/css/sources.css +221 -0
- package/css/spotlight.css +104 -0
- package/css/state.css +121 -0
- package/css/tokens.css +60 -37
- package/css/workbench.css +83 -0
- package/dist/bronto.css +1 -1
- package/dist/css/analytical.css +1 -0
- package/dist/css/annotations.css +1 -0
- package/dist/css/app.css +1 -1
- package/dist/css/base.css +1 -1
- package/dist/css/command.css +1 -0
- package/dist/css/connectors.css +1 -0
- package/dist/css/content.css +1 -1
- package/dist/css/crosshair.css +1 -0
- package/dist/css/disclosure.css +1 -1
- package/dist/css/dots.css +1 -1
- package/dist/css/feedback.css +1 -1
- package/dist/css/fonts.css +1 -1
- package/dist/css/forms.css +1 -1
- package/dist/css/generated.css +1 -0
- package/dist/css/legend.css +1 -0
- package/dist/css/marks.css +1 -0
- package/dist/css/motion.css +1 -1
- package/dist/css/navigation.css +1 -1
- package/dist/css/overlay.css +1 -1
- package/dist/css/primitives.css +1 -1
- package/dist/css/report.css +1 -1
- package/dist/css/selection.css +1 -0
- package/dist/css/site.css +1 -1
- package/dist/css/sources.css +1 -0
- package/dist/css/spotlight.css +1 -0
- package/dist/css/state.css +1 -0
- package/dist/css/tokens.css +1 -1
- package/dist/css/workbench.css +1 -0
- package/docs/adr/0003-theme-model.md +7 -4
- package/docs/annotations.md +425 -0
- package/docs/architecture.md +246 -0
- package/docs/command.md +95 -0
- package/docs/connectors.md +91 -0
- package/docs/contrast.md +116 -92
- package/docs/crosshair.md +63 -0
- package/docs/d2.md +195 -0
- package/docs/generated.md +91 -0
- package/docs/legends.md +184 -0
- package/docs/marks.md +93 -0
- package/docs/mermaid.md +152 -0
- package/docs/reference.md +385 -23
- package/docs/reporting.md +436 -63
- package/docs/selection.md +40 -0
- package/docs/sources.md +137 -0
- package/docs/spotlight.md +78 -0
- package/docs/stability.md +24 -2
- package/docs/state.md +85 -0
- package/docs/usage.md +123 -4
- package/docs/vega.md +225 -0
- package/docs/workbench.md +78 -0
- package/fonts/doto-400.woff2 +0 -0
- package/fonts/doto-500.woff2 +0 -0
- package/fonts/doto-600.woff2 +0 -0
- package/fonts/doto-700.woff2 +0 -0
- package/fonts/doto-800.woff2 +0 -0
- package/fonts/doto-900.woff2 +0 -0
- package/glyphs/glyphs.js +6 -4
- package/llms.txt +362 -14
- package/package.json +115 -12
- package/qwik/index.d.ts +42 -54
- package/qwik/index.d.ts.map +1 -0
- package/qwik/index.js +75 -3
- package/react/index.d.ts +39 -56
- package/react/index.d.ts.map +1 -0
- package/react/index.js +67 -3
- package/solid/index.d.ts +64 -56
- package/solid/index.d.ts.map +1 -0
- package/solid/index.js +70 -3
- package/tokens/d2.d.ts +38 -0
- package/tokens/d2.js +71 -0
- package/tokens/d2.json +43 -0
- package/tokens/index.d.ts +5 -5
- package/tokens/index.js +23 -5
- package/tokens/index.json +9 -0
- package/tokens/mermaid.d.ts +23 -0
- package/tokens/mermaid.js +181 -0
- package/tokens/mermaid.json +163 -0
- package/tokens/resolved.json +45 -1
- package/tokens/skins.js +3 -2
- package/tokens/tokens.dtcg.json +26 -0
- package/tokens/vega.d.ts +34 -0
- package/tokens/vega.js +155 -0
- package/tokens/vega.json +179 -0
- package/fonts/doto-400.ttf +0 -0
- package/fonts/doto-500.ttf +0 -0
- package/fonts/doto-600.ttf +0 -0
- package/fonts/doto-700.ttf +0 -0
- package/fonts/doto-800.ttf +0 -0
- package/fonts/doto-900.ttf +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,556 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
> **Versioning:** pre-1.0, breaking changes ship in the _minor_. Pin
|
|
4
|
-
> `~0.
|
|
3
|
+
> **Versioning:** pre-1.0, breaking changes ship in the _minor_. Pin to the
|
|
4
|
+
> minor — `~0.4.0` (equivalently `^0.4.0`) resolves to `>=0.4.0 <0.5.0`; a bare
|
|
5
|
+
> `^0` / `*` wildcard does **not** protect you. See README → Versioning, and
|
|
5
6
|
> the deprecation policy in CONTRIBUTING.md.
|
|
6
7
|
|
|
8
|
+
## 0.6.0 — 2026-06-03
|
|
9
|
+
|
|
10
|
+
Accumulates the post-0.5.0 work: a multi-agent audit pass (accessibility
|
|
11
|
+
hardening, a behavior/binding scope-safety fix, codegen/gate tightening) plus a
|
|
12
|
+
**breaking** charting realignment. The local static-bar renderer
|
|
13
|
+
(`.ui-chart*`) is **removed** — a chart needs scales + data binding, which the
|
|
14
|
+
analytical layer refuses to own. In its place, bronto becomes a themeable target
|
|
15
|
+
for **Vega-Lite** (`@ponchia/ui/vega`), the same tokens-as-data path as Mermaid
|
|
16
|
+
and D2. The data-viz **palette** (`--chart-*`, `tokens/charts.json`) and the
|
|
17
|
+
**legend** layer are unchanged. Pin `~0.5` → re-pin `~0.6`; see
|
|
18
|
+
[`MIGRATIONS.json`](./MIGRATIONS.json) (`0.5`→`0.6`).
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **`@ponchia/ui/vega`** (+ `vega.json`) — an on-brand Vega-Lite / Vega
|
|
23
|
+
[`config`](https://vega.github.io/vega-lite/docs/config.html) resolved per
|
|
24
|
+
theme (the idiomatic `vega-themes` shape): monochrome chrome + one rationed
|
|
25
|
+
accent, `range.category/ordinal/ramp/heatmap/diverging` from the CVD-safe
|
|
26
|
+
data-viz palette. `brontoVegaConfig(theme)`. Resolved hex (Vega bakes colours
|
|
27
|
+
into SVG/canvas, can't read `var()`); gated structurally **and** by a headless
|
|
28
|
+
render-probe that asserts the colours land on a rendered chart. Vega is the
|
|
29
|
+
consumer's renderer — config only, not a dependency. See `docs/vega.md`.
|
|
30
|
+
- **`ui-delta`** — a standalone trend/change indicator (core primitive): an
|
|
31
|
+
arrow glyph (the non-colour channel) plus the figure, with
|
|
32
|
+
`--up`/`--down`/`--flat`, and `--invert` to swap only the tone when "up" is
|
|
33
|
+
the bad direction (latency, error rate, cost). `ui.delta({ dir, invert })`.
|
|
34
|
+
- **`ui-compare`** — a fluid side-by-side / before-after layout for the report
|
|
35
|
+
layer (`css/report.css`): `__col`, `__head`, and `--2up`.
|
|
36
|
+
`ui.compare({ cols })`.
|
|
37
|
+
- **`@ponchia/ui/classes.json`** — the class vocabulary as language-neutral
|
|
38
|
+
data (`groups`/`classes`/`states`/`customProperties`), so a non-JS/non-TS
|
|
39
|
+
host or an external linter can validate emitted markup without executing the
|
|
40
|
+
ESM `cls` map or parsing the `.d.ts`. Generated from `cls`; drift-checked and
|
|
41
|
+
its `states`/`customProperties` gated against the stylesheet.
|
|
42
|
+
- **`tokens/resolved.json` `scale` block** — the resolved non-colour scales
|
|
43
|
+
(spacing/radius/type/z/motion, `var()` chains flattened), completing the
|
|
44
|
+
token contract for non-CSS hosts (previously colour-only).
|
|
45
|
+
- **`--display-weight` / `--display-weight-strong`** (700 / 800) — the weight of
|
|
46
|
+
the Doto dot-matrix display face, now a token. Themes/skins can re-tune how
|
|
47
|
+
heavy display text renders in one place.
|
|
48
|
+
- On-brand **Mermaid** (`@ponchia/ui/mermaid`, `mermaid.json`) and **D2**
|
|
49
|
+
(`@ponchia/ui/d2`, `d2.json`) theme maps — resolved per-theme palettes
|
|
50
|
+
projected from the same tokens, gated. Diagrams stay the consumer's renderer;
|
|
51
|
+
these are config only.
|
|
52
|
+
- Annotation geometry options: `connectorElbow({ mid })` (turn position along the
|
|
53
|
+
dominant axis), `notePlacement({ inset })` (reserve the title stroke-halo so a
|
|
54
|
+
placement that "fits" doesn't clip), and a `spread` half-angle on both
|
|
55
|
+
`connectorEndArrow` and the shared `arrowHead` kernel.
|
|
56
|
+
- **`brontoVegaAccent(theme)` / `brontoVegaNeutral(theme)`** (`@ponchia/ui/vega`)
|
|
57
|
+
— the exact per-theme hexes for `range.category`'s accent (series 1) and
|
|
58
|
+
neutral (last series), so spending the accent on one emphasised mark needs no
|
|
59
|
+
palette-index reverse-engineering.
|
|
60
|
+
- **`--on-accent`** token — the readable ink for a label on **any accent fill**
|
|
61
|
+
(button, badge, themed chart bar, a Vega/D2 node). Resolves to `--button-text`
|
|
62
|
+
(white on the light accent, black on the dark) and is gated ≥ 4.5:1 in
|
|
63
|
+
`docs/contrast.md`. Use it instead of `--accent-text`, which is the inverse
|
|
64
|
+
(accent-coloured text for a *neutral* background, ~1.3:1 on an accent fill).
|
|
65
|
+
- **`.ui-src`** standalone trust pill (`cls.src`, `css/sources.css`) — wears a
|
|
66
|
+
`.ui-src--*` tone (verified / reviewed / generated / unverified / stale /
|
|
67
|
+
conflict) on its own, for a bare trust label outside a citation or source card.
|
|
68
|
+
Previously the `.ui-src--*` modifiers only painted a `--src-tone` with no
|
|
69
|
+
standalone host, so a lone pill validated against `classes.json` yet rendered
|
|
70
|
+
nothing.
|
|
71
|
+
|
|
72
|
+
### Removed
|
|
73
|
+
|
|
74
|
+
- **BREAKING: the local static bar-chart renderer (`.ui-chart`, `.ui-chart__plot`,
|
|
75
|
+
`__bar`, `__label`, `__track`, `__fill`, `__fallback`, `__caption`).** A chart
|
|
76
|
+
needs scales and data binding — out of scope for a CSS-first analytical layer
|
|
77
|
+
(ADR-0002). Replace with a Vega-Lite chart themed via `@ponchia/ui/vega`, or a
|
|
78
|
+
hand-authored token-themed inline `<svg>`, inside a `.ui-report__figure` with a
|
|
79
|
+
`.ui-report__caption` and a `.ui-legend` key. The `--chart-value` inline knob
|
|
80
|
+
is gone; the `--chart-color`/`--chart-pattern` swatch knobs remain (legend).
|
|
81
|
+
See `MIGRATIONS.json` (`0.5`→`0.6`) and `docs/vega.md`.
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- **Annotation connectors are crisper.** `connectorEndArrow` now defaults to a
|
|
86
|
+
sharper head (half-angle 0.32 ≈ 37°, size 8 vs the former blunt 0.45 / 7).
|
|
87
|
+
Author-facing geometry only; the `arrowHead` kernel default is unchanged, so
|
|
88
|
+
node-connector arrowheads don't move.
|
|
89
|
+
|
|
90
|
+
### Accessibility
|
|
91
|
+
|
|
92
|
+
- **Coarse-pointer tap-target floors extended to navigation.** The 2.9 rem
|
|
93
|
+
touch floor (already on primitives/forms/feedback) now also covers
|
|
94
|
+
`.ui-sitenav a`, `.ui-app-nav a`, `.ui-sitemenu > summary`, and
|
|
95
|
+
`.ui-themetoggle__button` under `@media (pointer: coarse)` — the primary nav
|
|
96
|
+
affordances were below the 44 px target on touch.
|
|
97
|
+
- **App shell uses dynamic viewport units.** `100vh` → `100dvh` (shell/body) and
|
|
98
|
+
the scrolling rail → `100svh`, so the rail and its pinned account/footer no
|
|
99
|
+
longer fall under the mobile URL bar.
|
|
100
|
+
- **Forced-colors status dots stay distinct.** `.ui-dot--success/--warning/--danger/--info`
|
|
101
|
+
and `.ui-dotmatrix__cell--hot/--accent` now map to distinct system colors
|
|
102
|
+
under Windows High Contrast instead of collapsing to one — the only signal
|
|
103
|
+
these carry is colour.
|
|
104
|
+
- **Keyboard affordance parity.** `.ui-menu__item:focus-visible` gets the same
|
|
105
|
+
row highlight as hover; the segmented control's focus ring is now inset so the
|
|
106
|
+
container's `overflow: hidden` no longer clips it.
|
|
107
|
+
- **Reduced-motion skeleton.** `.ui-skeleton` flattens to a solid placeholder
|
|
108
|
+
under `prefers-reduced-motion` instead of freezing mid-shimmer.
|
|
109
|
+
|
|
110
|
+
### Fixed
|
|
111
|
+
|
|
112
|
+
- **Published-type drift (code-quality audit).** `ui.meter({ tone: 'info' })` and
|
|
113
|
+
`ui.bracketNote({ tone: 'success' })` emit real classes at runtime, but the
|
|
114
|
+
generated `.d.ts` tone unions (hand-mirrored in `gen-dts.mjs`) omitted them, so
|
|
115
|
+
a TS consumer got a spurious type error for a value that renders. The unions
|
|
116
|
+
now match the factory; a new `check:recipe-types` gate cross-checks every
|
|
117
|
+
factory's string-literal options against its `*Opts` union so this whole class
|
|
118
|
+
of drift fails CI.
|
|
119
|
+
- **Component-library audit (16-agent dogfood pass) — the validates-but-no-ops
|
|
120
|
+
cluster.** A whole-surface audit found the meter-style trap (a class/token that
|
|
121
|
+
validates and paints but silently does nothing without an undocumented
|
|
122
|
+
precondition) recurring across components. Fixed:
|
|
123
|
+
- `aria-disabled="true"` on `.ui-button` / `.ui-link` now sets
|
|
124
|
+
`pointer-events: none` — it looked dead but a real `<a>` still navigated.
|
|
125
|
+
- Disabled affordance reaches the controls that wrap a native input
|
|
126
|
+
(`.ui-switch` / `.ui-check` / `.ui-segmented__option` via `:has(input:disabled)`,
|
|
127
|
+
plus `.ui-range` / `.ui-file`) — they previously looked operable and their
|
|
128
|
+
label kept `cursor: pointer`.
|
|
129
|
+
- Bare `[aria-current]` selectors (`.ui-sitenav`, `.ui-breadcrumb__item`) now
|
|
130
|
+
scope `:not([aria-current='false'])`, so a correctly-authored
|
|
131
|
+
`aria-current="false"` link is no longer styled as current.
|
|
132
|
+
- The active-tab forced-colors re-assert moved from `base.css` to
|
|
133
|
+
`disclosure.css` (after the default rule) — an earlier bundle leaf let the
|
|
134
|
+
accent default override it, so the selected tab lost its only HC cue.
|
|
135
|
+
- `.ui-meter__fill` / `.ui-progress__bar` get a system colour under
|
|
136
|
+
`forced-colors`, so the measured proportion stays visible.
|
|
137
|
+
- `.ui-search` gains a 2px keyboard focus ring to match every sibling input
|
|
138
|
+
(it had only a 1px border-colour shift).
|
|
139
|
+
- `.ui-prose` gets `overflow-wrap: break-word` — long tokens in
|
|
140
|
+
machine-generated Markdown forced horizontal page scroll.
|
|
141
|
+
- `.ui-mark--draw` is scoped to fill styles (`:not(--underline, --box, --strike)`)
|
|
142
|
+
so it no longer looks applied while doing nothing.
|
|
143
|
+
- `.ui-cq` hardcodes its container-name (the `@container bronto` collapse
|
|
144
|
+
queries hardcode it, so a `--cq-name` override silently killed the collapse).
|
|
145
|
+
- `initPopover()` seeds resting ARIA (`aria-haspopup`, `aria-controls`,
|
|
146
|
+
`aria-expanded`) and syncs `aria-expanded` when the UA closes a native
|
|
147
|
+
popover; `toast()` validates `tone` (an unknown string rendered an unstyled
|
|
148
|
+
neutral toast) and warns; the combobox listbox gets an accessible name.
|
|
149
|
+
- `.ui-error-summary__title` uses the legible sans, not the low-legibility Doto
|
|
150
|
+
display face. `.ui-input` / `.ui-search` autofill stays on-theme.
|
|
151
|
+
- `.ui-reveal` hidden state is gated on `scripting: enabled` (genuinely degrades
|
|
152
|
+
visible with no JS; the prior comment lied) — and `ui-scroll-reveal` is the
|
|
153
|
+
documented zero-JS path.
|
|
154
|
+
- Parity modifiers added: `.ui-meter--info`, `.ui-bracket-note--success`.
|
|
155
|
+
- Responsive/mobile hardening across the framework: `rem`-rooted type for WCAG
|
|
156
|
+
1.4.4, coarse-pointer tap-target floors, combobox/tour-note viewport clamps,
|
|
157
|
+
and `@media (hover)` gating — with a new responsive e2e sweep.
|
|
158
|
+
- **Faint numbers on stat cards.** `.ui-stat__value` / `.ui-app-metric__value`
|
|
159
|
+
(and the report cover/section titles, rail brand, panel titles, `.ui-display`,
|
|
160
|
+
`.ui-quote`) set the Doto display face but no weight, so they rendered at the
|
|
161
|
+
thinnest cut (400). They now apply `--display-weight(-strong)` — visibly bolder
|
|
162
|
+
and more legible, on screen and in print.
|
|
163
|
+
- **Painted data surfaces dropped in the PDF.** Headless-Chromium print drops
|
|
164
|
+
backgrounds by default, silently blanking the data-bearing fills. Dot-matrix
|
|
165
|
+
cells, the segmented meter, status dots, masked glyphs, highlight marks,
|
|
166
|
+
connector lines, and progress/meter fills now carry `print-color-adjust: exact`
|
|
167
|
+
so they survive the A4 print/PDF that the report kit targets.
|
|
168
|
+
- **Dark-theme cards/tables printed dark-on-white.** The dark→ink token remap was
|
|
169
|
+
scoped to `.ui-report`; it is now lifted to the print `:root` (in the exempt
|
|
170
|
+
token-definition file), so a bare `.ui-card` / `.ui-statgrid` / `.ui-table` —
|
|
171
|
+
the markup an external LLM emits — also prints legibly.
|
|
172
|
+
- Inline `ui-citation` no longer dumps its full URL mid-sentence when printed
|
|
173
|
+
(the reference list carries the URL); `ui-legend--with-values` values are
|
|
174
|
+
right-aligned for a clean tabular column.
|
|
175
|
+
- **Annotation elbow connector was a 45° chamfer, not a dogleg.**
|
|
176
|
+
`connectorElbow` turned by `min(|dx|,|dy|)`, drawing a diagonal stub the
|
|
177
|
+
`stroke-linejoin` bevel never matched. It now delegates to the connectors
|
|
178
|
+
geometry kernel's right-angle `elbowPath` (H/V/H), so an annotation leader and
|
|
179
|
+
a node connector draw the same elbow.
|
|
180
|
+
- **Scoped behaviors no longer hijack the whole document on a null root.**
|
|
181
|
+
`init*({ root })` with an explicitly-provided-but-unready root (a framework
|
|
182
|
+
ref still `null` at mount, a conditional that hasn't rendered) now no-ops
|
|
183
|
+
instead of silently widening to document-wide delegation. The react/solid/qwik
|
|
184
|
+
bindings emit `root: null` for the not-ready case so the distinction survives
|
|
185
|
+
the boundary; passing no `root` still delegates from `document` exactly as
|
|
186
|
+
before. Affects every delegated behavior (dialog, menu, combobox, …).
|
|
187
|
+
- **`--report-width` / `--report-padding-block` are now declared defaults** on
|
|
188
|
+
`.ui-report` — they were read with inline fallbacks but never declared, so the
|
|
189
|
+
override surface was undiscoverable and `--report-measure` looked like the
|
|
190
|
+
width knob when it isn't.
|
|
191
|
+
- Carousel's IntersectionObserver is now set up and torn down in lockstep with
|
|
192
|
+
its event binding, removing a one-tick window where a re-init left two
|
|
193
|
+
observers on the same slides.
|
|
194
|
+
- **`ui-meter` / `ui-progress` fill painted a 0×0 box.** `.ui-meter__fill` and
|
|
195
|
+
`.ui-progress__bar` set `block-size`/`inline-size` but no `display`, so on the
|
|
196
|
+
documented `<span>` fill (an inline box ignores width/height) the bar rendered
|
|
197
|
+
empty — a "validates-but-renders-nothing" trap the registry and docs both
|
|
198
|
+
hid. They are now `display: block`. Found by a second multi-agent dogfood
|
|
199
|
+
pass; guarded going forward by a render-geometry e2e (below).
|
|
200
|
+
|
|
201
|
+
### Documentation
|
|
202
|
+
|
|
203
|
+
- LLM-authored static reports: a prominent CSS-loading note (bundler vs
|
|
204
|
+
`node_modules` vs CDN) and a copy-pasteable CDN report in
|
|
205
|
+
`docs/reporting.md`; clarified that `dist/bronto.css` does **not** include the
|
|
206
|
+
opt-in report/chart/legend/annotation layers; number/date formatting
|
|
207
|
+
guidance; and a standalone, no-build report reference
|
|
208
|
+
(`demo/report-standalone.html`).
|
|
209
|
+
- Resolved the `is-*` self-contradiction: the framework's own
|
|
210
|
+
`is-num`/`is-pos`/`is-neg`/`is-key`/`is-open` state hooks are valid even
|
|
211
|
+
though they deliberately live outside `cls` (documented in
|
|
212
|
+
`docs/reference.md` and `classes.json`).
|
|
213
|
+
- Clarified two standing contracts in `docs/architecture.md`: `css/analytical.css`
|
|
214
|
+
is the roll-up of exactly the seven figure leaves (annotations, legend, marks,
|
|
215
|
+
connectors, spotlight, crosshair, selection) — `sources`/`state`/`generated`/
|
|
216
|
+
`workbench`/`command` are adjacent leaves imported individually — and the root
|
|
217
|
+
`.` export is CSS-only (no runtime JS at the root). Pre-1.0 stability/pinning
|
|
218
|
+
spelled out in `docs/stability.md`. `docs/workbench.md` notes that
|
|
219
|
+
`.ui-selectionbar` is unrelated to the `.ui-sel--*` selection-emphasis classes.
|
|
220
|
+
- Honest JSDoc limits: combobox/command read options from the DOM at init
|
|
221
|
+
(re-run after replacing them); popover restores focus on Escape but not on
|
|
222
|
+
outside-click; the table sorter is locale-naive display-text; mask-mode glyphs
|
|
223
|
+
are single-tone.
|
|
224
|
+
- **Foreign-renderer recipes hardened after a multi-agent dogfooding pass**
|
|
225
|
+
(build five real reports across the whole stack, review from every POV). The
|
|
226
|
+
Vega CDN recipe now pins the `/build/*.min.js` UMD bundles and `renderer:'svg'`
|
|
227
|
+
(a bare `cdn.jsdelivr.net/npm/vega@6` tag has no `window.vega`, so the previous
|
|
228
|
+
recipe rendered nothing); the file://-portable path (inline the config — an
|
|
229
|
+
imported/fetched config is CORS-blocked from disk) is now explicit. New
|
|
230
|
+
`docs/reporting.md` recipes: "Theming a live report" (the theme-toggle/re-embed
|
|
231
|
+
foot-guns — clear the host, container-width-while-hidden, Mermaid source vs
|
|
232
|
+
output), live charts are `ui-screen-only` while the table prints (a kept live
|
|
233
|
+
chart bakes the on-screen theme), `ui-meter`/`ui-quote` markup, and the
|
|
234
|
+
sequential/diverging frozen-figure ramp. `docs/d2.md` gains a frozen
|
|
235
|
+
inline-`<svg>`-from-slots recipe and on-accent-ink guidance; `docs/vega.md`
|
|
236
|
+
documents the theme-inverting ramp and the OKLCH-vs-d3 gradient-key drift.
|
|
237
|
+
- `docs/annotations.md` states the rule in both directions: a data annotation
|
|
238
|
+
must stay readable (not `aria-hidden`), a decorative one must be hidden.
|
|
239
|
+
- **A second dogfood pass closed the foreign-renderer/contract gaps it found.**
|
|
240
|
+
`docs/sources.md` + `llms.txt` now document the standalone `.ui-src` trust
|
|
241
|
+
pill and state that a `ui-src--*` tone class **needs a host** (a bare
|
|
242
|
+
`<span class="ui-src--verified">` validates but renders nothing), and name the
|
|
243
|
+
source-card body part as `__excerpt` (not `__detail`). `docs/mermaid.md`:
|
|
244
|
+
`gantt`/`timeline` are **not** covered by the base `themeVariables` (they
|
|
245
|
+
render with Mermaid's own defaults — prefer the native `ui-timeline` for a
|
|
246
|
+
report). `docs/mermaid.md` + `docs/d2.md` gain the same `file://` CORS caveat
|
|
247
|
+
Vega carries (inline the map or pre-render). `docs/vega.md`: select the themed
|
|
248
|
+
ramp with `scale: { range: 'heatmap' }` — **not** `scheme:`, which throws — and
|
|
249
|
+
the accent/neutral series map to `--chart-1` / `--chart-8`, so a legend keys
|
|
250
|
+
them with `ui-legend__swatch--1`/`--8` (`docs/legends.md`). `docs/reporting.md`:
|
|
251
|
+
the live-theme recipe now `finalize()`s the prior Vega view before re-embed
|
|
252
|
+
(was leaking a view per toggle), and notes `ui-meter --value` clamps at 100
|
|
253
|
+
(put an over-target figure in the written label). `docs/marks.md`: `ui-mark`
|
|
254
|
+
is a behind-text highlight (contrast-safe; never needs `--on-accent`).
|
|
255
|
+
|
|
256
|
+
### Internal
|
|
257
|
+
|
|
258
|
+
- **New `check:versions` gate** — every `@ponchia/ui@X.Y.Z` literal in a shipped
|
|
259
|
+
doc (`llms.txt`, `docs/reporting.md`, …) must equal `package.json`, so a stale
|
|
260
|
+
CDN pin can't ship to LLM/copy-paste consumers on the next bump.
|
|
261
|
+
- **Dev-dependency Vega bumped to the v6 stack** — the render-probe now runs on
|
|
262
|
+
`vega@^6.2.0` + `vega-lite@^6.4.3` (Vega-Lite 6 peers Vega 6; a Vega-Lite-6 ÷
|
|
263
|
+
Vega-5 mix is incoherent). The theme `config` is version-independent resolved
|
|
264
|
+
hex, so the artifacts and the probe assertions are unchanged; the documented
|
|
265
|
+
CDN recipe is re-pinned to the matching majors (`vega@6.2.0` / `vega-lite@6.4.3`
|
|
266
|
+
/ `vega-embed@7.1.0`, all still shipping a UMD `/build/*.min.js`). Vega remains
|
|
267
|
+
the consumer's renderer, not a runtime dependency.
|
|
268
|
+
- **New `check:doc-recipes` gate** — a `<script src>` CDN recipe in a shipped doc
|
|
269
|
+
must pin a jsDelivr `/build/*.min.js` UMD bundle, never a bare
|
|
270
|
+
`cdn.jsdelivr.net/npm/<pkg>@N` redirect (which serves a module bundle with no
|
|
271
|
+
global and renders nothing). Docs are otherwise an untested surface; this is
|
|
272
|
+
the structural guard that closes the broken-recipe class the dogfood pass
|
|
273
|
+
found. `<link href>` CSS and prose mentions are exempt.
|
|
274
|
+
- **`classes.json` `customProperties` expanded** to cover the load-bearing,
|
|
275
|
+
no-op-without-it knobs the audit found undocumented: the **required**
|
|
276
|
+
`--icon-mask` (a bare `.ui-icon` paints a solid square without it) and
|
|
277
|
+
`--ui-vt-name` (`.ui-vt` is inert without it), plus `--icon-size`. The
|
|
278
|
+
`states` manifest comment now explicitly names the runtime-managed hooks it
|
|
279
|
+
deliberately excludes (`is-leaving`/`is-visible`/`is-in`/`is-on`) so the
|
|
280
|
+
omission reads as intentional, not a gap. `--on-accent` is annotated at its
|
|
281
|
+
token source as a read-only export for foreign renderers (in-DOM ink is
|
|
282
|
+
`--button-text`). `contrast.md` now prints APCA `Lc` to one decimal so an
|
|
283
|
+
advisory shortfall (e.g. `Lc 44.9`) no longer rounds to a passing-looking `45`.
|
|
284
|
+
- Raw bundle budget 81 → 82 kB for the component-audit accessibility/state
|
|
285
|
+
blocks (gzip held ~14.1 kB — the additions are repetitive media-query and
|
|
286
|
+
`:has()`/`:not()` rules that compress well).
|
|
287
|
+
- **Code-quality audit (16-agent) — two new gates + targeted dedup, no churn.**
|
|
288
|
+
A code-health pass (complexity / duplication / AI-slop / missing-best-practice)
|
|
289
|
+
that deliberately left working, gate-protected code alone. Added:
|
|
290
|
+
`check:recipe-types` (factory↔`.d.ts` option parity, above) and `check:chain`
|
|
291
|
+
(every `check:*` script is wired into the aggregate `check` chain — closes the
|
|
292
|
+
silent-coverage-drop class; it would have caught a forgotten gate). Reconciled
|
|
293
|
+
a latent bug — `clamp()` had silently diverged between `connectors` and
|
|
294
|
+
`annotations`; the two now share one scalar/geometry kernel (the guarded form).
|
|
295
|
+
Dedup that removed real duplication: a shared `collectHosts()` /
|
|
296
|
+
`scrollIntoViewSafe()` / `wrapIndex()` in `behaviors/internal.js` (~9 behaviors),
|
|
297
|
+
a `freshnessErrors()` helper reused by 7 drift gates, the shared `CSS_COLOR`
|
|
298
|
+
regex across the 3 foreign-renderer gates, `check-report`'s opt-in list as a
|
|
299
|
+
loop, `check-pack`'s shipped-docs derived from `pkg.files`, and a looser
|
|
300
|
+
`check-classes` recipe-scrape. README hero de-densified; `srcTone` matched to
|
|
301
|
+
`stateTone`'s idiom; the intentional badge accent-mix (45% vs 40%) documented.
|
|
302
|
+
- **`check:dist` now asserts source-coverage** — every `css/*.css` leaf must be
|
|
303
|
+
bundled, an opt-in `EXTRA_LEAVES` entry, or a roll-up; an orphaned leaf that
|
|
304
|
+
would ship nothing now fails loudly (the inverse of the existing stale-dist
|
|
305
|
+
guard).
|
|
306
|
+
- **`check:dts-emit` now compares `.d.ts.map`** mapping data (volatile `sources`
|
|
307
|
+
path normalized), closing a drift hole the code comment had acknowledged.
|
|
308
|
+
- DTCG export types `--display-weight*` as the spec `fontWeight` type (was
|
|
309
|
+
`number`). Corrected stale `check-tokens.mjs` doc references (the real gate is
|
|
310
|
+
`check:fresh`).
|
|
311
|
+
- Tests: binding hook-surface parity is now **derived** from the modules (the old
|
|
312
|
+
hard-coded list silently omitted the five analytical hooks); a new
|
|
313
|
+
`analytical-boundary` test makes the "no scales/state/fetch/global-hotkey"
|
|
314
|
+
contract executable; a new behavior test pins the null-root no-op.
|
|
315
|
+
- Removed four dead keyframes (`scan`/`growBar`/`drawLine`/`pulseNode`) from
|
|
316
|
+
`motion.css`. Raw bundle budget 80 → 81 kB for the accessibility blocks (gzip
|
|
317
|
+
held ~14.0 kB).
|
|
318
|
+
- **`classes.json` `--value` retargeted** to `.ui-meter__fill, .ui-progress__bar`
|
|
319
|
+
(was the `.ui-meter, .ui-progress` track parent) — the custom property is read
|
|
320
|
+
on the fill child, so the machine-readable manifest now matches where an author
|
|
321
|
+
actually sets it.
|
|
322
|
+
- **New render-geometry e2e** (`test/e2e/render-geometry.spec.mjs`) — launches a
|
|
323
|
+
browser at the demo's real report primitives and asserts the `.ui-meter__fill`
|
|
324
|
+
/ `.ui-progress__bar` fills and the standalone `.ui-src` pill paint a non-zero
|
|
325
|
+
box (via `getBoundingClientRect`, not the inline-box-lying
|
|
326
|
+
`getComputedStyle().inlineSize`). Closes the validates-but-renders-nothing
|
|
327
|
+
category that hid the meter regression. The demo gains a standalone `.ui-src`
|
|
328
|
+
pill row to exercise it.
|
|
329
|
+
|
|
330
|
+
## 0.5.0 — 2026-06-02
|
|
331
|
+
|
|
332
|
+
A **minor** that builds out the "analytical & generated-report UI" identity: a
|
|
333
|
+
full suite of opt-in **communication primitives** — SVG annotations, legends,
|
|
334
|
+
text/evidence marks, leader-line connectors, a guided-focus spotlight, a
|
|
335
|
+
crosshair/readout, a selection-state vocabulary, label declutter + direct labels
|
|
336
|
+
(`declutterLabels`/`directLabels`), and a source/citation/provenance **trust
|
|
337
|
+
layer** — plus a consolidation pass over them. Each owns its visual grammar and
|
|
338
|
+
pure geometry and refuses to own scales/state/hit-testing (no chart engine).
|
|
339
|
+
|
|
340
|
+
Per the project's versioning policy, breaking changes ship in the minor. This
|
|
341
|
+
release carries three: the opt-in report kit's chart data key moved into the new
|
|
342
|
+
legend layer (`.ui-chart__legend`/`__swatch` removed — see Changed and
|
|
343
|
+
[`MIGRATIONS.json`](MIGRATIONS.json)), annotation arrowheads now render via
|
|
344
|
+
the shared connectors geometry kernel (a small path-shape change), and the
|
|
345
|
+
opt-in marks' rationed-accent tone was renamed `evidence`→`accent` to match the
|
|
346
|
+
rest of the analytical tone vocabulary. Everything else is additive and opt-in,
|
|
347
|
+
save for the tiny `.ui-shortcut` keyboard-hint primitive that joins the core
|
|
348
|
+
layer; the rest of the default `dist/bronto.css` is unchanged. Also folds in the
|
|
349
|
+
0.4.x maintenance hardening that had not yet been released.
|
|
350
|
+
|
|
351
|
+
### Added
|
|
352
|
+
|
|
353
|
+
- **SVG annotations** (`@ponchia/ui/css/annotations.css`,
|
|
354
|
+
`@ponchia/ui/annotations`, `.ui-annotation*`, `ui.annotation()`): an opt-in
|
|
355
|
+
annotation layer for charts, reports, and analytical figures, following the
|
|
356
|
+
d3-annotation grammar (a **subject** marks the thing, a **connector** points
|
|
357
|
+
away, a **note** carries the text). Ships a class grammar (variants for
|
|
358
|
+
label/callout/elbow/curve/circle/rect/threshold/badge/bracket/band/slope/
|
|
359
|
+
compare/cluster/axis/timeline/evidence, six tones, and opt-in
|
|
360
|
+
`draw`/`reveal`/`pulse`/`focus` motion that respects `prefers-reduced-motion`)
|
|
361
|
+
plus tiny geometry helpers that return SVG strings only — they own no chart
|
|
362
|
+
scales, mutate no DOM, and provide no edit mode. Documented in
|
|
363
|
+
[`docs/annotations.md`](docs/annotations.md) and gated by `check:report`.
|
|
364
|
+
- **Legends / data keys** (`@ponchia/ui/css/legend.css`, `.ui-legend*`,
|
|
365
|
+
`ui.legend()`/`ui.legendItem()`/`ui.legendSwatch()`, `initLegend`): an opt-in,
|
|
366
|
+
standalone data-key layer that reads the `--chart-*` palette tokens.
|
|
367
|
+
Categorical, continuous gradient (sequential + `--diverging`), threshold, and
|
|
368
|
+
pattern keys; swatch colour set inline (`--chart-color`) or via
|
|
369
|
+
`.ui-legend__swatch--1..8` index helpers; vertical/compact/with-values
|
|
370
|
+
layouts. WCAG 1.4.1 by construction (the text label is the non-colour
|
|
371
|
+
channel), with `forced-colors` and print care. Optional interactive
|
|
372
|
+
(series-toggling) entries are `<button aria-pressed>` controls: `initLegend`
|
|
373
|
+
flips `aria-pressed`/`.is-inactive` and emits `bronto:legend:toggle`
|
|
374
|
+
(`{ series, active }`) — the host owns hiding the series and any `aria-live`
|
|
375
|
+
announcement (it is never a chart engine). Optional `useLegend` hook in the
|
|
376
|
+
React/Solid/Qwik bindings. New `check:legend` gate proves swatch colours are a
|
|
377
|
+
subset of `tokens/charts.js` and never a raw hex. Documented in
|
|
378
|
+
[`docs/legends.md`](docs/legends.md).
|
|
379
|
+
- **Text marks / evidence** (`@ponchia/ui/css/marks.css`, `.ui-mark*`,
|
|
380
|
+
`.ui-bracket-note*`, `ui.mark()`/`ui.bracketNote()`): an opt-in layer of
|
|
381
|
+
sober, report-grade emphasis for running prose — the counterpart to SVG
|
|
382
|
+
annotations (annotations call out a figure, marks call out a sentence). Inline
|
|
383
|
+
`.ui-mark` (highlight/underline/box/strike; `--accent` + status
|
|
384
|
+
tones; `--draw` reduced-motion-safe sweep) for use on `<mark>`, and
|
|
385
|
+
`.ui-bracket-note` for bracketing a whole passage. Pure CSS on semantic
|
|
386
|
+
tokens, monochrome by default, with `forced-colors` care. Documented in
|
|
387
|
+
[`docs/marks.md`](docs/marks.md).
|
|
388
|
+
- **Connectors / leader lines** (`@ponchia/ui/css/connectors.css`,
|
|
389
|
+
`@ponchia/ui/connectors`, `.ui-connector*`, `initConnectors`, `ui.connector()`):
|
|
390
|
+
an opt-in layer that draws a line between two DOM elements (the
|
|
391
|
+
page-coordinate cousin of annotations). Pure geometry helpers
|
|
392
|
+
(`connectRects`/`connectorPath`/`arrowHead`/…) that return SVG strings and own
|
|
393
|
+
no DOM, an `.ui-connector` overlay grammar (straight/elbow/curve, arrow/dot
|
|
394
|
+
ends, tones, dashed, `--draw`), and an optional `initConnectors` behavior that
|
|
395
|
+
draws + tracks on resize/scroll. `useConnectors` in the bindings. Documented in
|
|
396
|
+
[`docs/connectors.md`](docs/connectors.md).
|
|
397
|
+
- **Spotlight / guided focus** (`@ponchia/ui/css/spotlight.css`, `.ui-spotlight*`,
|
|
398
|
+
`.ui-tour-note*`, `initSpotlight`, `ui.spotlight()`): an opt-in guided-focus
|
|
399
|
+
overlay — a box-shadow cutout over a target element, optional ring, and a
|
|
400
|
+
callout note. `initSpotlight` positions the cutout (`--spot-x/y/w/h`) and
|
|
401
|
+
re-places on resize/scroll and when `data-target` changes. Deliberately **not**
|
|
402
|
+
a tour engine — the host owns step order/advancing/visibility. `useSpotlight`
|
|
403
|
+
in the bindings. Documented in [`docs/spotlight.md`](docs/spotlight.md).
|
|
404
|
+
- **Crosshair / readout** (`@ponchia/ui/css/crosshair.css`, `.ui-crosshair*`,
|
|
405
|
+
`.ui-readout`, `initCrosshair`, `ui.crosshair()`): an opt-in plot ruler +
|
|
406
|
+
pinned readout. `initCrosshair` tracks the pointer over a
|
|
407
|
+
`[data-bronto-crosshair]` plot, sets `--crosshair-x/y`, and dispatches
|
|
408
|
+
`bronto:crosshair:move` with px + 0–1 fractions — it reports position only and
|
|
409
|
+
never maps pixels to data (that needs the host's scales). `useCrosshair` in the
|
|
410
|
+
bindings. Documented in [`docs/crosshair.md`](docs/crosshair.md).
|
|
411
|
+
- **Selection states** (`@ponchia/ui/css/selection.css`, `.ui-sel*`,
|
|
412
|
+
`ui.sel()`): a tiny cross-cutting selection-emphasis vocabulary
|
|
413
|
+
(`--on`/`--off`/`--maybe`) reusable on chart marks, table rows, list items, or
|
|
414
|
+
map regions. The carve-out from brush/lasso — Bronto styles the states; the
|
|
415
|
+
host owns the selection/hit-test logic. Documented in
|
|
416
|
+
[`docs/selection.md`](docs/selection.md).
|
|
417
|
+
- **Sources, citations & provenance** (`@ponchia/ui/css/sources.css`,
|
|
418
|
+
`.ui-citation`/`.ui-source-card`/`.ui-source-list`/`.ui-provenance`,
|
|
419
|
+
`ui.citation()`/`ui.source()`/`ui.provenance()`): an opt-in, CSS-only **trust
|
|
420
|
+
layer** for generated reports and AI output — the grammar for "where did this
|
|
421
|
+
come from?". A cross-cutting `.ui-src--*` state (verified/reviewed/generated/
|
|
422
|
+
unverified/stale/conflict) sets a rationed tone, always paired with an
|
|
423
|
+
author-written label (never colour alone). Bronto owns the grammar + states;
|
|
424
|
+
the host owns fetching, citation numbering, and trust. The first
|
|
425
|
+
frontier-primitive beyond the analytical suite. Documented in
|
|
426
|
+
[`docs/sources.md`](docs/sources.md).
|
|
427
|
+
- **Keyboard-shortcut hint** (`.ui-shortcut` + `.ui-shortcut__sep`, core): a tiny
|
|
428
|
+
universal-chrome primitive that lays out one or more `.ui-kbd` keys as a chord
|
|
429
|
+
(`⌘`+`K`) or sequence (`G` then `I`) with a dim connective. The command tier's
|
|
430
|
+
smallest piece, broadly useful outside a palette (menu items, buttons,
|
|
431
|
+
tooltips). Class-only, like `.ui-kbd`.
|
|
432
|
+
- **Lifecycle / system state** (`@ponchia/ui/css/state.css`, `.ui-state`
|
|
433
|
+
(+`__label`/`__detail`/`--busy`) with canonical state modifiers
|
|
434
|
+
(saving/saved/queued/offline/stale/conflict/error/locked/reviewed/
|
|
435
|
+
needs-review), `.ui-syncbar`, `ui.state()`): an opt-in, CSS-only vocabulary for
|
|
436
|
+
the states apps actually live in — a labelled state object with a rationed tone
|
|
437
|
+
and a page/document sync bar. The label is the state (never colour alone);
|
|
438
|
+
`--busy` pulses the indicator (reduced-motion-safe). Bronto ships the visual
|
|
439
|
+
states + canonical wording; the host owns the state machine, retry, and
|
|
440
|
+
persistence. Frontier candidate #2. Documented in [`docs/state.md`](docs/state.md).
|
|
441
|
+
- **Generated content & AI trust** (`@ponchia/ui/css/generated.css`,
|
|
442
|
+
`.ui-generated`/`.ui-origin-label`/`.ui-reasoning`/`.ui-tool-log`/`.ui-tool-call`,
|
|
443
|
+
`ui.originLabel()`): an opt-in, CSS-only set of **trust surfaces** for AI /
|
|
444
|
+
system-generated content — a marked region, an origin label, and quiet
|
|
445
|
+
native-`<details>` reasoning + tool-call logs. Not a chat kit; no
|
|
446
|
+
fabricated-confidence widget. Bronto styles disclosure/origin/trace, the host
|
|
447
|
+
owns model metadata, redaction, and safety. Pairs with the source layer.
|
|
448
|
+
Documented in [`docs/generated.md`](docs/generated.md).
|
|
449
|
+
- **Workbench** (`@ponchia/ui/css/workbench.css`, `.ui-inspector`/`.ui-property`/
|
|
450
|
+
`.ui-selectionbar`): an opt-in, CSS-only core for tool UIs — a selected-object
|
|
451
|
+
inspector panel, denser property rows, and a raised selection action bar.
|
|
452
|
+
Layout + affordances only; resizable split panes and drag handles are
|
|
453
|
+
deferred. Documented in [`docs/workbench.md`](docs/workbench.md).
|
|
454
|
+
- **Command palette** (`@ponchia/ui/css/command.css`, `.ui-command` (+
|
|
455
|
+
`__input`/`__list`/`__group`/`__item`/`__shortcut`/`__meta`/`__empty`),
|
|
456
|
+
`initCommand`, `useCommand`): an opt-in CSS shell + behavior — filter +
|
|
457
|
+
keyboard-navigate a DOM-authored command list (roving focus, group hiding,
|
|
458
|
+
full keyboard), emitting `bronto:command:select` ({ value, label }) and
|
|
459
|
+
`bronto:command:close`. Bronto navigates; the host owns the action registry,
|
|
460
|
+
routing, and execution. No global Cmd/Ctrl+K. Completes the command tier
|
|
461
|
+
(frontier #3) atop the shipped `ui-shortcut`. Documented in
|
|
462
|
+
[`docs/command.md`](docs/command.md).
|
|
463
|
+
- **Label declutter** (`@ponchia/ui/annotations` `declutterLabels`): a
|
|
464
|
+
deterministic, order-preserving **1-D** label de-overlap helper (sort, push
|
|
465
|
+
apart by `size + gap`, slide to fit `max`) — pure, no DOM/scales. Not a 2-D
|
|
466
|
+
collision solver. Documented in [`docs/annotations.md`](docs/annotations.md).
|
|
467
|
+
- **Direct labels** (`@ponchia/ui/annotations` `directLabels`): the
|
|
468
|
+
direct-labeling companion to `declutterLabels` — it declutters labels along an
|
|
469
|
+
axis **and** draws the leader from each anchor to its placed label, reusing the
|
|
470
|
+
connectors geometry kernel. Returns `[{ x, y, anchor, key, d }]` (the `d` feeds
|
|
471
|
+
a `ui-annotation__connector`). Deterministic and pure: no scales, no DOM, no
|
|
472
|
+
2-D placement (the 1-D core of Labella, completed with leaders). Documented in
|
|
473
|
+
[`docs/annotations.md`](docs/annotations.md).
|
|
474
|
+
- **Connectors** (`@ponchia/ui/connectors`, `@ponchia/ui/css/connectors.css`,
|
|
475
|
+
`initConnectors`, `useConnectors`, `ui.connector()`) and **Spotlight**
|
|
476
|
+
(`css/spotlight.css`, `initSpotlight`, `ui.spotlight()`) — leader lines between
|
|
477
|
+
DOM elements and a guided-focus overlay; both opt-in, geometry/visual only
|
|
478
|
+
(the host owns layout/tour state).
|
|
479
|
+
- **Crosshair / readout** (`css/crosshair.css`, `initCrosshair`,
|
|
480
|
+
`ui.crosshair()`) and **selection states** (`css/selection.css`, `ui.sel()`) —
|
|
481
|
+
a plot ruler that reports pointer position (not data), and a cross-cutting
|
|
482
|
+
`.ui-sel--on/off/maybe` emphasis vocabulary (the host owns brush/hit-test).
|
|
483
|
+
- **`@ponchia/ui/css/analytical.css`** — a convenience roll-up that bundles the
|
|
484
|
+
seven analytical leaves (annotations, legend, marks, connectors, spotlight,
|
|
485
|
+
crosshair, selection) into one import. Add `dataviz.css`/`report.css`
|
|
486
|
+
separately as needed.
|
|
487
|
+
|
|
488
|
+
### Fixed
|
|
489
|
+
|
|
490
|
+
- The optional Qwik binding (`@ponchia/ui/qwik`) is now built from the packed
|
|
491
|
+
tarball in CI **and** release, alongside React/Solid — closing a coverage gap
|
|
492
|
+
(it was documented as optimizer-proven but no job actually built it). Also
|
|
493
|
+
covered by `check:pack`, the size report, and the dead-code config.
|
|
494
|
+
|
|
495
|
+
### Changed
|
|
496
|
+
|
|
497
|
+
- **Breaking (opt-in report kit):** the chart data key moved out of
|
|
498
|
+
`css/report.css` into the standalone `css/legend.css`. `.ui-chart__legend` →
|
|
499
|
+
`.ui-legend` (now with `.ui-legend__item`/`.ui-legend__label` rows) and
|
|
500
|
+
`.ui-chart__swatch` → `.ui-legend__swatch`. Import `@ponchia/ui/css/legend.css`
|
|
501
|
+
beside the report kit; see [`MIGRATIONS.json`](MIGRATIONS.json) and
|
|
502
|
+
[`docs/legends.md`](docs/legends.md). The `--chart-color`/`--chart-pattern`
|
|
503
|
+
swatch contract is unchanged, so the rename is mechanical.
|
|
504
|
+
- **Breaking (opt-in marks):** the rationed-accent **tone** on `.ui-mark` and
|
|
505
|
+
`.ui-bracket-note` was renamed `evidence` → `accent` (`ui-mark--evidence` →
|
|
506
|
+
`ui-mark--accent`, `ui-bracket-note--evidence` → `ui-bracket-note--accent`;
|
|
507
|
+
`ui.mark({ tone: 'accent' })` / `ui.bracketNote({ tone: 'accent' })`) so the
|
|
508
|
+
accent tone reads the same across every analytical primitive (it already was
|
|
509
|
+
`accent` on `ui.connector`/`ui.annotation`). `.ui-annotation--evidence` is
|
|
510
|
+
**unchanged** — it is a marker _variant_ (a proof/source shape), not a tone.
|
|
511
|
+
Mechanical whole-token rename; see [`MIGRATIONS.json`](MIGRATIONS.json).
|
|
512
|
+
- **Consolidation:** the SVG geometry is single-sourced in the `connectors`
|
|
513
|
+
kernel — `@ponchia/ui/annotations` now builds its connectors on it, so a
|
|
514
|
+
line/curve/arrow/dot is drawn one way across both. `connectorLine`/`Curve`/
|
|
515
|
+
`EndDot` output is byte-identical; **`connectorEndArrow` is the one
|
|
516
|
+
(minor-breaking) shape change** — the arrowhead now matches the connectors
|
|
517
|
+
arrowhead. New `check:helpers-dts` gate keeps the hand-maintained
|
|
518
|
+
`annotations`/`connectors` `.d.ts` in parity with their runtime exports.
|
|
519
|
+
- The Doto webfont now ships as **woff2 only** (Brotli) instead of uncompressed
|
|
520
|
+
TTF: ~5.7 kB per weight vs ~137 kB, cutting the six-weight payload from ~823 kB
|
|
521
|
+
to ~35 kB (the dot-matrix glyphs compress ~96%) and shrinking the unpacked
|
|
522
|
+
tarball by roughly the same. No TTF fallback is carried — woff2 is supported by
|
|
523
|
+
the entire browser floor (ADR-0002: Chrome 125 / Safari 18 / Firefox 129).
|
|
524
|
+
`@font-face` is internal, so this is transparent to consumers; only self-hosts
|
|
525
|
+
that referenced `fonts/doto-*.ttf` directly need to point at `*.woff2`.
|
|
526
|
+
- `docs/architecture.md` now ships in the package, so the offline rationale the
|
|
527
|
+
shipped ADRs link to resolves inside the tarball.
|
|
528
|
+
- `docs/stability.md` clarifies that `data-surface`/`data-density`/
|
|
529
|
+
`data-contrast` are **convenience presets**, not part of the stability
|
|
530
|
+
contract; `data-theme` (light/dark) remains the contractual base.
|
|
531
|
+
|
|
532
|
+
### Internal
|
|
533
|
+
|
|
534
|
+
- Token values are single-sourced in `tokens/index.js` (`cssVars`); the
|
|
535
|
+
`css/tokens.css` palette is generated from it, so the dark palette is authored
|
|
536
|
+
once instead of in three places (the shipped CSS is byte-identical).
|
|
537
|
+
- `behaviors/index.js` is split into per-behavior modules behind the same public
|
|
538
|
+
barrel (no surface change).
|
|
539
|
+
- Drift-gate consolidation (`assertFresh`), a Qwik type smoke + stronger
|
|
540
|
+
class-recipe wiring test, the APCA advisory widened to the accent text across
|
|
541
|
+
the core palette and every colorway (still advisory; WCAG 2.1 AA stays the
|
|
542
|
+
hard gate), an OLED computed-style smoke test, and several doc reconciliations.
|
|
543
|
+
- New `demos.spec` e2e sweep runs the console-error / uncaught-exception /
|
|
544
|
+
failed-response guards **and** an axe scan over every per-feature demo page
|
|
545
|
+
(annotations, legends, marks, connectors, spotlight, crosshair, selection,
|
|
546
|
+
report) in both themes and cross-browser — previously only `/demo/` was
|
|
547
|
+
guarded, so a throw or 404 on those SVG-heavy pages could not fail CI.
|
|
548
|
+
- The `check:dist` payload ceiling was raised to 80 kB raw / 14.5 kB gzip (from
|
|
549
|
+
78 kB / 13.5 kB). The default bundle was sitting ~21 bytes under the old gzip
|
|
550
|
+
gate — the analytical primitives are opt-in leaves and stay out of it, so this
|
|
551
|
+
is residual prior growth; the bump restores a real ~3% raw / ~7% gzip margin
|
|
552
|
+
so an ordinary token addition no longer trips an unrelated PR.
|
|
553
|
+
|
|
7
554
|
## 0.4.1 — 2026-06-01
|
|
8
555
|
|
|
9
556
|
Patch hardening for the public framework surface, plus the first step of the
|
|
@@ -79,6 +626,9 @@ modern-platform motion direction (see [ADR-0002](docs/adr/0002-scope-and-2026-ba
|
|
|
79
626
|
- **[ADR-0003](docs/adr/0003-theme-model.md)** records the theme model: a binary
|
|
80
627
|
light/dark base × one-knob derivation × orthogonal axes (colorway, surface,
|
|
81
628
|
contrast, density), and why a flat named-theme catalog is rejected.
|
|
629
|
+
- React and Solid Vite examples, CI/release matrix coverage for those examples,
|
|
630
|
+
runtime binding tests, public API stability docs, a release runbook, and
|
|
631
|
+
`npm run size:report`.
|
|
82
632
|
|
|
83
633
|
### Changed
|
|
84
634
|
|
|
@@ -117,12 +667,6 @@ modern-platform motion direction (see [ADR-0002](docs/adr/0002-scope-and-2026-ba
|
|
|
117
667
|
and the OKLCH accent ramp uses an explicit white/black neutral endpoint for
|
|
118
668
|
cross-engine browser parity.
|
|
119
669
|
|
|
120
|
-
### Added
|
|
121
|
-
|
|
122
|
-
- React and Solid Vite examples, CI/release matrix coverage for those examples,
|
|
123
|
-
runtime binding tests, public API stability docs, a release runbook, and
|
|
124
|
-
`npm run size:report`.
|
|
125
|
-
|
|
126
670
|
## 0.4.0 — 2026-05-31
|
|
127
671
|
|
|
128
672
|
The color-system release — [ADR-0001](docs/adr/0001-color-system.md) steps 1–8.
|