@ponchia/ui 0.5.0 → 0.6.3

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.
Files changed (196) hide show
  1. package/CHANGELOG.md +386 -4
  2. package/MIGRATIONS.json +14 -0
  3. package/README.md +29 -6
  4. package/annotations/index.d.ts +398 -276
  5. package/annotations/index.d.ts.map +1 -0
  6. package/annotations/index.js +350 -77
  7. package/behaviors/carousel.d.ts +28 -0
  8. package/behaviors/carousel.d.ts.map +1 -0
  9. package/behaviors/carousel.js +20 -16
  10. package/behaviors/combobox.d.ts +40 -0
  11. package/behaviors/combobox.d.ts.map +1 -0
  12. package/behaviors/combobox.js +111 -29
  13. package/behaviors/command.d.ts +41 -0
  14. package/behaviors/command.d.ts.map +1 -0
  15. package/behaviors/command.js +27 -15
  16. package/behaviors/connectors.d.ts +17 -0
  17. package/behaviors/connectors.d.ts.map +1 -0
  18. package/behaviors/connectors.js +7 -5
  19. package/behaviors/crosshair.d.ts +42 -0
  20. package/behaviors/crosshair.d.ts.map +1 -0
  21. package/behaviors/crosshair.js +23 -6
  22. package/behaviors/dialog.d.ts +20 -0
  23. package/behaviors/dialog.d.ts.map +1 -0
  24. package/behaviors/dialog.js +6 -2
  25. package/behaviors/disclosure.d.ts +10 -0
  26. package/behaviors/disclosure.d.ts.map +1 -0
  27. package/behaviors/disclosure.js +6 -2
  28. package/behaviors/dismissible.d.ts +10 -0
  29. package/behaviors/dismissible.d.ts.map +1 -0
  30. package/behaviors/dismissible.js +6 -2
  31. package/behaviors/forms.d.ts +27 -0
  32. package/behaviors/forms.d.ts.map +1 -0
  33. package/behaviors/forms.js +54 -13
  34. package/behaviors/glyph.d.ts +14 -0
  35. package/behaviors/glyph.d.ts.map +1 -0
  36. package/behaviors/glyph.js +28 -5
  37. package/behaviors/index.d.ts +31 -237
  38. package/behaviors/index.d.ts.map +1 -0
  39. package/behaviors/index.js +17 -0
  40. package/behaviors/inert.d.ts +20 -0
  41. package/behaviors/inert.d.ts.map +1 -0
  42. package/behaviors/inert.js +46 -0
  43. package/behaviors/internal.d.ts +25 -0
  44. package/behaviors/internal.d.ts.map +1 -0
  45. package/behaviors/internal.js +77 -1
  46. package/behaviors/legend.d.ts +35 -0
  47. package/behaviors/legend.d.ts.map +1 -0
  48. package/behaviors/legend.js +32 -2
  49. package/behaviors/menu.d.ts +16 -0
  50. package/behaviors/menu.d.ts.map +1 -0
  51. package/behaviors/menu.js +6 -2
  52. package/behaviors/modal.d.ts +41 -0
  53. package/behaviors/modal.d.ts.map +1 -0
  54. package/behaviors/modal.js +124 -0
  55. package/behaviors/popover.d.ts +28 -0
  56. package/behaviors/popover.d.ts.map +1 -0
  57. package/behaviors/popover.js +78 -7
  58. package/behaviors/spotlight.d.ts +17 -0
  59. package/behaviors/spotlight.d.ts.map +1 -0
  60. package/behaviors/spotlight.js +7 -5
  61. package/behaviors/table.d.ts +36 -0
  62. package/behaviors/table.d.ts.map +1 -0
  63. package/behaviors/table.js +84 -17
  64. package/behaviors/tabs.d.ts +20 -0
  65. package/behaviors/tabs.d.ts.map +1 -0
  66. package/behaviors/tabs.js +17 -14
  67. package/behaviors/theme.d.ts +54 -0
  68. package/behaviors/theme.d.ts.map +1 -0
  69. package/behaviors/theme.js +22 -3
  70. package/behaviors/toast.d.ts +49 -0
  71. package/behaviors/toast.d.ts.map +1 -0
  72. package/behaviors/toast.js +47 -3
  73. package/classes/classes.json +2527 -0
  74. package/classes/index.d.ts +134 -15
  75. package/classes/index.js +280 -80
  76. package/classes/vscode.css-custom-data.json +12 -0
  77. package/connectors/index.d.ts +201 -69
  78. package/connectors/index.d.ts.map +1 -0
  79. package/connectors/index.js +142 -25
  80. package/css/app.css +69 -13
  81. package/css/base.css +15 -10
  82. package/css/bullet.css +108 -0
  83. package/css/code.css +98 -0
  84. package/css/connectors.css +17 -0
  85. package/css/content.css +22 -3
  86. package/css/crosshair.css +7 -7
  87. package/css/dataviz.css +5 -1
  88. package/css/diff.css +153 -0
  89. package/css/disclosure.css +53 -7
  90. package/css/dots.css +94 -7
  91. package/css/feedback.css +97 -7
  92. package/css/forms.css +113 -4
  93. package/css/legend.css +16 -9
  94. package/css/marks.css +38 -8
  95. package/css/motion.css +98 -53
  96. package/css/navigation.css +7 -0
  97. package/css/overlay.css +90 -3
  98. package/css/primitives.css +158 -13
  99. package/css/report.css +73 -56
  100. package/css/sidenote.css +67 -0
  101. package/css/site.css +16 -2
  102. package/css/sources.css +43 -1
  103. package/css/spark.css +62 -0
  104. package/css/spotlight.css +1 -1
  105. package/css/table.css +9 -2
  106. package/css/term.css +110 -0
  107. package/css/textref.css +63 -0
  108. package/css/toc.css +91 -0
  109. package/css/tokens.css +49 -1
  110. package/css/tree.css +134 -0
  111. package/css/workbench.css +1 -1
  112. package/dist/bronto.css +1 -1
  113. package/dist/css/analytical.css +1 -1
  114. package/dist/css/app.css +1 -1
  115. package/dist/css/base.css +1 -1
  116. package/dist/css/bullet.css +1 -0
  117. package/dist/css/code.css +1 -0
  118. package/dist/css/connectors.css +1 -1
  119. package/dist/css/content.css +1 -1
  120. package/dist/css/crosshair.css +1 -1
  121. package/dist/css/diff.css +1 -0
  122. package/dist/css/disclosure.css +1 -1
  123. package/dist/css/dots.css +1 -1
  124. package/dist/css/feedback.css +1 -1
  125. package/dist/css/forms.css +1 -1
  126. package/dist/css/legend.css +1 -1
  127. package/dist/css/marks.css +1 -1
  128. package/dist/css/motion.css +1 -1
  129. package/dist/css/navigation.css +1 -1
  130. package/dist/css/overlay.css +1 -1
  131. package/dist/css/primitives.css +1 -1
  132. package/dist/css/report.css +1 -1
  133. package/dist/css/sidenote.css +1 -0
  134. package/dist/css/site.css +1 -1
  135. package/dist/css/sources.css +1 -1
  136. package/dist/css/spark.css +1 -0
  137. package/dist/css/spotlight.css +1 -1
  138. package/dist/css/table.css +1 -1
  139. package/dist/css/term.css +1 -0
  140. package/dist/css/textref.css +1 -0
  141. package/dist/css/toc.css +1 -0
  142. package/dist/css/tokens.css +1 -1
  143. package/dist/css/tree.css +1 -0
  144. package/dist/css/workbench.css +1 -1
  145. package/docs/adr/0003-theme-model.md +1 -1
  146. package/docs/annotations.md +133 -14
  147. package/docs/architecture.md +49 -6
  148. package/docs/bullet.md +78 -0
  149. package/docs/code.md +76 -0
  150. package/docs/contrast.md +116 -92
  151. package/docs/d2.md +196 -0
  152. package/docs/diff.md +146 -0
  153. package/docs/legends.md +23 -3
  154. package/docs/marks.md +9 -2
  155. package/docs/mermaid.md +169 -0
  156. package/docs/reference.md +201 -26
  157. package/docs/reporting.md +416 -57
  158. package/docs/sidenote.md +64 -0
  159. package/docs/sources.md +27 -0
  160. package/docs/spark.md +78 -0
  161. package/docs/stability.md +10 -2
  162. package/docs/term.md +81 -0
  163. package/docs/textref.md +78 -0
  164. package/docs/theming.md +44 -5
  165. package/docs/toc.md +83 -0
  166. package/docs/tree.md +74 -0
  167. package/docs/usage.md +354 -16
  168. package/docs/vega.md +244 -0
  169. package/docs/workbench.md +7 -1
  170. package/glyphs/glyphs.js +13 -5
  171. package/llms.txt +285 -14
  172. package/package.json +95 -17
  173. package/qwik/index.d.ts +44 -59
  174. package/qwik/index.d.ts.map +1 -0
  175. package/qwik/index.js +65 -3
  176. package/react/index.d.ts +41 -61
  177. package/react/index.d.ts.map +1 -0
  178. package/react/index.js +63 -3
  179. package/solid/index.d.ts +68 -61
  180. package/solid/index.d.ts.map +1 -0
  181. package/solid/index.js +66 -3
  182. package/tokens/d2.d.ts +38 -0
  183. package/tokens/d2.js +71 -0
  184. package/tokens/d2.json +43 -0
  185. package/tokens/index.d.ts +5 -5
  186. package/tokens/index.js +15 -1
  187. package/tokens/index.json +9 -0
  188. package/tokens/mermaid.d.ts +23 -0
  189. package/tokens/mermaid.js +181 -0
  190. package/tokens/mermaid.json +163 -0
  191. package/tokens/resolved.json +45 -1
  192. package/tokens/skins.js +3 -2
  193. package/tokens/tokens.dtcg.json +26 -0
  194. package/tokens/vega.d.ts +34 -0
  195. package/tokens/vega.js +155 -0
  196. package/tokens/vega.json +179 -0
package/llms.txt CHANGED
@@ -31,6 +31,23 @@ later layer) always win over framework styles regardless of selector
31
31
  specificity — this is the intended override mechanism; do not fight it
32
32
  with `!important`.
33
33
 
34
+ Loading a stylesheet — read before copying a `<link>` below. The opt-in
35
+ leaves are written as `@ponchia/ui/css/<leaf>.css` for brevity. That
36
+ package-specifier form resolves ONLY inside a CSS-aware bundler
37
+ (Vite/webpack); in a standalone `.html` file it does not resolve. For plain
38
+ HTML (the usual case when an LLM emits a report) use a real URL — and note
39
+ the path changes from source `css/` to built `dist/css/`:
40
+
41
+ ```html
42
+ <!-- installed locally -->
43
+ <link rel="stylesheet" href="./node_modules/@ponchia/ui/dist/css/<leaf>.css" />
44
+ <!-- or from a CDN; pin the version (pre-1.0, breaking changes ship in the minor) -->
45
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.3/dist/css/<leaf>.css" />
46
+ ```
47
+
48
+ The flattened default bundle is `dist/bronto.css` (bundler shorthand
49
+ `@ponchia/ui`). A complete, copy-pasteable CDN report is in `docs/reporting.md`.
50
+
34
51
  Typed class vocabulary (returns plain strings — works in any framework):
35
52
 
36
53
  ```js
@@ -52,6 +69,14 @@ Optional vanilla behaviors (theme toggle, etc. — SSR-safe, tree-shakeable):
52
69
  import { applyStoredTheme } from '@ponchia/ui/behaviors';
53
70
  ```
54
71
 
72
+ Notable behaviors beyond the obvious: `initMenu()` adds close affordances to a
73
+ native `<details data-bronto-menu>` dropdown (outside-click/Escape/select-close);
74
+ `initModal()` wires the controlled `.ui-modal.is-open` path (inert focus-trap +
75
+ role/aria-modal); `initDisabledGuard()` makes every `aria-disabled` control
76
+ keyboard-inert (CSS alone is only pointer-inert). For the value-bearing fills,
77
+ `attrs.meter(value)` / `attrs.progress(value)` from `@ponchia/ui/classes` return
78
+ `role`+`aria-valuenow/min/max`+the `--value` style to spread onto the host.
79
+
55
80
  For React/Solid/Qwik, optional thin hook bindings over those behaviors (peer
56
81
  deps `react` / `solid-js` / `@builder.io/qwik`, optional — core stays zero-dep):
57
82
 
@@ -69,6 +94,33 @@ import { renderGlyph, GLYPH_NAMES } from '@ponchia/ui/glyphs';
69
94
  el.innerHTML = renderGlyph('check', { label: 'Done' });
70
95
  ```
71
96
 
97
+ Layout primitives (core bundle, no media queries — intrinsic Every-Layout
98
+ composition that responds to content + available space): `ui-stack` (vertical
99
+ rhythm), `ui-cluster` (wrapping inline row), `ui-grid` (auto-fit columns),
100
+ `ui-sidebar` (sidebar + main that stacks when cramped), `ui-switcher` (row →
101
+ column together), `ui-center` (measure-bounded column), `ui-ratio` (aspect-ratio
102
+ box — one child only), and the `ui-app-shell`/`ui-app-rail`/`ui-app-nav` admin
103
+ shell. `ui-cq` makes descendant layouts respond to THAT box (container queries),
104
+ not the viewport — wrap a `ui-grid`/`ui-statgrid` in it for an island-safe
105
+ collapse in a slim pane. Each is tuned with an inline custom property rather than
106
+ a modifier — set `style="--grid-min: 12rem"`, `--sidebar-width`, `--sidebar-gap`,
107
+ `--switcher-min`, `--switcher-gap`, `--center-max` (the INNER measure; gutters add
108
+ to the total), `--ratio`, `--stack-gap`, `--cluster-gap`, `--app-rail`, etc. The
109
+ full list with defaults is in `classes.json` `customProperties`. App-shell/sitenav
110
+ current page is `aria-current="page"`.
111
+
112
+ Motion utilities (core bundle, all reduced-motion-safe — they collapse to the
113
+ static end state, not just a zeroed duration): `ui-animate-in`,
114
+ `ui-animate-fade`, `ui-animate-dot`, `ui-animate-matrix` (enter animations),
115
+ `ui-stagger` (+ `--i` per child, or `ui-stagger--auto` to
116
+ derive the delay from `:nth-child`), `ui-reveal` (JS/IntersectionObserver — adds
117
+ `is-visible`), `ui-scroll-reveal` and `ui-scroll-progress` (zero-JS,
118
+ scroll-driven; the recommended reveal for static reports), and `ui-vt` (View
119
+ Transitions — needs the required `--ui-vt-name`, which must be **unique per
120
+ document**: reusing one name across sibling items silently drops the transition).
121
+ Prefer `ui-scroll-reveal` over `ui-reveal` when no JS will run. Details:
122
+ `docs/usage.md`.
123
+
72
124
  Optional display colorways — opt-in, never in the default bundle. Root-level,
73
125
  like `data-theme` (the derived accent family only recomputes at `:root`):
74
126
 
@@ -92,6 +144,54 @@ import charts from '@ponchia/ui/charts.json' with { type: 'json' };
92
144
  // charts.dark.categorical → ['#ff3b41', …] (series 0 = the resolved accent)
93
145
  ```
94
146
 
147
+ On-brand Mermaid diagrams use the same tokens-as-data path — Mermaid is the
148
+ consumer's renderer, bronto just hands it a resolved `base` theme (Mermaid can't
149
+ read `var(--x)`):
150
+
151
+ ```js
152
+ import { brontoMermaidTheme } from '@ponchia/ui/mermaid';
153
+ mermaid.initialize(brontoMermaidTheme('dark')); // { theme: 'base', themeVariables }
154
+ ```
155
+
156
+ Annotate a rendered diagram with the SVG annotation layer as a build-time
157
+ recipe. Details: `docs/mermaid.md`.
158
+
159
+ D2 (d2lang.com) is themed the same way — it compiles to a frozen SVG, so the
160
+ slots take resolved hex; the base ramp is monochrome and the accent is opt-in
161
+ per node:
162
+
163
+ ```js
164
+ import { brontoD2Vars } from '@ponchia/ui/d2';
165
+ const source = brontoD2Vars() + 'a -> b'; // prepend the vars block, then render
166
+ ```
167
+
168
+ Details: `docs/d2.md`.
169
+
170
+ Charting is the same path: bronto does NOT ship a chart component (a chart needs
171
+ scales + data binding, which the analytical layer refuses). For charts, recommend
172
+ Vega-Lite — a declarative JSON spec an external system can emit — themed by the
173
+ on-brand `config` (resolved hex; Vega bakes colours into SVG/canvas, can't read
174
+ `var()`). `range.category` is the `--chart-*` palette, series 1 = accent:
175
+
176
+ ```js
177
+ import { brontoVegaConfig, brontoVegaAccent, brontoVegaNeutral } from '@ponchia/ui/vega';
178
+ vegaEmbed('#chart', spec, { config: brontoVegaConfig('dark'), renderer: 'svg', actions: false });
179
+ ```
180
+
181
+ Pass `renderer: 'svg'` (canvas is the wrong default for print/inspection).
182
+ `brontoVegaAccent(theme)`/`brontoVegaNeutral(theme)` give the exact hexes to spend
183
+ the accent on one mark. From a CDN, pin the `/build/*.min.js` UMD bundles (a bare
184
+ `vega@6` tag has no `window.vega`; keep Vega-Lite 6 / Vega 6 / vega-embed 7
185
+ aligned) and INLINE the config from `vega.json` — a
186
+ `file://` report can't `import`/`fetch` it (CORS). A label on an accent fill in a
187
+ foreign renderer (a themed Vega/D2/Mermaid node or bar) reads the `--on-accent`
188
+ token, never `--accent-text` (that is accent-coloured text for a neutral bg).
189
+ `--on-accent` is a READ-ONLY export for those renderers — no in-DOM `.ui-*` rule
190
+ consumes it, so setting it does not re-ink a component; to colour text on an
191
+ accent-filled DOM control, set `--button-text`. Details: `docs/vega.md`. (Observable
192
+ Plot works too — it inherits the page CSS, so it needs even less theming;
193
+ Vega-Lite is the recommended LLM-emittable path.)
194
+
95
195
  `--chart-1..8` (categorical; series 1 = accent; colourblind-safe, gated under
96
196
  simulated protan/deutan/tritan), `--chart-seq-*` (sequential), `--chart-div-*`
97
197
  (diverging), and `--chart-pattern-1..8` (dot-matrix fills — pair colour N with
@@ -245,14 +345,147 @@ reports/AI output:
245
345
  ```
246
346
 
247
347
  `ui-citation` (inline ref on a real `<a>`/`<button>`; `--chip` = named-source
248
- pill), `ui-source-card` (+`__title`/`__origin`/`__time`/`__excerpt`/`__actions`),
249
- `ui-source-list` (+`__item`), and `ui-provenance` (+`__item`). A cross-cutting
250
- trust state sets the tone: `ui-src--verified`/`--reviewed`/`--generated`/
251
- `--unverified`/`--stale`/`--conflict` always paired with an author-written
252
- label (never colour alone). Bronto styles + states; the host owns fetching,
253
- numbering, and trust. `ui.citation({chip,state})` / `ui.source({state})` /
348
+ pill), `ui-source-card` (+`__title`/`__origin`/`__time`/`__excerpt`/`__actions`;
349
+ the body part is `__excerpt`, not `__detail`), `ui-source-list` (+`__item`),
350
+ `ui-provenance` (+`__item`), and `ui-src` (a standalone trust pill). A
351
+ cross-cutting trust state sets the tone: `ui-src--verified`/`--reviewed`/
352
+ `--generated`/`--unverified`/`--stale`/`--conflict` always paired with an
353
+ author-written label (never colour alone). A tone class **needs a host**:
354
+ `ui-src--verified` on its own renders nothing — put it on `ui-src`,
355
+ `ui-citation`, `ui-source-card`, or `ui-provenance__item`. Bronto styles +
356
+ states; the host owns fetching, numbering, and trust. `ui.citation({chip,state})` / `ui.source({state})` /
254
357
  `ui.provenance({state})`. Details: `docs/sources.md`.
255
358
 
359
+ Optional line/row change-review grammar — opt-in, CSS only, never in the
360
+ default bundle. For code review, changelogs, version history, config diffs, and
361
+ generated reports:
362
+
363
+ ```html
364
+ <link rel="stylesheet" href="@ponchia/ui/css/diff.css" />
365
+ ```
366
+
367
+ The HOST pre-classifies each row (`add`/`remove`/`context`), computes hunks, and
368
+ aligns split panes; Bronto only paints — it never parses or diffs source.
369
+ Unified: `ui-diff` with `ui-diff__row--add`/`--remove`/`--context` rows of
370
+ `ui-diff__ln` (line-number gutters, keep `aria-hidden`) + `ui-diff__code`.
371
+ Split: `ui-diff--split` holds two `ui-diff__pane` columns. The `+`/`−` gutter
372
+ glyph is generated content, so add/remove survive forced-colors and print where
373
+ the tint drops (never colour alone, WCAG 1.4.1). `ui.diff({ split })` /
374
+ `ui.diffRow({ change })`. Pairs with `ui-compare--2up`. Details: `docs/diff.md`.
375
+
376
+ Optional fenced-code evidence chrome — opt-in, CSS only, never in the default
377
+ bundle. For code-as-evidence in changelogs, version history, and reports:
378
+
379
+ ```html
380
+ <link rel="stylesheet" href="@ponchia/ui/css/code.css" />
381
+ ```
382
+
383
+ It NEVER parses or tokenizes — the host (or Shiki, via the shipped
384
+ `shiki/nothing.json` token theme) supplies the coloured spans; Bronto owns only
385
+ the chrome. `ui-code` (+`__head` filename bar, `__body` the `<pre>`); wrap each
386
+ line in `ui-code__line` to opt into the `ui-code--numbered` gutter (CSS
387
+ counters) and the `ui-code__line--add`/`--del`/`--hl` line states (forced-colors
388
+ + print safe via an inline-start border). Long lines wrap. `ui.code({ numbered })`
389
+ / `ui.codeLine({ change })`. Details: `docs/code.md`.
390
+
391
+ Optional inline datawords — opt-in, CSS only, never in the default bundle. A
392
+ word-sized microchart (trend-in-a-sentence) for reports and dense tables, the
393
+ inline counterpart to the scalar `ui-delta`/`ui-num`/`ui-stat`:
394
+
395
+ ```html
396
+ <link rel="stylesheet" href="@ponchia/ui/css/spark.css" />
397
+ ```
398
+
399
+ The HOST normalises each point to 0..1 and sets it as `--v` on a
400
+ `ui-spark__bar`; Bronto only paints. Pure CSS, SSR-static, print-safe. A bare
401
+ spark is opaque to AT, so the `ui-spark` container MUST carry a host-written
402
+ `role="img"` + `aria-label` (colour is never the only channel, WCAG 1.4.1).
403
+ `ui-spark__bar--accent`/`--pos`/`--neg` tone a single bar.
404
+ `ui.sparkBar({ tone })`. Details: `docs/spark.md`.
405
+
406
+ Optional Tufte margin notes — opt-in, CSS only, never in the default bundle. For
407
+ evidence, caveats, and provenance asides beside the text:
408
+
409
+ ```html
410
+ <link rel="stylesheet" href="@ponchia/ui/css/sidenote.css" />
411
+ ```
412
+
413
+ `ui-sidenote` is a numbered margin note (CSS counters; anchored by an inline
414
+ `ui-sidenote__ref`); `ui-marginnote` is the unnumbered variant. Wide viewports
415
+ float the note into the inline-end margin, narrow viewports collapse it to an
416
+ indented inline block. The HOST owns where numbering restarts
417
+ (`counter-reset: ui-sidenote` on the article) and reserves the margin gutter
418
+ (`padding-inline-end`). Details: `docs/sidenote.md`.
419
+
420
+ Optional deep-link-to-cited-text — opt-in, CSS only, never in the default
421
+ bundle. For a citation that jumps to the EXACT quoted sentence:
422
+
423
+ ```html
424
+ <link rel="stylesheet" href="@ponchia/ui/css/textref.css" />
425
+ ```
426
+
427
+ `ui-textref` is a link whose `href` is a URL Text Fragment (`#…:~:text=`); the
428
+ browser scrolls to + highlights the quote and Bronto owns the on-brand
429
+ `::target-text` paint (`--textref-highlight`). The HOST builds the fragment URL
430
+ (a three-line pure encoder, see docs); no kernel ships. Text Fragment nav needs
431
+ a real user activation; unsupported engines just navigate (the highlight is
432
+ additive). Details: `docs/textref.md`.
433
+
434
+ Optional bullet graph — opt-in, CSS only, never in the default bundle. The
435
+ Stephen-Few measure-vs-target-vs-bands SLO figure `ui-meter` can't encode:
436
+
437
+ ```html
438
+ <link rel="stylesheet" href="@ponchia/ui/css/bullet.css" />
439
+ ```
440
+
441
+ `ui-bullet` is the track + grayscale qualitative bands (`--band-lo`/`--band-hi`);
442
+ `ui-bullet__measure` is the value bar (REQUIRED `--v` 0..1, `--accent`/`--pos`/
443
+ `--neg` tones); `ui-bullet__target` is the tick at `--t`; `ui-bullet__label` an
444
+ optional caption. Same contract as spark: the HOST normalises, Bronto paints. A
445
+ bare bullet is opaque to AT, so `ui-bullet` MUST carry a host-written
446
+ `role="img"` + `aria-label`. `ui.bulletMeasure({ tone })`. Details:
447
+ `docs/bullet.md`.
448
+
449
+ Optional inline glossary — opt-in, CSS only, never in the default bundle. The
450
+ accessible upgrade of the broken `abbr[title]`:
451
+
452
+ ```html
453
+ <link rel="stylesheet" href="@ponchia/ui/css/term.css" />
454
+ ```
455
+
456
+ `ui-term` is the term `<button popovertarget>` (keyboard/touch-reachable);
457
+ `ui-def` is the definition body — a native `[popover]` styled as a raised card;
458
+ `ui-glossary` is the end-of-document `<dl>` (`ui-glossary__term`/`__def`). The
459
+ native popover pairing gives open/Esc/light-dismiss for free, no kernel. Popovers
460
+ don't print — the printed doc leans on the glossary block. Details: `docs/term.md`.
461
+
462
+ Optional scrollspy table-of-contents — opt-in, CSS only, never in the default
463
+ bundle. A sticky contents rail that highlights the section in view:
464
+
465
+ ```html
466
+ <link rel="stylesheet" href="@ponchia/ui/css/toc.css" />
467
+ ```
468
+
469
+ `ui-toc` is the sticky rail (`--toc-top`); `ui-toc__title`/`ui-toc__list`/
470
+ `ui-toc__link`. The active entry keys on `aria-current="true"`. CSS can't know
471
+ the in-view section, so the HOST mirrors it — statically, or with a small
472
+ copy-paste IntersectionObserver (no kernel ships). Without it the rail is a plain
473
+ anchored list. Details: `docs/toc.md`.
474
+
475
+ Optional hierarchy outline — opt-in, CSS only, never in the default bundle. A
476
+ depth-indented tree on nested native `<details>`:
477
+
478
+ ```html
479
+ <link rel="stylesheet" href="@ponchia/ui/css/tree.css" />
480
+ ```
481
+
482
+ `ui-tree` is the outline; `ui-tree__branch` is a `<details>` node (twist
483
+ chevron; add `name` for an exclusive-accordion group); `ui-tree__leaf` a childless
484
+ row; `ui-tree__summary`/`ui-tree__label`. Open/close + keyboard are native
485
+ `<details>`. A11y honesty: this is a disclosure group, NOT an ARIA `tree` — don't
486
+ add `role="tree"`; the roving-focus kernel is deferred behind a real consumer.
487
+ Details: `docs/tree.md`.
488
+
256
489
  Optional lifecycle/system-state vocabulary — opt-in, CSS only, never in the
257
490
  default bundle. The states apps live in (saving/saved/queued/offline/stale/
258
491
  conflict/error/locked/reviewed/needs-review):
@@ -351,10 +584,18 @@ Canonical report skeleton:
351
584
  Report rules for agents: static output by default; do not initialize behaviors
352
585
  over untrusted generated content; sanitize arbitrary LLM/CMS/user HTML before
353
586
  rendering; use semantic headings; give tables captions and header cells; give
354
- charts captions, legends/direct labels, and fallback data; use
355
- `ui-chart__plot`/`ui-chart__bar`/`ui-chart__fill` for simple static bar charts;
356
- use `ui-report__section--unnumbered` for appendices in numbered reports; never
357
- use raw chromatic inline colors. Full cookbook: `docs/reporting.md`.
587
+ charts captions, legends/direct labels, and fallback data; for a chart, theme
588
+ Vega-Lite with `@ponchia/ui/vega` (or hand-author a token-themed inline `<svg>`)
589
+ inside a `ui-report__figure` bronto ships no chart component; use
590
+ `ui-delta` (`--up`/`--down`/`--flat`, `--invert` when up is bad) for a
591
+ trend figure and `ui-compare` (`--2up`) for an A/B / before-after section; use
592
+ `ui-report__section--unnumbered` for appendices in numbered reports; never
593
+ use raw chromatic inline colors. Format numbers/dates yourself (the framework
594
+ aligns figures, it does not format them) — see the reporting cookbook. To make
595
+ a PDF, render with `chrome-headless-shell` (or any Chromium) using
596
+ `printBackground: true` so figure fills survive — reports are static/zero-JS, so
597
+ it is just load → print; see "Print and PDF" in `docs/reporting.md`. Full
598
+ cookbook: `docs/reporting.md`.
358
599
 
359
600
  ## Authoritative offline references (shipped in this package)
360
601
 
@@ -363,6 +604,15 @@ Read these from `node_modules/@ponchia/ui/` — no network needed:
363
604
  - `classes/index.d.ts` — literal-typed `cls` map (exact class strings),
364
605
  every `ui.*()` recipe signature, every `*Opts` interface. The complete
365
606
  class surface; an agent should read this to know valid class names.
607
+ - `classes/classes.json` — the same vocabulary as language-neutral data, to
608
+ VALIDATE markup without executing ESM/parsing TS: `groups` (base →
609
+ modifiers/parts, the BEM structure; `base` is null for a parts-only namespace —
610
+ do not emit it), `classes` (flat list), `states` (the `is-*` hooks that live
611
+ outside `cls` by design, with their scope), `customProperties` (the author-set
612
+ inline-style knobs like `--chart-color` / `--value`), `behaviorAttributes` (the
613
+ `data-bronto-*` open/close/dismiss hooks the optional behaviors delegate on), and
614
+ `requiredAria` (the role/aria a generator must emit per component — meter/progress/
615
+ error-summary paint but are invisible to AT without it).
366
616
  - `docs/reference.md` — the full class catalog as prose tables (every
367
617
  class grouped by component, with registry key + kind). Generated from
368
618
  the same source as the types and CI-drift-checked.
@@ -378,6 +628,13 @@ Read these from `node_modules/@ponchia/ui/` — no network needed:
378
628
  boundaries.
379
629
  - `docs/annotations.md` — SVG annotation recipes and helper guidance for
380
630
  analytical figures.
631
+ - `docs/mermaid.md` — theme Mermaid diagrams from bronto tokens (resolved
632
+ `base` themeVariables, gated) and annotate the rendered SVG.
633
+ - `docs/d2.md` — theme D2 diagrams from bronto tokens (theme-override slots,
634
+ monochrome base + opt-in accent, gated) and annotate the rendered SVG.
635
+ - `docs/vega.md` — theme Vega-Lite charts from bronto tokens (resolved `config`,
636
+ gated + render-probed) — the recommended path when a report needs a chart,
637
+ since bronto ships no chart component.
381
638
  - `docs/contrast.md` — the published, CI-gated WCAG 2.1 contrast matrix
382
639
  for every contractual token pairing, per theme. Generated from the
383
640
  resolved palette; the build fails below the declared floor.
@@ -385,8 +642,11 @@ Read these from `node_modules/@ponchia/ui/` — no network needed:
385
642
  - `tokens/index.json` — tokens as plain data (global / light / dark).
386
643
  - `tokens/tokens.dtcg.json` — same tokens in W3C DTCG format.
387
644
  - `tokens/resolved.json` — every colour token resolved to a static
388
- `#rrggbb` / `rgba(...)` per theme (var() + color-mix() evaluated).
389
- Use this for non-CSS render targets: MapLibre/canvas/WebGL/SVG.
645
+ `#rrggbb` / `rgba(...)` per theme (var() + color-mix() evaluated) in
646
+ `light`/`dark`, plus a `scale` block of the non-colour scales
647
+ (spacing/radius/type/z/motion, var() chains flattened). The complete token
648
+ contract for non-CSS render targets: MapLibre/canvas/WebGL/SVG, or a
649
+ non-JS host (Python/Go) building a themed report.
390
650
  - `behaviors/index.d.ts` — typed signatures for the optional behaviors.
391
651
  - `glyphs/glyphs.d.ts` — the `GlyphName` literal union plus `renderGlyph` /
392
652
  `glyphCells` signatures for the display glyphs. (The DOM form,
@@ -404,13 +664,24 @@ Read these from `node_modules/@ponchia/ui/` — no network needed:
404
664
 
405
665
  ## Rules an agent should respect
406
666
 
407
- - Never invent `ui-*` class names. Every valid class is a member of
408
- `cls` in `classes/index.d.ts`; if it is not there, it does not exist.
667
+ - Never invent `ui-*` class names. Every valid `ui-*` class is a member of
668
+ `cls` in `classes/index.d.ts` (and `classes/classes.json`); if a `ui-*`
669
+ name is not there, it does not exist. The `is-*` state hooks
670
+ (`is-num`/`is-pos`/`is-neg`/`is-key` on `.ui-table` cells and `.ui-stat`
671
+ deltas, `is-open`/`is-active`/`is-inactive` on stateful components) are the
672
+ one exception — they are real, documented in `docs/reference.md`
673
+ (§"Table-local state classes" / §"Composition & state") and emitted by the
674
+ `ui.*()` recipes, but deliberately NOT in `cls`. Do not strip them.
409
675
  - Prefer the `ui.*()` recipes over hand-concatenating modifier strings.
410
676
  Report/layout classes added in 0.4.1 are the exception: use `cls.report*`,
411
677
  `cls.chart*`, `cls.printOnly`, or literal documented class names because
412
678
  there are no `ui.report()` / `ui.chart()` recipes yet. Annotations do have a
413
679
  `ui.annotation()` recipe for variant/tone selection.
680
+ - For a standalone HTML report, never `<link>` a `@ponchia/ui/css/*.css`
681
+ package specifier (it does not resolve in a browser) and never assume
682
+ `dist/bronto.css` carries the report/chart/legend/annotation layers — it
683
+ does not. Link each opt-in leaf from `dist/css/` via a real URL
684
+ (`./node_modules/…` or a pinned CDN). See the loading note above.
414
685
  - Override framework styles by writing your own rules outside
415
686
  `@layer bronto` — not with higher specificity or `!important`.
416
687
  - Color is tiered (ADR-0001): neutral canvas · one rationed accent · locked
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ponchia/ui",
3
- "version": "0.5.0",
3
+ "version": "0.6.3",
4
4
  "type": "module",
5
5
  "description": "CSS-first design system for interfaces that explain themselves — works in HTML, every framework, and PDF, no component runtime. A standard component set plus an opt-in analytical & report layer (annotations, legends, connectors, data-viz, report grammar). Monochrome with one rationed accent, re-skinnable from one --accent knob. Zero runtime dependencies.",
6
6
  "keywords": [
@@ -35,6 +35,9 @@
35
35
  "access": "public",
36
36
  "provenance": true
37
37
  },
38
+ "engines": {
39
+ "node": ">=18"
40
+ },
38
41
  "sideEffects": [
39
42
  "**/*.css"
40
43
  ],
@@ -62,6 +65,9 @@
62
65
  "docs/stability.md",
63
66
  "docs/usage.md",
64
67
  "docs/reporting.md",
68
+ "docs/mermaid.md",
69
+ "docs/d2.md",
70
+ "docs/vega.md",
65
71
  "docs/annotations.md",
66
72
  "docs/legends.md",
67
73
  "docs/marks.md",
@@ -70,6 +76,15 @@
70
76
  "docs/crosshair.md",
71
77
  "docs/selection.md",
72
78
  "docs/sources.md",
79
+ "docs/diff.md",
80
+ "docs/code.md",
81
+ "docs/spark.md",
82
+ "docs/sidenote.md",
83
+ "docs/textref.md",
84
+ "docs/bullet.md",
85
+ "docs/term.md",
86
+ "docs/toc.md",
87
+ "docs/tree.md",
73
88
  "docs/state.md",
74
89
  "docs/generated.md",
75
90
  "docs/workbench.md",
@@ -85,59 +100,76 @@
85
100
  "format": "prettier --write .",
86
101
  "check:format": "prettier --check .",
87
102
  "size:report": "node scripts/size-report.mjs",
103
+ "report:pdf": "node scripts/render-pdf.mjs",
104
+ "emit:theme": "node scripts/emit-theme.mjs",
105
+ "emit:theme:check": "node scripts/emit-theme.mjs --check",
106
+ "gen": "npm run prepack",
107
+ "fresh:build": "node scripts/gen-all.mjs",
88
108
  "tokens:build": "node scripts/gen-tokens-json.mjs",
89
109
  "tokens:css:build": "node scripts/gen-tokens-css.mjs",
90
110
  "dtcg:build": "node scripts/gen-dtcg.mjs",
91
111
  "resolved:build": "node scripts/gen-resolved.mjs",
92
112
  "dts:build": "node scripts/gen-dts.mjs",
113
+ "dts:emit": "node scripts/emit-dts.mjs",
93
114
  "glyphs:build": "node scripts/gen-glyphs.mjs",
94
115
  "skins:build": "node scripts/gen-skins.mjs",
95
116
  "charts:build": "node scripts/gen-charts.mjs",
117
+ "mermaid:build": "node scripts/gen-mermaid.mjs",
118
+ "d2:build": "node scripts/gen-d2.mjs",
119
+ "vega:build": "node scripts/gen-vega.mjs",
96
120
  "reference:build": "node scripts/gen-reference.mjs",
121
+ "classes:json:build": "node scripts/gen-classes-json.mjs",
97
122
  "contrast:build": "node scripts/gen-contrast.mjs",
98
123
  "vscode:build": "node scripts/gen-vscode-data.mjs",
99
124
  "dist:build": "node scripts/build-dist.mjs",
100
125
  "check:exports": "node scripts/check-exports.mjs",
101
- "check:tokens": "node scripts/check-tokens.mjs",
126
+ "check:fresh": "node scripts/check-fresh.mjs",
102
127
  "check:classes": "node scripts/check-classes.mjs",
103
- "check:dts": "node scripts/check-dts.mjs",
104
- "check:behaviors": "node scripts/check-behaviors.mjs",
105
- "check:bindings": "node scripts/check-bindings.mjs",
106
- "check:helpers-dts": "node scripts/check-helpers-dts.mjs",
128
+ "check:recipe-types": "node scripts/check-recipe-types.mjs",
129
+ "check:chain": "node scripts/check-chain.mjs",
130
+ "check:dts-emit": "node scripts/check-dts-emit.mjs",
107
131
  "check:glyphs": "node scripts/check-glyphs.mjs",
108
132
  "check:color-policy": "node scripts/check-color-policy.mjs",
109
133
  "check:skins": "node scripts/check-skins.mjs",
110
134
  "check:charts": "node scripts/check-charts.mjs",
135
+ "check:mermaid": "node scripts/check-mermaid.mjs",
136
+ "check:d2": "node scripts/check-d2.mjs",
137
+ "check:vega": "node scripts/check-vega.mjs",
111
138
  "check:report": "node scripts/check-report.mjs",
112
139
  "check:legend": "node scripts/check-legend.mjs",
113
140
  "check:types": "tsc -p tsconfig.json",
114
- "check:dtcg": "node scripts/check-dtcg.mjs",
115
- "check:resolved": "node scripts/check-resolved.mjs",
116
141
  "check:shiki": "node scripts/check-shiki.mjs",
117
142
  "check:dist": "node scripts/check-dist.mjs",
118
143
  "check:pack": "node scripts/check-pack.mjs",
119
144
  "check:release": "node scripts/check-release.mjs",
120
- "check:reference": "node scripts/check-reference.mjs",
145
+ "check:versions": "node scripts/check-versions.mjs",
146
+ "check:doc-recipes": "node scripts/check-doc-recipes.mjs",
147
+ "check:contract": "node scripts/check-contract.mjs",
121
148
  "check:contrast": "node scripts/check-contrast.mjs",
122
- "check:vscode": "node scripts/check-vscode-data.mjs",
123
- "check": "npm run lint && npm run check:format && npm run check:exports && npm run check:tokens && npm run check:classes && npm run check:dts && npm run check:types && npm run check:dtcg && npm run check:resolved && npm run check:shiki && npm run check:dist && npm run check:pack && npm run check:release && npm run check:reference && npm run check:contrast && npm run check:vscode && npm run check:behaviors && npm run check:bindings && npm run check:helpers-dts && npm run check:glyphs && npm run check:color-policy && npm run check:skins && npm run check:charts && npm run check:report && npm run check:legend",
149
+ "check:publint": "publint --strict",
150
+ "check:attw": "attw --pack --ignore-rules no-resolution cjs-resolves-to-esm",
151
+ "check": "npm run lint && npm run check:format && npm run check:exports && npm run check:fresh && npm run check:classes && npm run check:recipe-types && npm run check:types && npm run check:shiki && npm run check:dist && npm run check:pack && npm run check:publint && npm run check:attw && npm run check:release && npm run check:versions && npm run check:doc-recipes && npm run check:contract && npm run check:contrast && npm run check:dts-emit && npm run check:glyphs && npm run check:color-policy && npm run check:skins && npm run check:charts && npm run check:mermaid && npm run check:d2 && npm run check:vega && npm run check:report && npm run check:legend && npm run check:chain",
124
152
  "test": "node --test \"test/*.test.mjs\"",
125
- "prepack": "npm run tokens:css:build && npm run tokens:build && npm run dtcg:build && npm run resolved:build && npm run dts:build && npm run reference:build && npm run contrast:build && npm run vscode:build && npm run skins:build && npm run charts:build && npm run dist:build && npm run glyphs:build",
153
+ "prepack": "npm run tokens:css:build && npm run tokens:build && npm run dtcg:build && npm run resolved:build && npm run dts:build && npm run dts:emit && npm run reference:build && npm run classes:json:build && npm run contrast:build && npm run vscode:build && npm run skins:build && npm run charts:build && npm run mermaid:build && npm run d2:build && npm run vega:build && npm run dist:build && npm run glyphs:build",
126
154
  "prepublishOnly": "npm run check && npm test"
127
155
  },
128
156
  "devDependencies": {
157
+ "@arethetypeswrong/cli": "^0.18.3",
129
158
  "@axe-core/playwright": "^4.11.3",
130
159
  "@builder.io/qwik": "^1.20.0",
131
- "@playwright/test": "^1.60.0",
160
+ "@playwright/test": "1.60.0",
132
161
  "jsdom": "^29.1.1",
133
162
  "prettier": "^3.8.3",
134
- "react": "^19.2.6",
135
- "react-dom": "^19.2.6",
163
+ "publint": "^0.3.21",
164
+ "react": "^19.2.7",
165
+ "react-dom": "^19.2.7",
136
166
  "solid-js": "^1.9.13",
137
- "stylelint": "^17.11.1",
167
+ "stylelint": "^17.13.0",
138
168
  "stylelint-config-standard": "^40.0.0",
139
169
  "stylelint-use-logical": "^2.1.3",
140
- "typescript": "^6.0.3"
170
+ "typescript": "^6.0.3",
171
+ "vega": "^6.2.0",
172
+ "vega-lite": "^6.4.3"
141
173
  },
142
174
  "peerDependencies": {
143
175
  "@builder.io/qwik": ">=1.5",
@@ -189,6 +221,15 @@
189
221
  "./css/crosshair.css": "./dist/css/crosshair.css",
190
222
  "./css/selection.css": "./dist/css/selection.css",
191
223
  "./css/sources.css": "./dist/css/sources.css",
224
+ "./css/diff.css": "./dist/css/diff.css",
225
+ "./css/code.css": "./dist/css/code.css",
226
+ "./css/spark.css": "./dist/css/spark.css",
227
+ "./css/sidenote.css": "./dist/css/sidenote.css",
228
+ "./css/textref.css": "./dist/css/textref.css",
229
+ "./css/bullet.css": "./dist/css/bullet.css",
230
+ "./css/term.css": "./dist/css/term.css",
231
+ "./css/toc.css": "./dist/css/toc.css",
232
+ "./css/tree.css": "./dist/css/tree.css",
192
233
  "./css/state.css": "./dist/css/state.css",
193
234
  "./css/generated.css": "./dist/css/generated.css",
194
235
  "./css/workbench.css": "./dist/css/workbench.css",
@@ -220,6 +261,15 @@
220
261
  "./css/unlayered/crosshair.css": "./css/crosshair.css",
221
262
  "./css/unlayered/selection.css": "./css/selection.css",
222
263
  "./css/unlayered/sources.css": "./css/sources.css",
264
+ "./css/unlayered/diff.css": "./css/diff.css",
265
+ "./css/unlayered/code.css": "./css/code.css",
266
+ "./css/unlayered/spark.css": "./css/spark.css",
267
+ "./css/unlayered/sidenote.css": "./css/sidenote.css",
268
+ "./css/unlayered/textref.css": "./css/textref.css",
269
+ "./css/unlayered/bullet.css": "./css/bullet.css",
270
+ "./css/unlayered/term.css": "./css/term.css",
271
+ "./css/unlayered/toc.css": "./css/toc.css",
272
+ "./css/unlayered/tree.css": "./css/tree.css",
223
273
  "./css/unlayered/state.css": "./css/state.css",
224
274
  "./css/unlayered/generated.css": "./css/generated.css",
225
275
  "./css/unlayered/workbench.css": "./css/workbench.css",
@@ -241,6 +291,9 @@
241
291
  "./docs/stability.md": "./docs/stability.md",
242
292
  "./docs/usage.md": "./docs/usage.md",
243
293
  "./docs/reporting.md": "./docs/reporting.md",
294
+ "./docs/mermaid.md": "./docs/mermaid.md",
295
+ "./docs/d2.md": "./docs/d2.md",
296
+ "./docs/vega.md": "./docs/vega.md",
244
297
  "./docs/annotations.md": "./docs/annotations.md",
245
298
  "./docs/legends.md": "./docs/legends.md",
246
299
  "./docs/marks.md": "./docs/marks.md",
@@ -249,6 +302,15 @@
249
302
  "./docs/crosshair.md": "./docs/crosshair.md",
250
303
  "./docs/selection.md": "./docs/selection.md",
251
304
  "./docs/sources.md": "./docs/sources.md",
305
+ "./docs/diff.md": "./docs/diff.md",
306
+ "./docs/code.md": "./docs/code.md",
307
+ "./docs/spark.md": "./docs/spark.md",
308
+ "./docs/sidenote.md": "./docs/sidenote.md",
309
+ "./docs/textref.md": "./docs/textref.md",
310
+ "./docs/bullet.md": "./docs/bullet.md",
311
+ "./docs/term.md": "./docs/term.md",
312
+ "./docs/toc.md": "./docs/toc.md",
313
+ "./docs/tree.md": "./docs/tree.md",
252
314
  "./docs/state.md": "./docs/state.md",
253
315
  "./docs/generated.md": "./docs/generated.md",
254
316
  "./docs/workbench.md": "./docs/workbench.md",
@@ -260,6 +322,7 @@
260
322
  "types": "./classes/index.d.ts",
261
323
  "default": "./classes/index.js"
262
324
  },
325
+ "./classes.json": "./classes/classes.json",
263
326
  "./behaviors": {
264
327
  "types": "./behaviors/index.d.ts",
265
328
  "default": "./behaviors/index.js"
@@ -297,6 +360,21 @@
297
360
  "default": "./tokens/charts.js"
298
361
  },
299
362
  "./charts.json": "./tokens/charts.json",
363
+ "./mermaid": {
364
+ "types": "./tokens/mermaid.d.ts",
365
+ "default": "./tokens/mermaid.js"
366
+ },
367
+ "./mermaid.json": "./tokens/mermaid.json",
368
+ "./d2": {
369
+ "types": "./tokens/d2.d.ts",
370
+ "default": "./tokens/d2.js"
371
+ },
372
+ "./d2.json": "./tokens/d2.json",
373
+ "./vega": {
374
+ "types": "./tokens/vega.d.ts",
375
+ "default": "./tokens/vega.js"
376
+ },
377
+ "./vega.json": "./tokens/vega.json",
300
378
  "./fonts/*": "./fonts/*"
301
379
  }
302
380
  }