@ponchia/ui 0.6.6 → 0.6.8

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 (160) hide show
  1. package/CHANGELOG.md +175 -6
  2. package/README.md +38 -25
  3. package/annotations/index.d.ts.map +1 -1
  4. package/annotations/index.js +21 -3
  5. package/behaviors/carousel.d.ts.map +1 -1
  6. package/behaviors/carousel.js +91 -32
  7. package/behaviors/combobox.d.ts.map +1 -1
  8. package/behaviors/combobox.js +117 -43
  9. package/behaviors/command.d.ts.map +1 -1
  10. package/behaviors/command.js +74 -14
  11. package/behaviors/connectors.d.ts.map +1 -1
  12. package/behaviors/connectors.js +92 -9
  13. package/behaviors/crosshair.d.ts.map +1 -1
  14. package/behaviors/crosshair.js +47 -1
  15. package/behaviors/dialog.d.ts.map +1 -1
  16. package/behaviors/dialog.js +37 -16
  17. package/behaviors/disclosure.d.ts.map +1 -1
  18. package/behaviors/disclosure.js +33 -3
  19. package/behaviors/dismissible.d.ts.map +1 -1
  20. package/behaviors/dismissible.js +3 -2
  21. package/behaviors/forms.d.ts.map +1 -1
  22. package/behaviors/forms.js +78 -5
  23. package/behaviors/glyph.d.ts.map +1 -1
  24. package/behaviors/glyph.js +17 -2
  25. package/behaviors/index.d.ts +2 -0
  26. package/behaviors/index.d.ts.map +1 -1
  27. package/behaviors/index.js +2 -0
  28. package/behaviors/inert.js +3 -2
  29. package/behaviors/internal.d.ts +2 -1
  30. package/behaviors/internal.d.ts.map +1 -1
  31. package/behaviors/internal.js +25 -4
  32. package/behaviors/legend.d.ts +0 -5
  33. package/behaviors/legend.d.ts.map +1 -1
  34. package/behaviors/legend.js +78 -14
  35. package/behaviors/menu.d.ts.map +1 -1
  36. package/behaviors/menu.js +13 -8
  37. package/behaviors/modal.d.ts.map +1 -1
  38. package/behaviors/modal.js +77 -19
  39. package/behaviors/popover.d.ts +4 -3
  40. package/behaviors/popover.d.ts.map +1 -1
  41. package/behaviors/popover.js +89 -9
  42. package/behaviors/sources.d.ts.map +1 -1
  43. package/behaviors/sources.js +14 -2
  44. package/behaviors/splitter.d.ts +26 -0
  45. package/behaviors/splitter.d.ts.map +1 -0
  46. package/behaviors/splitter.js +239 -0
  47. package/behaviors/spotlight.d.ts.map +1 -1
  48. package/behaviors/spotlight.js +28 -2
  49. package/behaviors/table.d.ts.map +1 -1
  50. package/behaviors/table.js +105 -13
  51. package/behaviors/tabs.d.ts.map +1 -1
  52. package/behaviors/tabs.js +82 -18
  53. package/behaviors/theme.d.ts.map +1 -1
  54. package/behaviors/theme.js +26 -6
  55. package/classes/classes.json +230 -4
  56. package/classes/index.d.ts +64 -3
  57. package/classes/index.js +56 -2
  58. package/classes/vscode.css-custom-data.json +1 -1
  59. package/connectors/index.d.ts +39 -6
  60. package/connectors/index.d.ts.map +1 -1
  61. package/connectors/index.js +67 -9
  62. package/css/analytical.css +3 -1
  63. package/css/annotations.css +12 -0
  64. package/css/app.css +4 -4
  65. package/css/clamp.css +92 -0
  66. package/css/crosshair.css +27 -2
  67. package/css/feedback.css +2 -30
  68. package/css/figure.css +102 -0
  69. package/css/highlights.css +50 -0
  70. package/css/interval.css +90 -0
  71. package/css/navigation.css +12 -0
  72. package/css/primitives.css +2 -3
  73. package/css/report-kit.css +38 -0
  74. package/css/report.css +23 -4
  75. package/css/sidenote.css +12 -2
  76. package/css/site.css +2 -1
  77. package/css/sources.css +5 -0
  78. package/css/state.css +120 -1
  79. package/css/table.css +4 -0
  80. package/css/tokens.css +25 -9
  81. package/css/workbench.css +101 -8
  82. package/dist/bronto.css +1 -1
  83. package/dist/css/analytical.css +1 -1
  84. package/dist/css/annotations.css +1 -1
  85. package/dist/css/app.css +1 -1
  86. package/dist/css/clamp.css +1 -0
  87. package/dist/css/crosshair.css +1 -1
  88. package/dist/css/feedback.css +1 -1
  89. package/dist/css/figure.css +1 -0
  90. package/dist/css/highlights.css +1 -0
  91. package/dist/css/interval.css +1 -0
  92. package/dist/css/navigation.css +1 -1
  93. package/dist/css/primitives.css +1 -1
  94. package/dist/css/report-kit.css +1 -0
  95. package/dist/css/report.css +1 -1
  96. package/dist/css/sidenote.css +1 -1
  97. package/dist/css/site.css +1 -1
  98. package/dist/css/sources.css +1 -1
  99. package/dist/css/state.css +1 -1
  100. package/dist/css/table.css +1 -1
  101. package/dist/css/tokens.css +1 -1
  102. package/dist/css/workbench.css +1 -1
  103. package/docs/adr/0001-color-system.md +3 -2
  104. package/docs/adr/0002-scope-and-2026-baseline.md +1 -1
  105. package/docs/annotations.md +12 -1
  106. package/docs/architecture.md +105 -48
  107. package/docs/clamp.md +49 -0
  108. package/docs/command.md +4 -1
  109. package/docs/connectors.md +16 -0
  110. package/docs/contrast.md +34 -24
  111. package/docs/crosshair.md +1 -1
  112. package/docs/d2.md +37 -0
  113. package/docs/dots.md +4 -1
  114. package/docs/figure.md +71 -0
  115. package/docs/frontier-primitives.md +25 -24
  116. package/docs/glyphs.md +11 -0
  117. package/docs/highlights.md +52 -0
  118. package/docs/interop/tailwind.md +148 -0
  119. package/docs/interval.md +55 -0
  120. package/docs/legends.md +3 -2
  121. package/docs/mermaid.md +6 -0
  122. package/docs/migrations/0.2-to-0.3.md +80 -0
  123. package/docs/migrations/0.3-to-0.4.md +48 -0
  124. package/docs/migrations/0.4-to-0.5.md +96 -0
  125. package/docs/migrations/0.5-to-0.6.md +82 -0
  126. package/docs/package-contract.md +44 -6
  127. package/docs/reference.md +78 -5
  128. package/docs/reporting.md +126 -60
  129. package/docs/sidenote.md +7 -1
  130. package/docs/sources.md +1 -1
  131. package/docs/stability.md +23 -5
  132. package/docs/state.md +67 -10
  133. package/docs/theming.md +12 -4
  134. package/docs/usage.md +47 -13
  135. package/docs/vega.md +4 -4
  136. package/docs/workbench.md +59 -18
  137. package/llms.txt +89 -16
  138. package/package.json +82 -6
  139. package/qwik/index.d.ts +1 -0
  140. package/qwik/index.d.ts.map +1 -1
  141. package/qwik/index.js +26 -21
  142. package/react/index.d.ts +1 -0
  143. package/react/index.d.ts.map +1 -1
  144. package/react/index.js +4 -1
  145. package/schemas/report-claims.v1.schema.json +137 -0
  146. package/solid/index.d.ts +2 -0
  147. package/solid/index.d.ts.map +1 -1
  148. package/solid/index.js +3 -0
  149. package/svelte/index.d.ts +114 -0
  150. package/svelte/index.d.ts.map +1 -0
  151. package/svelte/index.js +193 -0
  152. package/tailwind.css +87 -0
  153. package/tokens/figma.variables.json +2241 -0
  154. package/tokens/index.js +1 -1
  155. package/tokens/index.json +2 -2
  156. package/tokens/resolved.json +3 -3
  157. package/tokens/tokens.dtcg.json +1 -1
  158. package/vue/index.d.ts +116 -0
  159. package/vue/index.d.ts.map +1 -0
  160. package/vue/index.js +228 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,175 @@
5
5
  |> `^0` / `*` wildcard does **not** protect you. See README → Versioning, and
6
6
  |> the deprecation policy in CONTRIBUTING.md.
7
7
 
8
+ ## 0.6.8 — 2026-06-16
9
+
10
+ Patch release for the deep UI-framework audit: broader browser/package gates,
11
+ clean-consumer verification, and runtime fixes found while hardening the public
12
+ surface. No breaking changes, no `MIGRATIONS.json` entry.
13
+
14
+ ### Added
15
+
16
+ - **Tarball and clean-consumer gates.** `check:consumer-surface` now imports
17
+ public JS/JSON subpaths from the packed package, resolves concrete CSS/doc/
18
+ font subpaths without optional peers, and verifies behavior initializers stay
19
+ SSR-safe. `check:consumer-types` installs the tarball into a clean TypeScript
20
+ consumer and compiles every typed `@ponchia/ui/...` package subpath.
21
+ - **Matrix ownership gates.** `check:component-matrix`,
22
+ `check:behavior-matrix`, `check:helper-matrix`, and `check:binding-matrix`
23
+ now require shipped CSS leaves, public behavior exports, helper modules, and
24
+ framework bindings to have explicit docs, type, unit, or browser ownership.
25
+ - **Public docs and package hygiene gates.** `check:doc-links` validates local
26
+ links and heading anchors across shipped docs, authoring docs, and the docs
27
+ viewer route list. `check:schemas`, `check:visual-baselines`,
28
+ `check:playwright-container`, and stronger `check:contract` / `check:report`
29
+ coverage close stale public snippets, missing visual baselines, and invalid
30
+ report/schema surfaces.
31
+ - **Broader browser coverage.** The Playwright suite now pins docs viewer deep
32
+ links, cascade-layer behavior, source focusing, renderer geometry, behavior
33
+ cleanup/idempotency, connector transforms, annotation motion/overflow,
34
+ command interactions, crosshair payloads, responsive overflow, and more
35
+ forced-colors/reduced-motion contracts.
36
+ - **Packed example smoke coverage.** The example runner now builds and smokes
37
+ the packed examples from one registry, with richer runtime assertions,
38
+ desktop/mobile visual health, and optional Chromium/Firefox/WebKit coverage.
39
+ Astro joins the packed-tarball smoke matrix.
40
+ - **Renderer theme helper coverage.** Chart, Mermaid, D2, and Vega package
41
+ helpers now have type/runtime coverage that checks default exports,
42
+ theme-selection fallbacks, resolved colors, and `var()` leak prevention.
43
+
44
+ ### Fixed
45
+
46
+ - **Standalone dot readouts survive `report-kit.css`.** `crosshair.css` now
47
+ scopes pinned readout-chip styling to `.ui-crosshair .ui-readout`, so the
48
+ core dot-matrix `.ui-readout` keeps its normal inline layout when a report
49
+ imports the full report kit.
50
+ - **Rendered docs deep links work.** `docs/index.html` now preserves
51
+ `doc.md#section` routes, generates deterministic heading IDs, keeps
52
+ same-page anchors inside the current doc route, and drops the invalid
53
+ meta-CSP `frame-ancestors` directive that browsers reported as a console
54
+ error.
55
+ - **Command adapter docs match the shipped matrix.** `docs/command.md`, the
56
+ stability matrix, package-contract provenance, and `llms.txt` now name the
57
+ Svelte action and Vue directive/plugin paths alongside the React/Solid/Qwik
58
+ bindings.
59
+ - **CodeQL review findings.** Docs slug helpers no longer use incomplete
60
+ regex-based tag stripping, and wildcard package-subpath expansion replaces
61
+ every placeholder rather than only the first one.
62
+
63
+ ### Changed
64
+
65
+ - `npm run check` now owns the unit suite through `check:unit`; CI, release
66
+ workflow validation, PR templates, release docs, and package-contract docs
67
+ all describe the same aggregate gate instead of duplicating `npm test`.
68
+ - Release hygiene now verifies the aggregate check includes unit coverage and
69
+ prevents duplicate release-workflow unit runs from drifting out of sync.
70
+ - `check:exports` now pins package-level CSS metadata: the top-level `style`
71
+ field, root export targets, `files`, and CSS-preserving `sideEffects`.
72
+ - Type-only coverage now instantiates Svelte action and Vue directive
73
+ declarations from consumer-shaped code, including invalid root-shape
74
+ assertions.
75
+ - The default bundle budget is recalibrated to 91 kB raw / 15.65 kB gzip after
76
+ the audited bundle landed below that ceiling at 87.9 kB raw / 15.0 kB gzip.
77
+
78
+ ## 0.6.7 — 2026-06-15
79
+
80
+ ### Added
81
+
82
+ - **Tailwind v4 bridge.** `@ponchia/ui/tailwind` / `@ponchia/ui/tailwind.css`
83
+ ships a CSS-first `@theme inline` bridge, `bronto-dark` and `bronto-oled`
84
+ custom variants, and source-registration guidance for Tailwind v4 projects.
85
+ `docs/interop/tailwind.md` documents `@reference` / `@source`, and
86
+ `examples/tailwind-vite` builds from the packed tarball and browser-smokes
87
+ the emitted Bronto utilities.
88
+ - **Svelte and Vue lifecycle adapters.** `@ponchia/ui/svelte` exports
89
+ dependency-free actions over the delegated behavior layer, and
90
+ `@ponchia/ui/vue` exports directives, plugin helpers, and the shared
91
+ imperative `useToast()` helper.
92
+ The SvelteKit example now uses the Svelte adapter, and `examples/vue-vite`
93
+ covers Vue consumer install/build/runtime smoke from the packed package.
94
+ - **Figma Variables handoff artifact.** `tokens/figma.variables.json` is
95
+ generated from the token source, exported as
96
+ `@ponchia/ui/tokens/figma.variables.json`, drift-checked in `check:fresh`,
97
+ and documented as a local import/sync handoff alongside the DTCG token export.
98
+ - **Report-primitive batch** — four additive opt-in leaves for static reports
99
+ and explanation surfaces: `ui-figure` (`css/figure.css`) for reusable
100
+ chart/diagram/media stages with overlay, key and fallback-data slots;
101
+ `ui-interval` (`css/interval.css`) for host-normalised low/high evidence
102
+ windows; `ui-clamp` (`css/clamp.css`) for bounded excerpts with CSS-only
103
+ show-more / show-less; and `ui-highlights` (`css/highlights.css`) for named
104
+ CSS Custom Highlight API paints (`bronto-evidence`, `bronto-search`,
105
+ `bronto-current`). All stay out of `dist/bronto.css`; `figure.css` and
106
+ `highlights.css` join the analytical roll-up.
107
+ - **Background-job state primitive.** `state.css` now includes `ui-job` for
108
+ persistent asynchronous work: written status, determinate progress via
109
+ `--job-progress`, optional actions, compact mode, and queued/running/blocked/
110
+ failed/complete tones. The host still owns polling, retries, cancellation,
111
+ and announcements.
112
+ - **Workbench splitter primitive.** `workbench.css` now includes
113
+ `ui-splitter` / `__pane` / `__handle` plus the optional `initSplitter`
114
+ behavior (`data-bronto-splitter`) for focusable ARIA separator handles,
115
+ keyboard and pointer resizing, `--splitter-pos` / `aria-valuenow` sync, and a
116
+ `bronto:splitter:resize` event. React, Solid, Qwik, Svelte, and Vue adapters
117
+ expose the matching hook/action/directive.
118
+ - **Service identity demo and report kit.** The public demo set now includes
119
+ `demo/service.html`, a cross-service `ui-app-shell` specimen that keeps the
120
+ default bundle centered on shared app identity. Static reports get the new
121
+ opt-in `@ponchia/ui/css/report-kit.css` roll-up for the complete report
122
+ vocabulary, plus `@ponchia/ui/schemas/report-claims.v1.schema.json` for
123
+ claim/source sidecar validation.
124
+ - **Public-package hardening gates.** `check:public-hygiene`,
125
+ `check:variables`, and `check:migrations` are now part of the aggregate
126
+ `npm run check` chain, covering packed public text leaks, undefined CSS
127
+ custom-property references, and migration-map/doc alignment.
128
+
129
+ ### Fixed
130
+
131
+ - **Silent CSS token typos.** `css/workbench.css` now uses the real
132
+ `--focus-ring` token for splitter focus outlines, and `css/report.css` uses
133
+ `--text-base` for finding/evidence value text. The new variable-reference
134
+ gate prevents the same class of no-op declaration from shipping again.
135
+ - **Print: stat tiles and table rows no longer slice across PDF page
136
+ boundaries** — the report-layer `@media print` break-inside guard covered
137
+ the report shell (`.ui-report__*`, `.ui-claim`, `.ui-evidence-item`) but
138
+ not `.ui-stat` tiles, generic `.ui-statgrid` children, or `tr`, so a stat
139
+ card landing on a page boundary printed half its value on one page and the
140
+ delta on the next (observed in a consumer report's PDF export). Guarded at
141
+ the item level — the tile / the row, not the container — so a long
142
+ statgrid or table can still span pages.
143
+
144
+ - **Sidenote gutter contract actually works now** — `--sidenote-width` /
145
+ `--sidenote-gap` are root-scoped instead of declared only on the notes.
146
+ The documented host wiring (container
147
+ `padding-inline-end: calc(var(--sidenote-width) + var(--sidenote-gap))`)
148
+ referenced vars an ancestor could never see, so the calc was invalid and
149
+ silently reserved NO gutter — the floated notes spilled past the page edge
150
+ (caught by a real report's visual QA). The demo now uses the documented
151
+ calc verbatim (it previously masked the bug with a hardcoded literal), and
152
+ a wide-viewport e2e asserts the contract: gutter resolves, float stays
153
+ on-page, no horizontal scroll. Overriding either knob on the container now
154
+ re-sizes the notes and the gutter together.
155
+
156
+ ### Changed
157
+
158
+ - `docs/d2.md` tokenize recipe covers the full embedded-style surface
159
+ (`.color-*` / `.background-color-*` rules, not just `fill`/`stroke`) and
160
+ warns that `tooltip:`/`|md` shapes embed GitHub-Primer styling that
161
+ survives tokenization. `docs/sidenote.md` documents the root-scoped knobs.
162
+ - Local verification is now reproducible through named scripts:
163
+ `npm run test:e2e:nonpixel` runs every non-screenshot Playwright spec across
164
+ Chromium, Firefox, and WebKit, while `npm run test:examples` packs the real
165
+ tarball, builds all examples in temp directories, and browser-smokes the
166
+ runtime examples. `CONTRIBUTING.md`, `docs/release.md`, and
167
+ `docs/architecture.md` describe when to use those local gates versus the
168
+ pinned-container screenshot gate.
169
+ - `check:examples` keeps the example inventory, CI matrix, browser-smoke list,
170
+ README rows, and preview ports aligned from one registry; `check:dead` now
171
+ runs in the aggregate `npm run check` chain.
172
+ - README, package metadata, usage docs, workbench examples, and the docs index
173
+ now frame `@ponchia/ui` as the shared UI identity layer for services, tools,
174
+ sites, and reports, with reports as an opt-in consumer rather than the center
175
+ of the package.
176
+
8
177
  ## 0.6.6 — 2026-06-10
9
178
 
10
179
  Consolidation pass from the 2026-06-10 multi-agent audit: two real PDF-export
@@ -68,13 +237,13 @@ changes, no `MIGRATIONS.json` entry.
68
237
  post-0.6.0 leaves. The broadened scan immediately caught the demo/reference
69
238
  class defects above. `core.css` imports are now closed over an explicit
70
239
  CORE_BUNDLE allowlist in both directions.
71
- - `ROADMAP.md` / `docs/frontier-primitives.md` reconciled to 0.6.5: the
240
+ - `ROADMAP.md` / `docs/frontier-primitives.md` reconciled to 0.6.7: the
72
241
  report/provenance/explanation lane is named the proven core; ui-job,
73
- ui-conflict, ui-splitter, the tree roving-focus kernel, and
74
- command/workbench follow-ons are explicitly dormant until a real app
75
- consumer exists; the 2026-06-09 scout keeps (ui-interval, ui-clamp,
76
- ui-highlights) are recorded as report-lane candidates gated behind the
77
- routing hub. The adoption stance is stated in ROADMAP.
242
+ ui-conflict, drag/drop workbench follow-ons, the tree roving-focus kernel,
243
+ and command follow-ons are explicitly dormant until a real app consumer
244
+ exists; the 2026-06-09 scout keeps (ui-interval, ui-clamp, ui-highlights) are
245
+ recorded as report-lane candidates gated behind the routing hub. The adoption
246
+ stance is stated in ROADMAP.
78
247
 
79
248
  ## 0.6.5 — 2026-06-09
80
249
 
package/README.md CHANGED
@@ -3,30 +3,32 @@
3
3
  [![npm](https://img.shields.io/npm/v/@ponchia/ui?logo=npm)](https://www.npmjs.com/package/@ponchia/ui)
4
4
  [![npm provenance](https://img.shields.io/badge/npm-provenance-blue?logo=npm)](https://www.npmjs.com/package/@ponchia/ui#provenance)
5
5
  [![runtime deps](https://img.shields.io/badge/runtime%20deps-0-brightgreen)](https://github.com/Ponchia/bronto-ui/blob/main/package.json)
6
- [![dist](https://img.shields.io/badge/dist-~87kB%20%2F%20~15kB%20gzip-informational)](https://github.com/Ponchia/bronto-ui/blob/main/scripts/check-dist.mjs)
6
+ [![dist](https://img.shields.io/badge/dist-~88kB%20%2F%20~15kB%20gzip-informational)](https://github.com/Ponchia/bronto-ui/blob/main/scripts/check-dist.mjs)
7
7
  [![CI](https://github.com/Ponchia/bronto-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/Ponchia/bronto-ui/actions/workflows/ci.yml)
8
8
  [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Ponchia/bronto-ui/badge)](https://scorecard.dev/viewer/?uri=github.com/Ponchia/bronto-ui)
9
9
  [![license: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/Ponchia/bronto-ui/blob/main/LICENSE)
10
10
 
11
- **A CSS-first design system for interfaces that explain themselves.** It works in
12
- plain HTML, every modern framework, and print/PDF, with no component runtime to
13
- adopt and zero runtime dependencies.
11
+ **A CSS-first identity and UI layer for services, tools, sites, and reports.** It
12
+ works in plain HTML, every modern framework, and print/PDF, with no component
13
+ runtime to adopt and zero runtime dependencies.
14
14
 
15
15
  The look is a deliberate stance: a neutral monochrome canvas with one rationed
16
16
  accent (colour signals, it never decorates), dot-matrix display type, and
17
17
  hairline borders — all re-skinnable from a single `--accent` knob (opt-in
18
18
  amber-CRT, phosphor-green, and e-ink colorways).
19
19
 
20
- Beyond the standard component set it ships an opt-in analytical & report layer —
21
- SVG annotations, legends, leader-line connectors, a guided-focus spotlight, text
22
- marks, a colourblind-safe data-viz palette, and a static/PDF report grammar for
23
- dashboards and LLM-authored reports.
20
+ The default bundle is the shared service identity: app shells, navigation,
21
+ forms, tables, feedback, overlays, workflow surfaces, prose, motion and the
22
+ token system that lets each app feel related without sharing a component
23
+ runtime. On top of that it ships opt-in tooling/report layers — workbench panes,
24
+ commands, system state, provenance, figure stages, annotations, legends,
25
+ evidence highlights, intervals, data-viz tokens and a static/PDF report grammar.
24
26
 
25
- ### [Live demo →](https://ponchia.github.io/bronto-ui/)  ·  [Static report →](https://ponchia.github.io/bronto-ui/demo/report-standalone.html)  ·  [Theme playground →](https://ponchia.github.io/bronto-ui/demo/theme-playground.html)
27
+ ### [Live demo →](https://ponchia.github.io/bronto-ui/)  ·  [Service shell →](https://ponchia.github.io/bronto-ui/demo/service.html)  ·  [Static report →](https://ponchia.github.io/bronto-ui/demo/report-standalone.html)  ·  [Theme playground →](https://ponchia.github.io/bronto-ui/demo/theme-playground.html)
26
28
 
27
29
  The demo is the kitchen sink — every component, light/dark, RTL, live theming.
28
- The static report is the differentiator in one file: a complete, no-build,
29
- no-JS, Chromium-PDF-ready report built from the report grammar.
30
+ The service shell shows the shared app identity; the static report shows the
31
+ same system under a no-build, no-JS, Chromium-PDF-ready constraint.
30
32
 
31
33
  <p>
32
34
  <img alt="A research report built with the @ponchia/ui report layer" src="https://raw.githubusercontent.com/Ponchia/bronto-ui/main/demo/_preview-report-research.png" width="49%" />
@@ -48,7 +50,13 @@ and the accent is a spotlight, not a paint bucket. Because everything lives in a
48
50
  single `@layer bronto`, your own un-layered CSS overrides the framework with no
49
51
  specificity fight and no `!important`.
50
52
 
51
- It ships a complete, accessible **standard component set**, but that's not where it competes — its differentiator is the opt-in **analytical & communication layer** sketched above. The line that holds it together: each primitive owns only its visual grammar and pure geometry — no chart engine, no state, no hit-testing. See **[docs/frontier-primitives.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/frontier-primitives.md)** for the thesis.
53
+ It ships a complete, accessible **standard component set** because that is the
54
+ identity layer every service consumes. Its sharper edge is the opt-in **tooling,
55
+ analytical, and communication layer** sketched above. The line that holds it
56
+ together: each primitive owns only its visual grammar and pure geometry — no
57
+ chart engine, no domain state, no hit-testing. See
58
+ **[docs/frontier-primitives.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/frontier-primitives.md)**
59
+ for the thesis.
52
60
 
53
61
  ## Install
54
62
 
@@ -59,12 +67,12 @@ npm i @ponchia/ui
59
67
  Or drop it in with no build step, straight from a CDN:
60
68
 
61
69
  ```html
62
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui/dist/bronto.css">
70
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.8/dist/bronto.css">
63
71
  ```
64
72
 
65
73
  ## Quick start
66
74
 
67
- **1. Load the CSS.** One flattened, minified bundle — the whole standard component set, one request (~87 kB raw / ~15 kB gzip):
75
+ **1. Load the CSS.** One flattened, minified bundle — the whole standard component set, one request (~88 kB raw / ~15 kB gzip):
68
76
 
69
77
  ```css
70
78
  @import '@ponchia/ui'; /* via a bundler */
@@ -77,7 +85,7 @@ Or drop it in with no build step, straight from a CDN:
77
85
 
78
86
  > Prefer source leaves through a bundler? Use `@import '@ponchia/ui/css'` (a thin `@import` fan-out) instead. Both resolve the Doto `@font-face` with relative URLs, so there's no `/fonts` path assumption.
79
87
 
80
- > The bundle is the standard component set. The opt-in analytical & report layers — `report.css`, `dataviz.css`, `annotations.css`, `legend.css`, and the rest — are **not** in `bronto.css`; link each one you need from `dist/css/`. For LLM-authored static reports see [docs/reporting.md](docs/reporting.md).
88
+ > The bundle is the standard component set. The opt-in analytical & report layers — `report.css`, `dataviz.css`, `figure.css`, `annotations.css`, `legend.css`, `interval.css`, `clamp.css`, `highlights.css`, and the rest — are **not** in `bronto.css`; link each one you need from `dist/css/`. For LLM-authored static reports see [docs/reporting.md](docs/reporting.md).
81
89
 
82
90
  **2. Write markup with `ui-*` classes** (primary is the default button; modifiers are opt-in):
83
91
 
@@ -130,10 +138,10 @@ Arrows, chevrons, check/close/plus/minus, search/menu/gear, info/warning/bell/lo
130
138
  - **Feedback** — alert/callout, toast, tooltip, `ui-progress` (task) and `ui-meter` (measured value).
131
139
  - **Overlay** — modal + drawer on native `<dialog>`, dropdown menu, `ui-carousel` + `ui-lightbox` (gallery, user-driven — not an auto-slider).
132
140
  - **Disclosure & nav** — tabs, accordion, segmented, breadcrumb, pagination, `ui-steps`, `ui-timeline`, `ui-pagehead`, `ui-kbd`.
133
- - **Shells** — an admin dashboard shell (`ui-app-*`) and a content/marketing site shell (`ui-site*`, `ui-container`).
141
+ - **Shells** — a service/app shell (`ui-app-*`) and a content/marketing site shell (`ui-site*`, `ui-container`).
134
142
  - **Prose** — `.ui-prose` styles raw, unclassed semantic HTML (Markdown / CMS / LLM output) with zero classes.
135
- - **Analytical & communication primitives** _(opt-in)_ — `@ponchia/ui/css/analytical.css`: SVG **annotations** (subject/connector/note), standalone **legends**/data-keys, text/evidence **marks**, leader-line **connectors** (+ a pure `@ponchia/ui/connectors` geometry kernel), a guided-focus **spotlight**, a **crosshair**/readout, and a cross-cutting **selection** vocabulary. Each owns its visual grammar + pure geometry and refuses scales/state/hit-testing — figures that explain themselves, not a chart engine. Plus standalone **`source`/provenance** (trust) and **lifecycle `state`** leaves.
136
- - **Reports** _(opt-in)_ — `@ponchia/ui/css/report.css`, a static/PDF-first report grammar for LLM-authored HTML: covers, decisions, claims, sections, severity-labelled findings, evidence packets, evidence ledgers, action registers, source-card bindings, figures, chart wrappers and print utilities.
143
+ - **Analytical & communication primitives** _(opt-in)_ — `@ponchia/ui/css/analytical.css`: **figure** stages, SVG **annotations** (subject/connector/note), standalone **legends**/data-keys, text/evidence **marks**, leader-line **connectors** (+ a pure `@ponchia/ui/connectors` geometry kernel), a guided-focus **spotlight**, a **crosshair**/readout, a cross-cutting **selection** vocabulary, and CSS Custom Highlight API **highlights**. Each owns its visual grammar + pure geometry and refuses scales/state/hit-testing — figures that explain themselves, not a chart engine. Plus standalone **`source`/provenance** (trust), **interval**, **clamp**, and **lifecycle `state`** leaves.
144
+ - **Reports** _(opt-in)_ — `@ponchia/ui/css/report-kit.css` for a complete static/PDF report vocabulary, or `@ponchia/ui/css/report.css` plus only the leaves a narrow report uses. Covers, decisions, claims, sections, severity-labelled findings, evidence packets, evidence ledgers, action registers, source-card bindings, `ui-figure` composition, intervals, bounded excerpts, chart wrappers and print utilities.
137
145
  - **Motion & dots** — the dot-matrix motif kit: dot grid, status dots, dot loaders, the orbital spinner, matrix reveal — all reduced-motion aware.
138
146
  - **Glyphs** — `@ponchia/ui/glyphs`, a 71-glyph dot-matrix icon set on the `.ui-dotmatrix` primitive (display marks + crisp `solid` inline icons + one-node `.ui-icon` mask rendering).
139
147
  - **Colorways** _(opt-in)_ — `data-bronto-skin="amber-crt | phosphor-green | e-ink"`: a root-level recolour of the one accent (OKLCH, per-theme, contrast-gated), never in the default bundle.
@@ -143,13 +151,17 @@ Full generated catalog of every class: **[docs/reference.md](https://github.com/
143
151
 
144
152
  ## Theming: one knob
145
153
 
146
- Everything accent-colored derives from a single `--accent` variable via `color-mix()`. Re-brand the entire app — both light and dark — with one declaration, globally or scoped to any subtree:
154
+ Everything accent-colored derives from a single `--accent` variable via `color-mix()`. Re-brand the entire app — both light and dark — with root-level, per-theme overrides:
147
155
 
148
156
  ```css
149
157
  :root { --accent: #2f6df6; } /* whole app blue */
150
- .promo { --accent: #16a34a; } /* …or just this section green */
151
158
  ```
152
159
 
160
+ Scoped `--accent` overrides recolor direct accent uses in that subtree, but the
161
+ derived family (`--accent-text`, `--accent-soft`, focus/dot/ramp tokens) is a
162
+ root-level skin contract. Use the full per-theme recipe in
163
+ [`docs/theming.md`](docs/theming.md) for production rebrands.
164
+
153
165
  Buttons, focus rings, dot motifs, accent borders and soft fills all follow automatically. Light/dark is `data-theme="light"` / `"dark"` on `<html>` (defaults to `prefers-color-scheme`); `data-density` and `data-contrast` give density and contrast presets. A full re-skin (radius, display face, dot density, surfaces) is a handful more token overrides — the default monochrome look is **one skin, not the architecture**.
154
166
 
155
167
  **One system, many skins.** That the knob is real isn't a claim — it ships: drop in `@ponchia/ui/css/skins.css` and set `data-bronto-skin="amber-crt | phosphor-green | e-ink"` on `<html>` for a complete, contrast-gated recolour (the derived accent family, focus ring, dot-matrix and glyphs all follow). Colour is governed in **tiers** — neutral canvas · one accent · locked status · display expression · opt-in data-viz — so it always earns its place; the full constitution is **[ADR-0001](https://github.com/Ponchia/bronto-ui/blob/main/docs/adr/0001-color-system.md)**.
@@ -162,7 +174,7 @@ Not an afterthought — a gate. Every contractual token pairing has a declared W
162
174
 
163
175
  ## Works with anything
164
176
 
165
- The CSS is the framework, so it works with React, Svelte/SvelteKit, Astro, Vue, Solid, Qwik or plain HTML — there's no component runtime to adopt. The optional `classes` and `behaviors` entrypoints pull in **no** UI framework and are SSR-safe. For React, Solid and Qwik there are also **optional thin bindings** — `@ponchia/ui/react`, `@ponchia/ui/solid` and `@ponchia/ui/qwik` wrap the behaviors as hooks (`useDialog`, `useToast`, …); `react`/`solid-js`/`@builder.io/qwik` are optional peer deps, so the core stays zero-dependency.
177
+ The CSS is the framework, so it works with React, Svelte/SvelteKit, Astro, Vue, Solid, Qwik or plain HTML — there's no component runtime to adopt. The optional `classes` and `behaviors` entrypoints pull in **no** UI framework and are SSR-safe. For React, Solid and Qwik there are also **optional thin bindings** — `@ponchia/ui/react`, `@ponchia/ui/solid` and `@ponchia/ui/qwik` wrap the behaviors as hooks (`useDialog`, `useToast`, …); `react`/`solid-js`/`@builder.io/qwik` are optional peer deps. Svelte and Vue get dependency-free lifecycle adapters too: `@ponchia/ui/svelte` exports actions, and `@ponchia/ui/vue` exports directives/plugin helpers over the same behavior layer.
166
178
 
167
179
  Per-framework getting-started guides + runnable example apps live in the repo:
168
180
 
@@ -171,16 +183,17 @@ Per-framework getting-started guides + runnable example apps live in the repo:
171
183
  | Vanilla / Vite / plain HTML | [vanilla.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/vanilla.md) | [`examples/vanilla-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/vanilla-vite) |
172
184
  | Astro | [astro.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/astro.md) | [`examples/astro`](https://github.com/Ponchia/bronto-ui/tree/main/examples/astro) |
173
185
  | SvelteKit | [sveltekit.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/sveltekit.md) | [`examples/sveltekit`](https://github.com/Ponchia/bronto-ui/tree/main/examples/sveltekit) |
186
+ | Vue | [vue.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/vue.md) | [`examples/vue-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/vue-vite) |
174
187
  | React | [react-solid.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/react-solid.md) | [`examples/react-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/react-vite) |
175
188
  | Solid | [react-solid.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/react-solid.md) | [`examples/solid-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/solid-vite) |
176
189
  | Qwik | [react-solid.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/getting-started/react-solid.md) | [`examples/qwik-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/qwik-vite) |
177
- | Tailwind / cascade-layer interop | [tailwind.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/interop/tailwind.md) | |
190
+ | Tailwind v4 bridge / cascade-layer interop | [tailwind.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/interop/tailwind.md) | [`examples/tailwind-vite`](https://github.com/Ponchia/bronto-ui/tree/main/examples/tailwind-vite) |
178
191
 
179
192
  ## Extras
180
193
 
181
- - **Tokens as data** — `import tokens, { themeColor, cssVars } from '@ponchia/ui/tokens'` (plus `tokens.json`, W3C DTCG `tokens.dtcg.json`, and `tokens/resolved.json` concrete hex per theme for canvas/SVG/MapLibre).
194
+ - **Tokens as data** — `import tokens, { themeColor, cssVars } from '@ponchia/ui/tokens'` (plus `tokens.json`, W3C DTCG `tokens.dtcg.json`, `tokens/resolved.json` for concrete values in canvas/SVG/MapLibre, and `tokens/figma.variables.json` for local Figma Variables import/sync scripts).
182
195
  - **Chart colours for dashboards** — `import charts from '@ponchia/ui/charts.json' with { type: 'json' }` in Node ESM, or the same path through a bundler JSON import (resolved hex per theme; series 1 = your accent) plus the opt-in `@ponchia/ui/css/dataviz.css`.
183
- - **Static reports for LLMs** — add `@ponchia/ui/css/report.css` for report structure, claim/evidence/action grammar, source-card bindings, and print utilities; pair with `@ponchia/ui/css/dataviz.css` only when the report contains charts. Full cookbook: `docs/reporting.md`.
196
+ - **Static reports for LLMs** — add `@ponchia/ui/css/report-kit.css` for the complete report vocabulary, or `@ponchia/ui/css/report.css` plus the specific leaves a smaller report needs. Sidecar claim/source contracts can validate against `@ponchia/ui/schemas/report-claims.v1.schema.json`. Full cookbook: `docs/reporting.md`.
184
197
  - **Modern-platform motion** — overlays (modal/drawer/popover), toasts and the `<details>` accordion animate **in and out** with zero JS (`@starting-style` + `allow-discrete`, `::details-content` + `interpolate-size`). Progressive-enhancement extras: `.ui-scroll-progress` / `.ui-scroll-reveal` (scroll-driven, no JS) and `.ui-vt` for View Transitions. All degrade to a static end-state and respect `prefers-reduced-motion`. For smooth **cross-document** navigations, add the document-global one-liner to your own top-level (unlayered) CSS: `@view-transition { navigation: auto; }`.
185
198
  - **Editor IntelliSense** — point VS Code at the shipped custom-data file so every token autocompletes in `var(--…)`:
186
199
  ```json
@@ -188,7 +201,7 @@ Per-framework getting-started guides + runnable example apps live in the repo:
188
201
  ```
189
202
  - **For AI coding agents** — the package ships `llms.txt` at its root plus `docs/reference.md`, `docs/usage.md`, `docs/reporting.md`, `docs/theming.md`, `docs/contrast.md`, `docs/stability.md`, `docs/package-contract.md`, the color constitution `docs/adr/0001-color-system.md` and the `CHANGELOG` inside the tarball, so an offline agent has the full API and rationale without guessing.
190
203
 
191
- > The package root is **CSS-only**. Use `@import '@ponchia/ui'` in CSS, or `import '@ponchia/ui'` only as a CSS side-effect import in a CSS-aware bundler (Vite, Astro, SvelteKit, webpack). Do not import the package root from Node/runtime JS. JS entrypoints are explicit subpaths: `/tokens`, `/classes`, `/behaviors`, `/glyphs`, `/react`, `/solid`, `/qwik`, `/skins`, and `/charts`.
204
+ > The package root is **CSS-only**. Use `@import '@ponchia/ui'` in CSS, or `import '@ponchia/ui'` only as a CSS side-effect import in a CSS-aware bundler (Vite, Astro, SvelteKit, webpack). Do not import the package root from Node/runtime JS. CSS helper subpaths are explicit too, including `/tailwind` for the Tailwind v4 theme/variant bridge. JS entrypoints are explicit subpaths: `/tokens`, `/classes`, `/behaviors`, `/glyphs`, `/annotations`, `/connectors`, `/react`, `/solid`, `/qwik`, `/svelte`, `/vue`, `/skins`, `/charts`, `/mermaid`, `/d2`, and `/vega`.
192
205
  > JS subpaths are **ESM-only**. CommonJS consumers should use dynamic
193
206
  > `import('@ponchia/ui/behaviors')`.
194
207
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":"AA4RA;;;GAGG;AACH,+CAHW,OAAO,CAAC,eAAe,CAAC,GACtB,MAAM,CAIlB;AAED;;;GAGG;AACH,gFAHW,oBAAoB,GAClB,MAAM,CA0BlB;AAsCD;;;GAGG;AACH,iGAHW,oBAAoB,GAClB,aAAa,CA0DzB;AAED;;;GAGG;AACH,+CAHW,oBAAoB,GAClB,MAAM,CAIlB;AAED;;;GAGG;AACH,mEAHW,kBAAkB,GAChB,MAAM,CAYlB;AAED;;;GAGG;AACH,mDAHW,gBAAgB,GACd,MAAM,CAMlB;AAED;;;GAGG;AACH,uEAHW,oBAAoB,GAClB,MAAM,CASlB;AAED;;;GAGG;AACH,+DAHW,qBAAqB,GACnB,MAAM,CAWlB;AAED;;;GAGG;AACH,mEAHW,kBAAkB,GAChB,MAAM,CAIlB;AAED;;;GAGG;AACH,sDAHW,mBAAmB,GACjB,MAAM,CAIlB;AAED;;;GAGG;AACH,gEAHW,sBAAsB,GACpB,MAAM,CAqClB;AAED;;;GAGG;AACH,wDAHW,qBAAqB,GACnB,MAAM,CAUlB;AAED;;;GAGG;AACH,wDAHW,oBAAoB,GAClB,MAAM,CAUlB;AAED;;;GAGG;AACH,sEAHW,qBAAqB,GACnB,MAAM,CAclB;AAED;;;GAGG;AACH,mDAHW,sBAAsB,GACpB,MAAM,CAIlB;AAED;;;GAGG;AACH,qEAHW,wBAAwB,GACtB,MAAM,CAQlB;AAED;;;GAGG;AACH,qCAHW,gBAAgB,GACd,MAAM,CAWlB;AAED;;;GAGG;AACH,sCAHW,gBAAgB,GACd,MAAM,CAelB;AAED;;;GAGG;AACH,sCAHW,gBAAgB,GACd,MAAM,CAWlB;AAkBD;;;GAGG;AACH,uCAHW,sBAAsB,GACpB,eAAe,CAyB3B;AAED;;;;;;;;;;;;;;GAcG;AACH,uCAJW,kBAAkB,EAAE,SACpB,sBAAsB,GACpB,MAAM,EAAE,CA+BpB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,oCAJW,eAAe,EAAE,SACjB,mBAAmB,GACjB,WAAW,EAAE,CAgCzB;8BAjxBY;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE;+BACxB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE;sCAC1B,SAAS,GAAG,OAAO,GAAG,OAAO;8BAC7B,OAAO,GAAG,QAAQ,GAAG,KAAK;+BAC1B,KAAK,GAAG,QAAQ,GAAG,QAAQ;8BAC3B,YAAY,GAAG,UAAU;gCACzB,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;;UAG/B,QAAQ;YACR,MAAM;;;;UAIN,MAAM;WACN,MAAM;YACN,MAAM;;;;;+BAKP,aAAa,GAAG,WAAW;+BAE3B,gBAAgB,GAAG;IAAE,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE;;YAG9D,MAAM;;;WAGN,MAAM;YACN,MAAM;;;;;;;;QAQN,MAAM;QACN,MAAM;;;;;;SAMN,MAAM;;;QAGN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;;;;;;WAMN,MAAM;YACN,MAAM;;;;QAIN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;;;QAGN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;;;;YAIN,eAAe,EAAE;;;;;;;;;;;;;;qCAclB,eAAe,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;;;;QAKpC,MAAM;QACN,MAAM;;;;;;;;;;;;;;;;;;;;;WAkBN,MAAM;YACN,MAAM;;;;;WAKN,MAAM;YACN,MAAM;YACN,gBAAgB;;;;;;;;;;;;QAShB,MAAM;QACN,MAAM;WACN,eAAe;YACf,gBAAgB;eAChB,MAAM;;qCAEP,CACN,aAAa,GACb,WAAW,GACX,CAAC;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GAAG,gBAAgB,CAAC,GAC1C,CAAC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG,qBAAqB,CAAC,GAC7C,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,kBAAkB,CAAC,GACvC,CAAC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,mBAAmB,CAAC,GACzC,CAAC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG,sBAAsB,CAAC,GAC9C,CAAC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG,qBAAqB,CAAC,GAC7C,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,oBAAoB,CAAC,GACzC,CAAC;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG,oBAAoB,CAAC,GAC7C,CAAC;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG,qBAAqB,CAAC,CACjD;;;;;;;;;;eAWU,MAAM;aACN,MAAM;eACN,MAAM;UACN,MAAM;;;;;;SAGN,MAAM;;;;UACN,MAAM;;;;;;;;;;;;;;;;;;;;YAQN,eAAe;;;;UACf,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAYN,MAAM;OACN,MAAM;;;;YACN,eAAe;;;;;;;;OAEf,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":"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"}
@@ -237,6 +237,24 @@ function validateOffset(opts) {
237
237
  };
238
238
  }
239
239
 
240
+ function annotationConnectorType(value) {
241
+ const type = value ?? 'callout';
242
+ if (type === 'callout' || type === 'elbow' || type === 'curve') return type;
243
+ throw new TypeError('type must be "callout", "elbow" or "curve"');
244
+ }
245
+
246
+ function directLabelAxis(value) {
247
+ const axis = value ?? 'y';
248
+ if (axis === 'x' || axis === 'y') return axis;
249
+ throw new TypeError('axis must be "x" or "y"');
250
+ }
251
+
252
+ function directLabelShape(value) {
253
+ const shape = value ?? 'straight';
254
+ if (shape === 'straight' || shape === 'elbow' || shape === 'curve') return shape;
255
+ throw new TypeError('shape must be "straight", "elbow" or "curve"');
256
+ }
257
+
240
258
  function trimForCircle(dx, dy, subject) {
241
259
  const len = Math.hypot(dx, dy);
242
260
  const radius = dimension('subject.radius', subject.radius);
@@ -673,7 +691,7 @@ const SUBJECT_BUILDERS = {
673
691
  * @returns {AnnotationParts}
674
692
  */
675
693
  export function annotationParts(opts = {}) {
676
- const type = opts.type ?? 'callout';
694
+ const type = annotationConnectorType(opts.type);
677
695
  const transform = annotationTransform({ x: opts.x ?? 0, y: opts.y ?? 0 });
678
696
  const dx = finite('dx', opts.dx, 0);
679
697
  const dy = finite('dy', opts.dy, 0);
@@ -764,9 +782,9 @@ export function declutterLabels(items, opts = {}) {
764
782
  */
765
783
  export function directLabels(items, opts = {}) {
766
784
  if (!Array.isArray(items)) throw new TypeError('items must be an array');
767
- const axis = opts.axis === 'x' ? 'x' : 'y';
785
+ const axis = directLabelAxis(opts.axis);
768
786
  const cross = finite('cross', opts.cross, 0);
769
- const shape = opts.shape === 'elbow' || opts.shape === 'curve' ? opts.shape : 'straight';
787
+ const shape = directLabelShape(opts.shape);
770
788
 
771
789
  const anchors = items.map((it) => ({
772
790
  anchor: { x: finite('anchor.x', it?.anchor?.x), y: finite('anchor.y', it?.anchor?.y) },
@@ -1 +1 @@
1
- {"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["carousel.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CAuK3C"}
1
+ {"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["carousel.js"],"names":[],"mappings":"AA6CA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CA8L3C"}
@@ -5,8 +5,44 @@ import {
5
5
  bindOnce,
6
6
  scrollIntoViewSafe,
7
7
  collectHosts,
8
+ closestSafe,
8
9
  } from './internal.js';
9
10
 
11
+ const snapshotAttrs = (el) =>
12
+ Array.from(el.attributes, ({ name, value }) => ({
13
+ name,
14
+ value,
15
+ }));
16
+
17
+ const restoreAttrs = (el, attrs) => {
18
+ for (const { name } of Array.from(el.attributes)) el.removeAttribute(name);
19
+ for (const { name, value } of attrs) el.setAttribute(name, value);
20
+ };
21
+
22
+ const snapshotNode = (el, { html = false } = {}) =>
23
+ el
24
+ ? {
25
+ el,
26
+ attrs: snapshotAttrs(el),
27
+ ...(html ? { innerHTML: el.innerHTML } : {}),
28
+ }
29
+ : null;
30
+
31
+ const restoreNode = (state) => {
32
+ if (!state) return;
33
+ restoreAttrs(state.el, state.attrs);
34
+ if ('innerHTML' in state) state.el.innerHTML = state.innerHTML;
35
+ };
36
+
37
+ const clampIndex = (value, max) => Math.max(0, Math.min(max, value));
38
+
39
+ const renderedStatusIndex = (status) => {
40
+ const match = /^(\d+)\s*\/\s*\d+$/.exec(status?.textContent?.trim() ?? '');
41
+ if (!match) return -1;
42
+ const value = Number(match[1]);
43
+ return Number.isInteger(value) ? value - 1 : -1;
44
+ };
45
+
10
46
  /**
11
47
  * Image carousel / gallery, built on CSS scroll-snap so touch + trackpad
12
48
  * swipe (and momentum) are the browser's, not hand-rolled. This wires the
@@ -54,33 +90,12 @@ export function initCarousel({ root } = {}) {
54
90
  const nextBtn = box.querySelector('[data-bronto-carousel-next]');
55
91
  const loop = box.hasAttribute('data-bronto-carousel-loop');
56
92
 
57
- // ARIA scaffolding pragmatic carousel semantics (not the full APG
58
- // tablist), the same restraint initMenu takes.
59
- viewport.setAttribute('role', 'group');
60
- viewport.setAttribute('aria-roledescription', 'carousel');
61
- if (!viewport.hasAttribute('aria-label'))
62
- viewport.setAttribute(
63
- 'aria-label',
64
- box.getAttribute('data-bronto-carousel-label') || 'Carousel',
65
- );
66
- if (!viewport.hasAttribute('tabindex')) viewport.tabIndex = 0;
67
- slides.forEach((s, i) => {
68
- s.setAttribute('role', 'group');
69
- s.setAttribute('aria-roledescription', 'slide');
70
- if (!s.hasAttribute('aria-label')) s.setAttribute('aria-label', `${i + 1} of ${n}`);
71
- });
72
- if (status) status.setAttribute('aria-live', 'polite');
73
- for (const b of [prevBtn, nextBtn]) {
74
- if (!b) continue;
75
- if (b.tagName === 'BUTTON' && !b.hasAttribute('type')) b.type = 'button';
76
- }
77
- if (prevBtn && !prevBtn.hasAttribute('aria-label'))
78
- prevBtn.setAttribute('aria-label', 'Previous');
79
- if (nextBtn && !nextBtn.hasAttribute('aria-label')) nextBtn.setAttribute('aria-label', 'Next');
80
-
81
- let index = Math.max(
82
- 0,
83
- slides.findIndex((s) => s.hasAttribute('data-bronto-carousel-current')),
93
+ const authoredIndex = slides.findIndex((s) => s.hasAttribute('data-bronto-carousel-current'));
94
+ const renderedThumbIndex = thumbs.findIndex((t) => t.getAttribute('aria-current') === 'true');
95
+ const statusIndex = renderedStatusIndex(status);
96
+ let index = clampIndex(
97
+ renderedThumbIndex >= 0 ? renderedThumbIndex : statusIndex >= 0 ? statusIndex : authoredIndex,
98
+ n - 1,
84
99
  );
85
100
 
86
101
  // While a button/keyboard nav is smooth-scrolling, the IntersectionObserver
@@ -136,15 +151,15 @@ export function initCarousel({ root } = {}) {
136
151
  goTo(target);
137
152
  };
138
153
  const onClick = (e) => {
139
- if (prevBtn && e.target.closest('[data-bronto-carousel-prev]')) {
154
+ if (prevBtn && closestSafe(e.target, '[data-bronto-carousel-prev]')) {
140
155
  goTo(index - 1);
141
156
  return;
142
157
  }
143
- if (nextBtn && e.target.closest('[data-bronto-carousel-next]')) {
158
+ if (nextBtn && closestSafe(e.target, '[data-bronto-carousel-next]')) {
144
159
  goTo(index + 1);
145
160
  return;
146
161
  }
147
- const thumb = e.target.closest('.ui-carousel__thumb');
162
+ const thumb = closestSafe(e.target, '.ui-carousel__thumb');
148
163
  if (thumb) {
149
164
  const i = thumbs.indexOf(thumb);
150
165
  if (i >= 0) goTo(i);
@@ -178,20 +193,64 @@ export function initCarousel({ root } = {}) {
178
193
  );
179
194
  }
180
195
 
181
- render();
182
196
  const bound = bindOnce(box, 'carousel', () => {
197
+ const state = {
198
+ viewport: snapshotNode(viewport),
199
+ slides: slides.map((slide) => snapshotNode(slide)),
200
+ status: snapshotNode(status, { html: true }),
201
+ controls: [prevBtn, nextBtn, ...thumbs]
202
+ .filter(Boolean)
203
+ .map((control) => snapshotNode(control)),
204
+ };
205
+
206
+ // ARIA scaffolding — pragmatic carousel semantics (not the full APG
207
+ // tablist), the same restraint initMenu takes.
208
+ viewport.setAttribute('role', 'group');
209
+ viewport.setAttribute('aria-roledescription', 'carousel');
210
+ if (!viewport.hasAttribute('aria-label'))
211
+ viewport.setAttribute(
212
+ 'aria-label',
213
+ box.getAttribute('data-bronto-carousel-label') || 'Carousel',
214
+ );
215
+ if (!viewport.hasAttribute('tabindex')) viewport.tabIndex = 0;
216
+ slides.forEach((s, i) => {
217
+ s.setAttribute('role', 'group');
218
+ s.setAttribute('aria-roledescription', 'slide');
219
+ if (!s.hasAttribute('aria-label')) s.setAttribute('aria-label', `${i + 1} of ${n}`);
220
+ });
221
+ if (status) status.setAttribute('aria-live', 'polite');
222
+ for (const b of [prevBtn, nextBtn]) {
223
+ if (!b) continue;
224
+ if (b.tagName === 'BUTTON' && !b.hasAttribute('type')) b.type = 'button';
225
+ }
226
+ for (const b of thumbs) {
227
+ if (b.tagName === 'BUTTON' && !b.hasAttribute('type')) b.type = 'button';
228
+ }
229
+ if (prevBtn && !prevBtn.hasAttribute('aria-label'))
230
+ prevBtn.setAttribute('aria-label', 'Previous');
231
+ if (nextBtn && !nextBtn.hasAttribute('aria-label'))
232
+ nextBtn.setAttribute('aria-label', 'Next');
233
+
234
+ render();
183
235
  viewport.addEventListener('keydown', onKey);
184
236
  box.addEventListener('click', onClick);
185
237
  // Observe inside the add callback so observe/disconnect pair with the
186
238
  // binding lifecycle: a re-init tears down the prior binding (which
187
239
  // disconnects the old observer) before this starts, so two observers
188
240
  // never watch the same slides — even for one tick.
189
- slides.forEach((s) => io?.observe(s));
241
+ if (io) {
242
+ holdProgrammatic();
243
+ slides.forEach((s) => io.observe(s));
244
+ }
190
245
  return () => {
191
246
  viewport.removeEventListener('keydown', onKey);
192
247
  box.removeEventListener('click', onClick);
193
248
  io?.disconnect();
194
249
  if (progTimer) clearTimeout(progTimer);
250
+ restoreNode(state.viewport);
251
+ state.slides.forEach(restoreNode);
252
+ restoreNode(state.status);
253
+ state.controls.forEach(restoreNode);
195
254
  };
196
255
  });
197
256
  cleanups.push(bound);
@@ -1 +1 @@
1
- {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["combobox.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CAqO3C"}
1
+ {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["combobox.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CA8S3C"}