@ponchia/ui 0.6.3 → 0.6.5

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 (51) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +7 -7
  3. package/behaviors/glyph.d.ts +7 -0
  4. package/behaviors/glyph.d.ts.map +1 -1
  5. package/behaviors/glyph.js +58 -4
  6. package/behaviors/index.d.ts +2 -0
  7. package/behaviors/index.d.ts.map +1 -1
  8. package/behaviors/index.js +2 -0
  9. package/behaviors/sources.d.ts +28 -0
  10. package/behaviors/sources.d.ts.map +1 -0
  11. package/behaviors/sources.js +158 -0
  12. package/classes/classes.json +210 -4
  13. package/classes/index.d.ts +75 -1
  14. package/classes/index.js +95 -1
  15. package/css/dots.css +210 -3
  16. package/css/report.css +359 -7
  17. package/css/skins.css +9 -0
  18. package/css/sources.css +18 -0
  19. package/css/spark.css +14 -0
  20. package/css/table.css +7 -1
  21. package/css/tokens.css +8 -1
  22. package/dist/bronto.css +1 -1
  23. package/dist/css/dots.css +1 -1
  24. package/dist/css/report.css +1 -1
  25. package/dist/css/skins.css +1 -1
  26. package/dist/css/sources.css +1 -1
  27. package/dist/css/spark.css +1 -1
  28. package/dist/css/table.css +1 -1
  29. package/dist/css/tokens.css +1 -1
  30. package/docs/dots.md +146 -0
  31. package/docs/frontier-primitives.md +262 -0
  32. package/docs/glyphs.md +114 -0
  33. package/docs/package-contract.md +263 -0
  34. package/docs/reference.md +115 -1
  35. package/docs/reporting.md +296 -16
  36. package/docs/sources.md +32 -0
  37. package/docs/stability.md +6 -3
  38. package/glyphs/glyphs.d.ts +61 -0
  39. package/glyphs/glyphs.js +593 -30
  40. package/llms.txt +79 -25
  41. package/package.json +13 -3
  42. package/qwik/index.d.ts +1 -0
  43. package/qwik/index.d.ts.map +1 -1
  44. package/qwik/index.js +5 -0
  45. package/react/index.d.ts +1 -0
  46. package/react/index.d.ts.map +1 -1
  47. package/react/index.js +3 -0
  48. package/solid/index.d.ts +2 -0
  49. package/solid/index.d.ts.map +1 -1
  50. package/solid/index.js +3 -0
  51. package/tokens/skins.js +22 -9
package/docs/reporting.md CHANGED
@@ -37,11 +37,11 @@ No install? Link the same files from a CDN. Pin the version — pre-1.0, breakin
37
37
  changes ship in the minor (see [stability.md](./stability.md)):
38
38
 
39
39
  ```html
40
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.3/dist/bronto.css" />
41
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.3/dist/css/report.css" />
42
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.3/dist/css/dataviz.css" />
43
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.3/dist/css/annotations.css" />
44
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.3/dist/css/legend.css" />
40
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.5/dist/bronto.css" />
41
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.5/dist/css/report.css" />
42
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.5/dist/css/dataviz.css" />
43
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.5/dist/css/annotations.css" />
44
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.5/dist/css/legend.css" />
45
45
  ```
46
46
 
47
47
  The CDN serves the package's own `fonts/` next to the CSS, so font URLs resolve
@@ -106,6 +106,24 @@ they are all safe in the static, PDF-first report path.
106
106
  <div class="ui-report__summary">
107
107
  <p>The summary block is for the decision-level conclusion.</p>
108
108
  </div>
109
+ <aside class="ui-report__decision" aria-labelledby="decision-title">
110
+ <p class="ui-report__decision-kicker">Decision</p>
111
+ <h3 class="ui-report__decision-title" id="decision-title">Ship the low-risk path</h3>
112
+ <p class="ui-report__decision-body">
113
+ State the operator-facing call first, then list the evidence below it.
114
+ </p>
115
+ <dl class="ui-report__decision-grid">
116
+ <div class="ui-report__decision-item">
117
+ <dt class="ui-report__decision-label">Basis</dt>
118
+ <dd class="ui-report__decision-value">Two verified sources support the call.</dd>
119
+ </div>
120
+ <div class="ui-report__decision-item">
121
+ <dt class="ui-report__decision-label">Next action</dt>
122
+ <dd class="ui-report__decision-value">Owner rechecks the remaining caveat by Jun 8.</dd>
123
+ </div>
124
+ </dl>
125
+ <p class="ui-report__decision-meta">Evidence state: supported · Checked: 2026-06-01</p>
126
+ </aside>
109
127
  <div class="ui-statgrid">
110
128
  <div class="ui-stat">
111
129
  <span class="ui-stat__label">Open risks</span>
@@ -127,6 +145,147 @@ they are all safe in the static, PDF-first report path.
127
145
  </main>
128
146
  ```
129
147
 
148
+ ## Report-specific primitives
149
+
150
+ Use these report-layer primitives before inventing custom card layouts. They are
151
+ generic, static, and PDF-safe; the host still owns the content, scoring, source
152
+ fetching, and claim wording.
153
+
154
+ - `ui-report__decision` is the above-the-fold call. Pair it with
155
+ `ui-report__decision-kicker`, `ui-report__decision-title`,
156
+ `ui-report__decision-body`, optional `ui-report__decision-grid` /
157
+ `ui-report__decision-item` detail rows, and optional
158
+ `ui-report__decision-meta`. It should answer "what should the reader do or
159
+ believe now?" before the deep evidence. Good rows are basis, impact, next
160
+ action, owner, recheck date, and evidence state.
161
+ - `ui-report__finding` is the repeated finding block. Add
162
+ `ui-report__finding--critical`, `--major`, `--minor`, or `--resolved` only
163
+ when the written finding label also states the severity/status. The colour
164
+ band is a scanning aid, not the data of record. For dense reports, use
165
+ `ui-report__finding-title`, `ui-report__finding-claim`,
166
+ `ui-report__finding-impact`, `ui-report__finding-remediation`,
167
+ `ui-report__finding-evidence`, and `ui-report__finding-caveat` so impact,
168
+ evidence, caveat, and remediation do not collapse into one paragraph.
169
+ - `ui-claim` is the smallest claim/evidence contract. Use
170
+ `ui-claim--supported`, `--partial`, `--disputed`, `--unsupported`, or
171
+ `--unknown` only when the written `ui-claim__status` says the same thing.
172
+ Use `ui-claim__statement`, `__scope`, `__basis`, `__limits`, `__refs`, and
173
+ `__caveat` to show what the report asserts, where it applies, what supports
174
+ it, what would limit or change it, and which sources/evidence entries it maps
175
+ to.
176
+ - `ui-evidence-grid` and `ui-evidence-item` are for compact evidence packets:
177
+ one source, check, observation, counterexample, or assumption per item. Use
178
+ `ui-evidence-item__title`, `__meta`, and `__body` for simple cards; add
179
+ `__kind`, `__method`, `__window`, `__value`, `__source`, and `__caveat` when
180
+ the evidence needs to say how it was gathered. Link to source cards or a table
181
+ when the evidence is more than a sentence.
182
+ - `ui-evidence-ledger` is a wrapper for a claim/evidence/source matrix. Put a
183
+ normal `ui-table` inside it with columns such as claim, evidence, source,
184
+ trust, freshness, relation, and caveat.
185
+ - `ui-report__actions`, `ui-report__action`, and
186
+ `ui-report__action-status` are for follow-up rows in status, incident, and
187
+ audit reports. Add `ui-report__action-title`, `__action-owner`,
188
+ `__action-due`, `__action-priority`, `__action-criteria`, and
189
+ `__action-source` when the action is a real workflow item. The status text
190
+ must be written out; do not rely on tone alone.
191
+
192
+ Decision brief pattern:
193
+
194
+ ```html
195
+ <aside class="ui-report__decision" aria-labelledby="decision-title">
196
+ <p class="ui-report__decision-kicker">Decision</p>
197
+ <h3 class="ui-report__decision-title" id="decision-title">Adopt the safer option</h3>
198
+ <p class="ui-report__decision-body">
199
+ The current evidence supports the lower-risk path while the disputed source is rechecked.
200
+ </p>
201
+ <dl class="ui-report__decision-grid">
202
+ <div class="ui-report__decision-item">
203
+ <dt class="ui-report__decision-label">Basis</dt>
204
+ <dd class="ui-report__decision-value">Verified metrics support the call; one source is stale.</dd>
205
+ </div>
206
+ <div class="ui-report__decision-item">
207
+ <dt class="ui-report__decision-label">Recheck</dt>
208
+ <dd class="ui-report__decision-value"><time datetime="2026-06-08">2026-06-08</time></dd>
209
+ </div>
210
+ </dl>
211
+ <p class="ui-report__decision-meta">Evidence state: partial · Sources: 4 · Checked: 2026-06-01</p>
212
+ </aside>
213
+ ```
214
+
215
+ Finding + evidence pattern:
216
+
217
+ ```html
218
+ <article class="ui-report__finding ui-report__finding--major" aria-labelledby="finding-cache">
219
+ <p class="ui-eyebrow" id="finding-cache">Major finding — cache pressure is rising</p>
220
+ <p class="ui-report__finding-claim">
221
+ Claim: cache pressure is rising during the refresh window.
222
+ </p>
223
+ <p class="ui-report__finding-impact">Impact: p95 latency is likely to breach target if volume rises.</p>
224
+ <p class="ui-report__finding-remediation">Remediation: lower the refresh batch size before the next rollout.</p>
225
+ <p class="ui-report__finding-caveat">
226
+ Caveat: the conclusion assumes comparable traffic shape in the next window.
227
+ </p>
228
+ </article>
229
+ <div class="ui-evidence-grid" aria-label="Evidence summary">
230
+ <article class="ui-evidence-item">
231
+ <h3 class="ui-evidence-item__title">Metric trend</h3>
232
+ <p class="ui-evidence-item__kind">Observation</p>
233
+ <p class="ui-evidence-item__meta">Prometheus · 24 h window</p>
234
+ <p class="ui-evidence-item__body">p95 latency rose 18% while request volume stayed flat.</p>
235
+ </article>
236
+ <article class="ui-evidence-item">
237
+ <h3 class="ui-evidence-item__title">Log sample</h3>
238
+ <p class="ui-evidence-item__meta">Application logs · reviewed</p>
239
+ <p class="ui-evidence-item__body">Timeouts cluster around cache refresh intervals.</p>
240
+ </article>
241
+ </div>
242
+ ```
243
+
244
+ Claim block pattern:
245
+
246
+ ```html
247
+ <article class="ui-claim ui-claim--partial" id="claim-latency">
248
+ <p class="ui-claim__statement">The migration improved latency without reducing availability.</p>
249
+ <p class="ui-claim__status">Evidence state: partial</p>
250
+ <p class="ui-claim__scope">Scope: last 7 days, production traffic only</p>
251
+ <p class="ui-claim__basis">Basis: metrics export S1 and incident note S2 support the claim.</p>
252
+ <p class="ui-claim__limits">Limit: retry volume still needs a separate review.</p>
253
+ <p class="ui-claim__refs">Sources: <a class="ui-citation" href="#source-metrics">S1</a></p>
254
+ </article>
255
+ ```
256
+
257
+ Evidence ledger pattern:
258
+
259
+ ```html
260
+ <div class="ui-evidence-ledger">
261
+ <div class="ui-table-wrap">
262
+ <table class="ui-table ui-table--dense">
263
+ <caption>Claim, evidence, and caveat ledger</caption>
264
+ <thead>
265
+ <tr>
266
+ <th>Claim</th>
267
+ <th>Evidence</th>
268
+ <th>Source</th>
269
+ <th>Trust</th>
270
+ <th>Relation</th>
271
+ <th>Caveat</th>
272
+ </tr>
273
+ </thead>
274
+ <tbody>
275
+ <tr>
276
+ <td><a href="#claim-latency">Latency improved</a></td>
277
+ <td>p95 fell 48 ms</td>
278
+ <td><a class="ui-citation" href="#source-metrics">S1</a></td>
279
+ <td>Verified</td>
280
+ <td>Supports</td>
281
+ <td>Last 7 days only</td>
282
+ </tr>
283
+ </tbody>
284
+ </table>
285
+ </div>
286
+ </div>
287
+ ```
288
+
130
289
  ## Composition rules
131
290
 
132
291
  - Use `ui-report` as the page-level wrapper. Add `ui-report--numbered` when
@@ -150,6 +309,16 @@ they are all safe in the static, PDF-first report path.
150
309
  `ui-alert` for persistent notices, `ui-table` for structured evidence,
151
310
  `ui-timeline` for events, `ui-meter` for measured values, and `ui-num` for
152
311
  non-table numeric values.
312
+ - Put a `ui-report__decision` near the start of decision reports, audits, and
313
+ incident reviews. If the report is intentionally exploratory and has no
314
+ decision yet, say so in the summary instead of leaving the reader to infer it.
315
+ - Use severity modifiers on `ui-report__finding` only for scanability. The
316
+ label should still include the severity/status in text, for example
317
+ "Major finding — …" or "Resolved finding — …".
318
+ - In alerts, put the readable message in `<p class="ui-alert__body">…</p>`
319
+ and use `ui-alert__title` only for a separate title line. `ui-alert` is a
320
+ grid with a leading status dot; raw text or loose inline children such as
321
+ `<strong>` / `<code>` become separate grid items and can fragment in print.
153
322
  - Give `ui-report__finding` blocks an accessible name so the visual grouping is
154
323
  also programmatic: point `aria-labelledby` at the block's `ui-eyebrow` label
155
324
  (give it an `id`), or lead with a real heading. Do the same for a
@@ -167,6 +336,10 @@ they are all safe in the static, PDF-first report path.
167
336
  inside `ui-prose`; use `.ui-table` for curated evidence tables. If a
168
337
  `ui-report__evidence` block contains only a `ui-table-wrap`, the report layer
169
338
  removes the inner frame so evidence tables do not look double-boxed.
339
+ Report tables preserve words by default so identifiers and headings do not
340
+ split into unreadable fragments in PDF. Add `ui-table--break-anywhere` only
341
+ for machine-token tables where avoiding horizontal overflow matters more than
342
+ preserving words.
170
343
  - Every `<figure>` should include a `figcaption` using `ui-report__caption`.
171
344
  - Do not use raw color values. Theme with `--accent`; use status tones for
172
345
  status; use chart tokens only in chart figures.
@@ -571,14 +744,100 @@ the target theme, or use the frozen inline `<svg>` route, which has no runtime.
571
744
 
572
745
  ## Common templates
573
746
 
574
- - Executive brief: compact cover, one summary block, KPI `ui-statgrid`, short
575
- findings, and sources.
576
- - Research brief: compact header, decision frame, evidence table, quotes or
577
- prose excerpts, and sources.
578
- - Incident review: compact cover, summary, `ui-timeline`, corrective-action
579
- evidence table, and footnotes.
580
- - Project status: compact header, KPI `ui-statgrid`, chart figure with fallback
581
- data, print-only notes, and unnumbered appendix.
747
+ - Executive brief: compact cover, above-fold reader outcome, KPI
748
+ `ui-statgrid`, short findings, evidence-state disclosure, and sources.
749
+ - Decision report: decision frame, options considered, chosen option, rationale,
750
+ tradeoffs, revisit trigger, next actions, evidence ledger, and sources.
751
+ - Research brief: compact header, scope/method block, claim cards, evidence
752
+ table, quotes or prose excerpts, limitations, and sources.
753
+ - Incident review: compact cover, impact summary, `ui-timeline`, root-cause
754
+ claim, corrective-action register, evidence ledger, and footnotes.
755
+ - Audit: summary, finding cards with severity in text, evidence/caveat rows,
756
+ remediation owner/due dates, accepted risk, and sources.
757
+ - Project status: compact header, KPI `ui-statgrid`, current state, blocked
758
+ decisions, action register, chart figure with fallback data, print-only notes,
759
+ and unnumbered appendix.
760
+
761
+ Minimum blocks by report type:
762
+
763
+ | Type | Required shape |
764
+ | --- | --- |
765
+ | Executive | Summary, above-fold outcome, evidence-state disclosure, source cards. |
766
+ | Decision | Decision frame, options/tradeoffs, claim cards, evidence ledger, next actions, sources. |
767
+ | Research | Scope/method, explicit claims, evidence table, limitations, sources. |
768
+ | Primer | Scope, teaching sequence, key claims, examples, caveats, sources. |
769
+ | Incident | Impact, root-cause claim, timeline, evidence ledger, corrective actions, footnotes. |
770
+ | Audit | Severity-labelled findings, evidence/caveat rows, remediation owners/dates, accepted risk, sources. |
771
+ | Status | Current state, risks/blockers, decision requests, action register, recheck timing, sources. |
772
+
773
+ ## Semantic contract
774
+
775
+ The report layer is not a fact checker, but it should make a report's reasoning
776
+ auditable. A useful report separates:
777
+
778
+ - **Reader outcome** — what the reader should do or believe now.
779
+ - **Claim** — the actual assertion, with scope and evidence state.
780
+ - **Evidence** — observation, metric, log, quote, sample, method, assumption,
781
+ counterevidence, or limitation.
782
+ - **Source** — where the evidence came from, with trust/freshness written in
783
+ text.
784
+ - **Action** — who does what next, by when, and how completion is checked.
785
+
786
+ Use inline citations and stable IDs to connect those layers:
787
+
788
+ ```html
789
+ <article class="ui-claim ui-claim--supported" id="claim-1" data-source-ids="source-metrics">
790
+ <p class="ui-claim__statement">Availability remained above target.</p>
791
+ <p class="ui-claim__status">Evidence state: supported</p>
792
+ <p class="ui-claim__refs">Source: <a class="ui-citation" href="#source-metrics">S1</a></p>
793
+ </article>
794
+
795
+ <article class="ui-source-card ui-src--verified" id="source-metrics">
796
+ <h3 class="ui-source-card__title">Metrics export</h3>
797
+ <p class="ui-source-card__origin">Verified operational export</p>
798
+ </article>
799
+ ```
800
+
801
+ If a claim is generated, inferred, stale, disputed, or uncited, say so near the
802
+ claim, not only in the source appendix. Do not use a numeric confidence widget
803
+ unless the number has a real model, sample, or scoring method behind it.
804
+
805
+ Generator-side tools should keep a machine-readable claim/source sidecar beside
806
+ important reports. The HTML stays the readable artifact; the sidecar lets a
807
+ checker prove that claim IDs, source IDs, trust states, retrieval dates and
808
+ high-risk decisions still line up after editing.
809
+
810
+ ```json
811
+ {
812
+ "schemaVersion": "bronto-report-claims.v1",
813
+ "report": { "title": "Decision readiness", "type": "decision" },
814
+ "claims": [
815
+ {
816
+ "id": "claim-primary",
817
+ "status": "supported",
818
+ "risk": "medium",
819
+ "statement": "The guarded option reduces operational risk.",
820
+ "scope": "Current release window",
821
+ "sourceIds": ["source-primary"]
822
+ }
823
+ ],
824
+ "sources": [
825
+ {
826
+ "id": "source-primary",
827
+ "state": "verified",
828
+ "title": "Release metrics export",
829
+ "origin": "Verified operational export",
830
+ "retrievedAt": "2026-06-08T10:00:00Z",
831
+ "supports": ["claim-primary"]
832
+ }
833
+ ]
834
+ }
835
+ ```
836
+
837
+ For source archives, keep the same source IDs and add any available immutable
838
+ handles: URL, artifact path, content hash, retrieval timestamp, collection
839
+ method and caveats. A report is more useful when the source appendix, inline
840
+ citations, evidence ledger and sidecar all name the same IDs.
582
841
 
583
842
  ## Print and PDF
584
843
 
@@ -586,12 +845,18 @@ The supported export target is modern Chromium print/PDF. A bronto report is
586
845
  static and zero-JS, so producing the PDF is just _load → print_ — you do not
587
846
  need a full automatable browser, only a Chromium-class layout+print pass.
588
847
 
848
+ Chromium's generated PDF is a visual/export artifact, not a tagged accessible
849
+ PDF. Keep the HTML report as the accessible artifact unless the host application
850
+ adds a separate tagged-PDF pipeline and verifies it with PDF accessibility
851
+ tooling.
852
+
589
853
  - **By hand:** open the report in Chrome/Edge → Print (Cmd/Ctrl+P) → "Save as
590
854
  PDF". In **More settings**, enable **Background graphics** (the dialog's
591
855
  equivalent of `printBackground` — without it chart fills and swatches drop
592
- out), and pick the paper size there. Paper size is a browser print setting,
593
- not a token; the layer only themes the page _margin_ via
594
- `--report-page-margin`.
856
+ out), and pick the paper size there. Paper size and page margins are browser
857
+ print settings; the report stylesheet uses a fixed 18mm `@page` margin because
858
+ Chromium-class print engines do not reliably resolve custom properties inside
859
+ `@page` rules.
595
860
  - **Headless, lightweight:** use **`chrome-headless-shell`** — the minimal
596
861
  headless-Chromium binary built for exactly this, a fraction of a full
597
862
  browser's weight. Drive it through Playwright/Puppeteer (or raw CDP) and
@@ -657,8 +922,23 @@ Before returning a report, an LLM should verify:
657
922
  cells and `.ui-stat` deltas, `is-open`/`is-active`) are valid but live
658
923
  outside `cls` by design — keep them.
659
924
  - The document has one `h1`, ordered headings, and a single main report region.
925
+ - The report type is clear: executive, decision, research, incident, audit,
926
+ primer, or status. The above-fold block answers what the reader should do or
927
+ believe now, unless the report explicitly says it is exploratory.
928
+ - Every decision, major finding, quantitative claim, and recommendation has a
929
+ nearby citation, claim block, evidence packet, evidence ledger row, or an
930
+ explicit assumption/uncited/generated label.
931
+ - Claim/source sidecars, when present, resolve every claim ID and source ID back
932
+ to visible HTML. High-risk claims have at least one verified or reviewed
933
+ source.
934
+ - Stale, conflicting, unverified, or generated inputs are surfaced near the
935
+ affected claim or decision, not buried only in the source appendix.
936
+ - Actions that represent real follow-up include owner, due/recheck date, status,
937
+ and success criteria, or explicitly say why those fields are unassigned.
660
938
  - Tables have captions and header cells.
661
939
  - Charts have captions, direct labels or legends, and fallback data.
662
940
  - No raw chromatic colors appear in inline styles.
663
941
  - No remote scripts, styles, iframes, or images are required for the report.
664
942
  - Generated/untrusted body HTML was sanitized before insertion.
943
+ - Alert text is wrapped in `.ui-alert__body`; no loose text or inline-only
944
+ elements are direct children of `.ui-alert`.
package/docs/sources.md CHANGED
@@ -102,6 +102,35 @@ A references section: a reset list of source cards (or rows).
102
102
  </ol>
103
103
  ```
104
104
 
105
+ ## Optional behavior — `initSources`
106
+
107
+ When you want citations to jump back to their source cards with a visible focus
108
+ cue, wrap the report or article in `data-bronto-sources` and initialize the
109
+ behavior:
110
+
111
+ ```html
112
+ <main data-bronto-sources>
113
+ <p>Latency fell 38%<a class="ui-citation" href="#s1" aria-label="Source 1">[1]</a>.</p>
114
+ <article id="s1" class="ui-source-card ui-src--verified">…</article>
115
+ </main>
116
+
117
+ <script type="module">
118
+ import { initSources } from '@ponchia/ui/behaviors';
119
+ const stop = initSources();
120
+ </script>
121
+ ```
122
+
123
+ `initSources()` is progressive enhancement over authored IDs. It resolves
124
+ `.ui-citation[href^="#"]` and `[data-bronto-source-ref]` controls inside each
125
+ `[data-bronto-sources]` island, adds preview metadata (`title` and
126
+ `aria-describedby`) when the author did not already provide it, and activation
127
+ focuses the matching source card with a temporary `.is-source-active` highlight.
128
+ It emits `bronto:source:focus` with `{ id, citation, source }`.
129
+
130
+ The host still owns fetching, numbering, permission checks, trust decisions, and
131
+ any rich preview popover. Generated/static reports can stay behavior-free:
132
+ hash-link navigation and `.ui-source-card:target` still provide a CSS-only cue.
133
+
105
134
  ## Provenance — `.ui-provenance`
106
135
 
107
136
  A compact metadata row beside generated content — each `__item` carries a trust
@@ -130,6 +159,9 @@ ui.provenance({ state: 'reviewed' }); // "ui-provenance ui-src--reviewed"
130
159
 
131
160
  - A citation must be a real link or button with a stable accessible name; the
132
161
  bracketed index alone is not enough.
162
+ - `initSources()` is optional. Initialize it only on trusted markup; the
163
+ delegated `data-bronto-source-ref` / `href="#…"` relationships focus elements
164
+ inside the source island.
133
165
  - The trust state must be readable as text — the tone dot/border is decorative
134
166
  reinforcement. Under `forced-colors`, dots and borders fall back to
135
167
  `CanvasText`, so the label remains the channel.
package/docs/stability.md CHANGED
@@ -1,12 +1,15 @@
1
1
  # Public API Stability
2
2
 
3
3
  `@ponchia/ui` is pre-1.0. Breaking changes ship in the minor (`0.x.0`), and
4
- patches are non-breaking. In practical terms: **PATCH releases (`0.5.x`) are
4
+ patches are non-breaking. In practical terms: **PATCH releases (`0.6.x`) are
5
5
  non-breaking bug-fixes and additive changes — safe to upgrade without review;
6
6
  MINOR releases (`0.x.0`) may include breaking changes and consumers should
7
7
  review the CHANGELOG before upgrading.** Pin `~0.x` (tilde) to accept only
8
8
  patches, or `^0.x` only if you accept minor-level churn. This policy holds
9
9
  until `1.0.0` is tagged. This matrix defines what counts as public API.
10
+ For the exhaustive package-manifest inventory — every `exports` key, every
11
+ shipped `files` entry, and the generated artifact provenance map — see
12
+ [package-contract.md](./package-contract.md).
10
13
 
11
14
  | Surface | Stability | Contract |
12
15
  | --- | --- | --- |
@@ -18,7 +21,7 @@ until `1.0.0` is tagged. This matrix defines what counts as public API.
18
21
  | Design tokens | Stable names/roles | Token names and documented roles are public. Exact values and generated colour math outputs may change for visual tuning before 1.0. |
19
22
  | `--accent-1..6` | Stable names/roles | A subtle-to-bold accent ramp derived from `--accent`. Exact resolved values are visual tuning; algorithm changes require release-note visibility and resolver/browser checks. |
20
23
  | Tokens as data (`tokens.json`, `tokens.dtcg.json`, `tokens/resolved.json`) | Stable additive | The JSON shapes are public for non-CSS/non-JS consumers. `resolved.json` exposes `light`/`dark` (resolved colours) and `scale` (resolved non-colour scales). Token names/roles are stable; exact resolved values are visual tuning (pin `~0.x`). |
21
- | Theme axes | Mixed | `data-theme` (light/dark) is the **contractual** base. `data-surface="oled"`, `data-density`, and `data-contrast` are **convenience presets** — best-effort visual variants, **not** part of the stability contract; their presence and exact values may change for tuning. (A computed-style smoke test guards the OLED `--bg` flip; the others are unverified.) |
24
+ | Theme axes | Mixed | `data-theme` (light/dark) is the **contractual** base. `data-surface="oled"`, `data-density`, and `data-contrast` are **convenience presets** — best-effort visual variants, **not** part of the stability contract; their presence and exact values may change for tuning. Computed-style smoke tests guard that the presets apply to their intended token families. |
22
25
  | Behavior attributes (`data-bronto-*`) | Stable | Attribute names and documented markup relationships are public. Behavior internals are not. |
23
26
  | Behavior functions (`@ponchia/ui/behaviors`) | Stable | Exported function names, option names, custom events, SSR no-op behavior, idempotency, and cleanup-returning contract are public. |
24
27
  | Glyph registry/renderers (`@ponchia/ui/glyphs`) | Stable additive | Existing glyph names stay valid. New glyphs are additive. Renderer option names and accessibility defaults are public. |
@@ -35,7 +38,7 @@ until `1.0.0` is tagged. This matrix defines what counts as public API.
35
38
  | Crosshair (`css/crosshair.css`, `.ui-crosshair*`, `.ui-readout`, `initCrosshair`) | Stable additive | Crosshair/readout class names, the `--crosshair-x/y` properties, the `data-bronto-crosshair` attribute, and the `bronto:crosshair:move`/`:leave` event contract are public. Opt-in. Reports pointer position only — no data mapping. |
36
39
  | Selection states (`css/selection.css`, `.ui-sel*`) | Stable additive | The `.ui-sel`/`--on`/`--off`/`--maybe` emphasis classes and recipe options are public. Opt-in, cross-cutting. The host owns selection logic; Bronto only styles the states. |
37
40
  | Analytical roll-up (`css/analytical.css`) | Stable additive | A convenience `@import` of the seven analytical leaves (annotations, legend, marks, connectors, spotlight, crosshair, selection). The set of leaves it bundles may grow additively; each leaf also stays individually exported. Opt-in, not in the default bundle. |
38
- | Sources / provenance (`css/sources.css`, `.ui-citation*`, `.ui-source-card*`, `.ui-source-list*`, `.ui-provenance*`, `.ui-src--*`) | Stable additive | Citation/source/provenance class names, the cross-cutting `.ui-src--*` trust-state modifiers (always paired with an author label), and the `ui.citation`/`ui.source`/`ui.provenance` recipes + `cls.sourceList` are public. Opt-in, not in the default bundle. |
41
+ | Sources / provenance (`css/sources.css`, `.ui-citation*`, `.ui-source-card*`, `.ui-source-list*`, `.ui-provenance*`, `.ui-src--*`, `initSources`) | Stable additive | Citation/source/provenance class names, the cross-cutting `.ui-src--*` trust-state modifiers (always paired with an author label), the optional `data-bronto-sources` / `data-bronto-source-ref` behavior contract, `bronto:source:focus`, and the `ui.citation`/`ui.source`/`ui.provenance` recipes + `cls.sourceList` are public. Opt-in, not in the default bundle. |
39
42
  | Lifecycle state (`css/state.css`, `.ui-state*`, `.ui-syncbar`) | Stable additive | The `.ui-state`/`__label`/`__detail`/`--busy` classes, the canonical lifecycle state modifiers, `.ui-syncbar`, and the `ui.state` recipe are public. Opt-in, not in the default bundle. |
40
43
  | Generated / AI-trust (`css/generated.css`, `.ui-generated*`, `.ui-origin-label*`, `.ui-reasoning*`, `.ui-tool-log`, `.ui-tool-call*`) | Stable additive | The generated-content, origin-label (incl. `--ai`), reasoning-trace and tool-log/tool-call class names and the `ui.originLabel` recipe are public. Opt-in, not in the default bundle. Not a chat kit; no confidence widget. |
41
44
  | Workbench (`css/workbench.css`, `.ui-inspector*`, `.ui-property*`, `.ui-selectionbar*`) | Stable additive | Inspector, property-row and selection-bar class + BEM part names are public (class-only — no recipe). Opt-in, not in the default bundle. Splitters/drag handles are out of scope. |
@@ -8,7 +8,9 @@ export type GlyphName =
8
8
  | 'arrow-left'
9
9
  | 'arrow-right'
10
10
  | 'arrow-up'
11
+ | 'bar-chart'
11
12
  | 'bell'
13
+ | 'calendar'
12
14
  | 'check'
13
15
  | 'check-circle'
14
16
  | 'chevron-down'
@@ -18,14 +20,30 @@ export type GlyphName =
18
20
  | 'circle'
19
21
  | 'clock'
20
22
  | 'close'
23
+ | 'colon'
24
+ | 'comma'
25
+ | 'copy'
26
+ | 'database'
27
+ | 'digit-0'
28
+ | 'digit-1'
29
+ | 'digit-2'
30
+ | 'digit-3'
31
+ | 'digit-4'
32
+ | 'digit-5'
33
+ | 'digit-6'
34
+ | 'digit-7'
35
+ | 'digit-8'
36
+ | 'digit-9'
21
37
  | 'download'
22
38
  | 'edit'
23
39
  | 'eye'
24
40
  | 'eye-off'
25
41
  | 'file'
42
+ | 'filter'
26
43
  | 'folder'
27
44
  | 'gear'
28
45
  | 'grid'
46
+ | 'hash'
29
47
  | 'heart'
30
48
  | 'home'
31
49
  | 'info'
@@ -39,11 +57,16 @@ export type GlyphName =
39
57
  | 'more-horizontal'
40
58
  | 'more-vertical'
41
59
  | 'pause'
60
+ | 'percent'
61
+ | 'period'
42
62
  | 'play'
43
63
  | 'plus'
44
64
  | 'plus-circle'
45
65
  | 'refresh'
46
66
  | 'search'
67
+ | 'share'
68
+ | 'sliders'
69
+ | 'sort'
47
70
  | 'spark'
48
71
  | 'star'
49
72
  | 'sun'
@@ -111,5 +134,43 @@ export declare function glyph(name: GlyphNameInput): Glyph | undefined;
111
134
  /** 256 cell descriptors (row-major), or `[]` if unknown. */
112
135
  export declare function glyphCells(name: GlyphNameInput): GlyphCell[];
113
136
 
137
+ /** The CSS `mask-image` `url()` for a glyph (the `--icon-mask` value on a
138
+ * `.ui-icon`), or `''` if unknown. Single-tone. */
139
+ export declare function glyphMask(name: GlyphNameInput): string;
140
+
114
141
  /** A full `.ui-dotmatrix` HTML string for a glyph (`''` if unknown). */
115
142
  export declare function renderGlyph(name: GlyphNameInput, options?: RenderGlyphOptions): string;
143
+
144
+ /** Hand-curated intent→glyph search aliases (e.g. `trash`→`delete`/`remove`).
145
+ * Keys are real glyph names; values are extra search terms. */
146
+ export declare const GLYPH_TAGS: Readonly<Partial<Record<GlyphName, readonly string[]>>>;
147
+
148
+ /** Glyph names whose name OR a search alias contains `query` (case-insensitive),
149
+ * sorted. `findGlyphs('')` returns every name. */
150
+ export declare function findGlyphs(query: string): GlyphName[];
151
+
152
+ /** Options for renderReadout. The per-glyph fields pass through to renderGlyph
153
+ * for each character; `gap` sets `--readout-gap` on the row. */
154
+ export interface RenderReadoutOptions {
155
+ /** Accessible name for the whole readout (defaults to the raw text). The dot
156
+ * digits are decorative; this carries the real value. */
157
+ label?: string;
158
+ /** CSS length between characters (sets `--readout-gap`; sanitized). */
159
+ gap?: string;
160
+ /** Render each character as square gapless pixels (legible small). */
161
+ solid?: boolean;
162
+ /** Show the unlit panel dots behind each character (default true). */
163
+ grid?: boolean;
164
+ /** Decorative per-character animation (reduced-motion-safe). */
165
+ anim?: 'reveal' | 'pulse';
166
+ /** CSS length for one dot of each character (sets `--dotmatrix-dot`). */
167
+ dot?: string;
168
+ /** `'mask'` renders each character as a single `.ui-icon` node (lightest). */
169
+ render?: 'mask';
170
+ /** With `render: 'mask'`, the per-character icon size. */
171
+ size?: string;
172
+ }
173
+
174
+ /** A row of dot-matrix glyphs for a numeric string (digits + `: , . % - +` and
175
+ * space) — the big Nothing-style readout. `''` for empty input. */
176
+ export declare function renderReadout(text: string, options?: RenderReadoutOptions): string;