@ponchia/ui 0.6.4 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +106 -0
- package/README.md +17 -10
- package/behaviors/index.d.ts +2 -0
- package/behaviors/index.d.ts.map +1 -1
- package/behaviors/index.js +2 -0
- package/behaviors/sources.d.ts +28 -0
- package/behaviors/sources.d.ts.map +1 -0
- package/behaviors/sources.js +158 -0
- package/classes/classes.json +146 -2
- package/classes/index.d.ts +63 -0
- package/classes/index.js +80 -0
- package/css/report.css +384 -3
- package/css/sources.css +18 -0
- package/css/tokens.css +8 -1
- package/dist/bronto.css +1 -1
- package/dist/css/report.css +1 -1
- package/dist/css/sources.css +1 -1
- package/dist/css/tokens.css +1 -1
- package/docs/frontier-primitives.md +286 -0
- package/docs/package-contract.md +263 -0
- package/docs/reference.md +75 -2
- package/docs/reporting.md +305 -15
- package/docs/sources.md +32 -0
- package/docs/stability.md +6 -3
- package/llms.txt +71 -25
- package/package.json +11 -3
- package/qwik/index.d.ts +1 -0
- package/qwik/index.d.ts.map +1 -1
- package/qwik/index.js +5 -0
- package/react/index.d.ts +1 -0
- package/react/index.d.ts.map +1 -1
- package/react/index.js +3 -0
- package/solid/index.d.ts +2 -0
- package/solid/index.d.ts.map +1 -1
- package/solid/index.js +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,112 @@
|
|
|
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.6 — 2026-06-10
|
|
9
|
+
|
|
10
|
+
Consolidation pass from the 2026-06-10 multi-agent audit: two real PDF-export
|
|
11
|
+
defects fixed and gated, the reporting hub routed to every shipped leaf, and
|
|
12
|
+
the drift-prone hand lists in the gates derived from registries. No breaking
|
|
13
|
+
changes, no `MIGRATIONS.json` entry.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **Print overprint (the big one)** — Chromium-class print engines restart
|
|
18
|
+
grid tracks at each page break, printing new rows over the running content.
|
|
19
|
+
`css/report.css` `@media print` now demotes the vertical document-flow
|
|
20
|
+
wrappers (`.ui-report`, `__section`, `__figure`, `__actions`,
|
|
21
|
+
`.ui-evidence-ledger`) to block flow with margin-emulated gaps; the column
|
|
22
|
+
grids (`.ui-compare`, `.ui-meter__row`, `.ui-report__decision-item`,
|
|
23
|
+
`.ui-evidence-grid`) keep their tracks. Gated by a promoted multi-page
|
|
24
|
+
fixture (`test/e2e/_report-print.fixture.html`) whose PDF is parsed with
|
|
25
|
+
pdfjs-dist and asserted overlap-free (`test/e2e/report-print.spec.mjs`).
|
|
26
|
+
- **Silent module-figure drop in PDFs** — reports that render figures from
|
|
27
|
+
relative `<script type="module">` imports lose them over `file://` (CORS).
|
|
28
|
+
`scripts/render-pdf.mjs` gains `--serve` (loopback HTTP + the report's
|
|
29
|
+
`data-report-ready` signal), forwards page/console errors to stderr, and
|
|
30
|
+
warns when a module report is rendered over `file://`.
|
|
31
|
+
- **Demo class drift** — `demo/index.html` still used the renamed
|
|
32
|
+
`ui-inspector__header` (now `__head`), and `demo/version-history-report.html`
|
|
33
|
+
carried a never-registered cover-mark class; both were silent no-ops. The
|
|
34
|
+
generated reference's analytical-leaves note now names `ui-annotation`
|
|
35
|
+
(singular, the real class).
|
|
36
|
+
- `scripts/smoke-example.mjs` imports Chromium from `@playwright/test` (the
|
|
37
|
+
installed devDependency) instead of the hoisting-dependent bare
|
|
38
|
+
`playwright` specifier.
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- **Reporting hub routing** — `docs/reporting.md`'s analytical-toolbox table
|
|
43
|
+
now routes ALL report-relevant leaves (spark, bullet, diff, code, sidenote,
|
|
44
|
+
textref, term, glossary, contents rail, tree, dot surfaces) and states
|
|
45
|
+
precisely what `analytical.css` does and does not bundle. New convention in
|
|
46
|
+
CONTRIBUTING: a new report-relevant leaf ships in the same PR as its
|
|
47
|
+
routing row.
|
|
48
|
+
- **`npm run release:prep -- X.Y.Z`** — one-shot release prep: version + lock
|
|
49
|
+
bump, CHANGELOG heading dating, and re-pinning every `@ponchia/ui@X.Y.Z`
|
|
50
|
+
literal across the gated shipped docs AND the ungated `demo/*.html` pages
|
|
51
|
+
(which had already drifted a version behind).
|
|
52
|
+
- **Cross-engine e2e on merge-to-main** — pushes to `main` that touch
|
|
53
|
+
engine-sensitive surfaces (`css/`, `dist/`, `behaviors/`, `fonts/`,
|
|
54
|
+
`tokens/`, `test/e2e/`, the Playwright config) now run the firefox/webkit
|
|
55
|
+
pass too, instead of deferring it to the release tag.
|
|
56
|
+
- **`demo/dots.html`** — the dot data surfaces (waffle, activity, level,
|
|
57
|
+
dotgauge, readout, spark--dots, halftone, dotfit) get a specimen page,
|
|
58
|
+
axe/guard coverage in `demos.spec`, and render-geometry boundingBox
|
|
59
|
+
assertions (their only possible executable gate — they ship no JS).
|
|
60
|
+
- jsdom coverage for `initDisabledGuard` (activation blocking, Tab
|
|
61
|
+
pass-through, root scoping, cleanup).
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
|
|
65
|
+
- `check:report` and `check:pack` derive their scan/entrypoint lists from
|
|
66
|
+
registries (`package.json` `files`/`exports` via `scripts/lib/css-leaves.mjs`
|
|
67
|
+
+ `lib/shipped-docs.mjs`) instead of hand lists that had drifted behind the
|
|
68
|
+
post-0.6.0 leaves. The broadened scan immediately caught the demo/reference
|
|
69
|
+
class defects above. `core.css` imports are now closed over an explicit
|
|
70
|
+
CORE_BUNDLE allowlist in both directions.
|
|
71
|
+
- `ROADMAP.md` / `docs/frontier-primitives.md` reconciled to 0.6.5: the
|
|
72
|
+
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.
|
|
78
|
+
|
|
79
|
+
## 0.6.5 — 2026-06-09
|
|
80
|
+
|
|
81
|
+
Patch release: the source-backref behavior, the report decision/evidence
|
|
82
|
+
grammar, and package/release hardening. No breaking changes, no
|
|
83
|
+
`MIGRATIONS.json` entry.
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
|
|
87
|
+
- **`initSources` behavior** — optional citation→source backref focus:
|
|
88
|
+
inside a `data-bronto-sources` host, a `.ui-citation[href^="#"]` (or an
|
|
89
|
+
explicit `data-bronto-source-ref`) click scrolls to its source card and
|
|
90
|
+
marks it `is-source-active`, emitting a cancellable focus event with the
|
|
91
|
+
`SourceFocusDetail` payload. Progressive enhancement over authored ids —
|
|
92
|
+
no DOM is generated; framework bindings re-export it.
|
|
93
|
+
- **Report decision/evidence grammar** — adds public, static report primitives
|
|
94
|
+
for decision blocks, severity-labelled findings, compact evidence packets and
|
|
95
|
+
follow-up action rows.
|
|
96
|
+
- **Claim and action-register grammar** — adds claim status blocks, structured
|
|
97
|
+
finding parts, evidence-method parts, evidence ledgers, decision detail rows,
|
|
98
|
+
and action owner/due/criteria/source parts for more auditable reports.
|
|
99
|
+
- **Package contract doc** — `docs/package-contract.md` pins the published
|
|
100
|
+
surface (exports map, files allowlist, generated-artifact freshness) that
|
|
101
|
+
`check:pack`/`check:publint`/`check:attw` enforce.
|
|
102
|
+
|
|
103
|
+
### Changed
|
|
104
|
+
|
|
105
|
+
- **Report fixtures and local guardrails** — expands the standalone and full
|
|
106
|
+
report demos with source/provenance examples, SVG accessibility details and a
|
|
107
|
+
local-only public-boundary terms gate for `check:report`.
|
|
108
|
+
- **Report shape checks** — `check:report` now parses report demos with a DOM
|
|
109
|
+
instead of regexes and validates the public claim/action contracts.
|
|
110
|
+
- **Release observability** — the release workflow gains a metadata gate and
|
|
111
|
+
theme-axis verification; the examples consumer build broadens its smoke
|
|
112
|
+
coverage.
|
|
113
|
+
|
|
8
114
|
## 0.6.4 — 2026-06-08
|
|
9
115
|
|
|
10
116
|
Patch release for the dot-matrix expansion and static report hardening shipped
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@ponchia/ui)
|
|
4
4
|
[](https://www.npmjs.com/package/@ponchia/ui#provenance)
|
|
5
5
|
[](https://github.com/Ponchia/bronto-ui/blob/main/package.json)
|
|
6
|
-
[](https://github.com/Ponchia/bronto-ui/blob/main/scripts/check-dist.mjs)
|
|
7
7
|
[](https://github.com/Ponchia/bronto-ui/actions/workflows/ci.yml)
|
|
8
8
|
[](https://scorecard.dev/viewer/?uri=github.com/Ponchia/bronto-ui)
|
|
9
9
|
[](https://github.com/Ponchia/bronto-ui/blob/main/LICENSE)
|
|
@@ -22,9 +22,16 @@ SVG annotations, legends, leader-line connectors, a guided-focus spotlight, text
|
|
|
22
22
|
marks, a colourblind-safe data-viz palette, and a static/PDF report grammar — for
|
|
23
23
|
dashboards and LLM-authored reports.
|
|
24
24
|
|
|
25
|
-
### [Live demo →](https://ponchia.github.io/bronto-ui/) · [Theme playground →](https://ponchia.github.io/bronto-ui/demo/theme-playground.html)
|
|
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)
|
|
26
26
|
|
|
27
27
|
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
|
+
|
|
31
|
+
<p>
|
|
32
|
+
<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%" />
|
|
33
|
+
<img alt="The same report grammar printed to PDF" src="https://raw.githubusercontent.com/Ponchia/bronto-ui/main/demo/_preview-report-print.png" width="49%" />
|
|
34
|
+
</p>
|
|
28
35
|
|
|
29
36
|
---
|
|
30
37
|
|
|
@@ -57,7 +64,7 @@ Or drop it in with no build step, straight from a CDN:
|
|
|
57
64
|
|
|
58
65
|
## Quick start
|
|
59
66
|
|
|
60
|
-
**1. Load the CSS.** One flattened, minified bundle — the whole standard component set, one request (~
|
|
67
|
+
**1. Load the CSS.** One flattened, minified bundle — the whole standard component set, one request (~87 kB raw / ~15 kB gzip):
|
|
61
68
|
|
|
62
69
|
```css
|
|
63
70
|
@import '@ponchia/ui'; /* via a bundler */
|
|
@@ -102,9 +109,9 @@ initDialog(); // native <dialog> glue: [data-bronto-open] / [data-bronto-
|
|
|
102
109
|
toast('Saved', { tone: 'success' }); // body-anchored stack, no markup needed
|
|
103
110
|
```
|
|
104
111
|
|
|
105
|
-
Behaviors cover theme persistence, disclosure, dropdown menus, native-`<dialog>` modals/drawers, tabs, combobox, form validation, table sort, carousel and toasts — wired by `data-bronto-*` attributes.
|
|
112
|
+
Behaviors cover theme persistence, disclosure, dropdown menus, native-`<dialog>` modals/drawers, tabs, combobox, form validation, table sort, carousel, source backrefs and toasts — wired by `data-bronto-*` attributes.
|
|
106
113
|
|
|
107
|
-
**5. (Optional) display glyphs — a
|
|
114
|
+
**5. (Optional) display glyphs — a 71-glyph dot-matrix icon set:**
|
|
108
115
|
|
|
109
116
|
```js
|
|
110
117
|
import { renderGlyph } from '@ponchia/ui/glyphs';
|
|
@@ -126,9 +133,9 @@ Arrows, chevrons, check/close/plus/minus, search/menu/gear, info/warning/bell/lo
|
|
|
126
133
|
- **Shells** — an admin dashboard shell (`ui-app-*`) and a content/marketing site shell (`ui-site*`, `ui-container`).
|
|
127
134
|
- **Prose** — `.ui-prose` styles raw, unclassed semantic HTML (Markdown / CMS / LLM output) with zero classes.
|
|
128
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.
|
|
129
|
-
- **Reports** _(opt-in)_ — `@ponchia/ui/css/report.css`, a static/PDF-first report grammar for LLM-authored HTML: covers, sections, findings, evidence, figures, chart wrappers and print utilities.
|
|
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.
|
|
130
137
|
- **Motion & dots** — the dot-matrix motif kit: dot grid, status dots, dot loaders, the orbital spinner, matrix reveal — all reduced-motion aware.
|
|
131
|
-
- **Glyphs** — `@ponchia/ui/glyphs`, a
|
|
138
|
+
- **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).
|
|
132
139
|
- **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.
|
|
133
140
|
- **Data-viz** _(opt-in)_ — a colourblind-safe chart palette (`--chart-*` + dot-matrix pattern fills, resolved hex in `charts.json`), gated under simulated protan/deutan/tritan vision. Charts only, never UI chrome.
|
|
134
141
|
|
|
@@ -173,13 +180,13 @@ Per-framework getting-started guides + runnable example apps live in the repo:
|
|
|
173
180
|
|
|
174
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).
|
|
175
182
|
- **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`.
|
|
176
|
-
- **Static reports for LLMs** — add `@ponchia/ui/css/report.css` for report structure and print utilities; pair with `@ponchia/ui/css/dataviz.css` only when the report contains charts. Full cookbook: `docs/reporting.md`.
|
|
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`.
|
|
177
184
|
- **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; }`.
|
|
178
185
|
- **Editor IntelliSense** — point VS Code at the shipped custom-data file so every token autocompletes in `var(--…)`:
|
|
179
186
|
```json
|
|
180
187
|
{ "css.customData": ["node_modules/@ponchia/ui/classes/vscode.css-custom-data.json"] }
|
|
181
188
|
```
|
|
182
|
-
- **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`, 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.
|
|
189
|
+
- **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.
|
|
183
190
|
|
|
184
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`.
|
|
185
192
|
> JS subpaths are **ESM-only**. CommonJS consumers should use dynamic
|
|
@@ -193,7 +200,7 @@ Recent-evergreen, by design. The framework targets the modern web platform — c
|
|
|
193
200
|
|
|
194
201
|
Pre-1.0 and deliberately so. **Until `1.0.0`, breaking changes ship in the _minor_** (`0.x.0`); patches (`0.x.y`) are always non-breaking. Pin with the patch range — at `0.x`, `~0.6.0` (and equivalently `^0.6.0`) resolves to `>=0.6.0 <0.7.0`, giving you safe patches while holding back the next breaking minor. Every breaking change is called out under a **BREAKING** heading in the **[CHANGELOG](https://github.com/Ponchia/bronto-ui/blob/main/CHANGELOG.md)** with a migration note.
|
|
195
202
|
|
|
196
|
-
Contractual (changes are breaking): token **names** and documented token roles, `.ui-*` class and recipe names, `data-bronto-*` attributes, exported behavior/glyph/binding function names and each behavior's cleanup contract. Not contractual (may change any release): exact token **values** and generated colour math outputs (visual tuning) unless a doc explicitly says the value is stable, plus internal leaf-file / `@layer` boundaries. See **[docs/stability.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/stability.md)** for the
|
|
203
|
+
Contractual (changes are breaking): token **names** and documented token roles, `.ui-*` class and recipe names, `data-bronto-*` attributes, exported behavior/glyph/binding function names and each behavior's cleanup contract. Not contractual (may change any release): exact token **values** and generated colour math outputs (visual tuning) unless a doc explicitly says the value is stable, plus internal leaf-file / `@layer` boundaries. See **[docs/stability.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/stability.md)** for the semantic public-surface matrix and **[docs/package-contract.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/package-contract.md)** for the generated export/file/provenance inventory.
|
|
197
204
|
|
|
198
205
|
Release candidates publish to the `next` dist-tag, never to `latest` — opt in with `npm i @ponchia/ui@next` to try an upcoming version early. A plain `npm i @ponchia/ui` only ever resolves a stable release.
|
|
199
206
|
|
package/behaviors/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export { initConnectors } from "./connectors.js";
|
|
|
17
17
|
export { initSpotlight } from "./spotlight.js";
|
|
18
18
|
export { initCrosshair } from "./crosshair.js";
|
|
19
19
|
export { initCommand } from "./command.js";
|
|
20
|
+
export { initSources } from "./sources.js";
|
|
20
21
|
export type Cleanup = import("./internal.js").Cleanup;
|
|
21
22
|
export type DelegateOpts = import("./internal.js").DelegateOpts;
|
|
22
23
|
export type ThemeStorageOpts = import("./theme.js").ThemeStorageOpts;
|
|
@@ -27,5 +28,6 @@ export type ModalCloseDetail = import("./modal.js").ModalCloseDetail;
|
|
|
27
28
|
export type LegendToggleDetail = import("./legend.js").LegendToggleDetail;
|
|
28
29
|
export type CrosshairMoveDetail = import("./crosshair.js").CrosshairMoveDetail;
|
|
29
30
|
export type CommandSelectDetail = import("./command.js").CommandSelectDetail;
|
|
31
|
+
export type SourceFocusDetail = import("./sources.js").SourceFocusDetail;
|
|
30
32
|
export { applyStoredTheme, initThemeToggle } from "./theme.js";
|
|
31
33
|
//# sourceMappingURL=index.d.ts.map
|
package/behaviors/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;sBAmBa,OAAO,eAAe,EAAE,OAAO;2BAC/B,OAAO,eAAe,EAAE,YAAY;+BACpC,OAAO,YAAY,EAAE,gBAAgB;6BACrC,OAAO,YAAY,EAAE,cAAc;gCACnC,OAAO,YAAY,EAAE,iBAAiB;wBACtC,OAAO,YAAY,EAAE,SAAS;+BAC9B,OAAO,YAAY,EAAE,gBAAgB;iCACrC,OAAO,aAAa,EAAE,kBAAkB;kCACxC,OAAO,gBAAgB,EAAE,mBAAmB;kCAC5C,OAAO,cAAc,EAAE,mBAAmB;gCAC1C,OAAO,cAAc,EAAE,iBAAiB"}
|
package/behaviors/index.js
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
* @typedef {import('./legend.js').LegendToggleDetail} LegendToggleDetail
|
|
28
28
|
* @typedef {import('./crosshair.js').CrosshairMoveDetail} CrosshairMoveDetail
|
|
29
29
|
* @typedef {import('./command.js').CommandSelectDetail} CommandSelectDetail
|
|
30
|
+
* @typedef {import('./sources.js').SourceFocusDetail} SourceFocusDetail
|
|
30
31
|
*/
|
|
31
32
|
export { applyStoredTheme, initThemeToggle } from './theme.js';
|
|
32
33
|
export { dismissible } from './dismissible.js';
|
|
@@ -48,3 +49,4 @@ export { initConnectors } from './connectors.js';
|
|
|
48
49
|
export { initSpotlight } from './spotlight.js';
|
|
49
50
|
export { initCrosshair } from './crosshair.js';
|
|
50
51
|
export { initCommand } from './command.js';
|
|
52
|
+
export { initSources } from './sources.js';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source/citation affordances for the `sources.css` trust layer. The behavior
|
|
3
|
+
* is deliberately small: within each `[data-bronto-sources]` island it resolves
|
|
4
|
+
* `.ui-citation[href^="#"]` and `[data-bronto-source-ref]` controls to source
|
|
5
|
+
* cards, adds non-visual preview metadata (`title` + `aria-describedby`), and
|
|
6
|
+
* on activation moves focus to the source card with a temporary
|
|
7
|
+
* `.is-source-active` highlight. The host still owns fetching, numbering,
|
|
8
|
+
* trust decisions, and any rich preview UI.
|
|
9
|
+
*
|
|
10
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
11
|
+
* @returns {import('./internal.js').Cleanup}
|
|
12
|
+
*/
|
|
13
|
+
export function initSources({ root }?: import("./internal.js").DelegateOpts): import("./internal.js").Cleanup;
|
|
14
|
+
export type SourceFocusDetail = {
|
|
15
|
+
/**
|
|
16
|
+
* The focused source-card id.
|
|
17
|
+
*/
|
|
18
|
+
id: string;
|
|
19
|
+
/**
|
|
20
|
+
* The citation/control that requested the source.
|
|
21
|
+
*/
|
|
22
|
+
citation: Element;
|
|
23
|
+
/**
|
|
24
|
+
* The target source card or source element.
|
|
25
|
+
*/
|
|
26
|
+
source: Element;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=sources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["sources.js"],"names":[],"mappings":"AA2CA;;;;;;;;;;;GAWG;AACH,uCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CAwG3C;;;;;QAjJa,MAAM;;;;cACN,OAAO;;;;YACP,OAAO"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hasDom,
|
|
3
|
+
resolveHost,
|
|
4
|
+
noop,
|
|
5
|
+
bindOnce,
|
|
6
|
+
byIdInHost,
|
|
7
|
+
collectHosts,
|
|
8
|
+
scrollIntoViewSafe,
|
|
9
|
+
} from './internal.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {object} SourceFocusDetail
|
|
13
|
+
* @property {string} id The focused source-card id.
|
|
14
|
+
* @property {Element} citation The citation/control that requested the source.
|
|
15
|
+
* @property {Element} source The target source card or source element.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const REF_SELECTOR = '[data-bronto-source-ref], .ui-citation[href^="#"]';
|
|
19
|
+
const ACTIVE = 'is-source-active';
|
|
20
|
+
|
|
21
|
+
function sourceId(ref) {
|
|
22
|
+
const explicit = ref.getAttribute('data-bronto-source-ref');
|
|
23
|
+
if (explicit) return explicit.replace(/^#/, '');
|
|
24
|
+
const href = ref.getAttribute('href') || '';
|
|
25
|
+
if (!href.startsWith('#') || href === '#') return '';
|
|
26
|
+
try {
|
|
27
|
+
return decodeURIComponent(href.slice(1));
|
|
28
|
+
} catch {
|
|
29
|
+
return href.slice(1);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function sourcePreview(source) {
|
|
34
|
+
const text = (selector) =>
|
|
35
|
+
source.querySelector(selector)?.textContent?.replace(/\s+/g, ' ').trim() || '';
|
|
36
|
+
const title = text('.ui-source-card__title');
|
|
37
|
+
const meta = [text('.ui-source-card__origin'), text('.ui-source-card__time')]
|
|
38
|
+
.filter(Boolean)
|
|
39
|
+
.join(' · ');
|
|
40
|
+
const excerpt = text('.ui-source-card__excerpt');
|
|
41
|
+
return [title, meta, excerpt].filter(Boolean).join(' — ');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Source/citation affordances for the `sources.css` trust layer. The behavior
|
|
46
|
+
* is deliberately small: within each `[data-bronto-sources]` island it resolves
|
|
47
|
+
* `.ui-citation[href^="#"]` and `[data-bronto-source-ref]` controls to source
|
|
48
|
+
* cards, adds non-visual preview metadata (`title` + `aria-describedby`), and
|
|
49
|
+
* on activation moves focus to the source card with a temporary
|
|
50
|
+
* `.is-source-active` highlight. The host still owns fetching, numbering,
|
|
51
|
+
* trust decisions, and any rich preview UI.
|
|
52
|
+
*
|
|
53
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
54
|
+
* @returns {import('./internal.js').Cleanup}
|
|
55
|
+
*/
|
|
56
|
+
export function initSources({ root } = {}) {
|
|
57
|
+
if (!hasDom()) return noop;
|
|
58
|
+
const host = resolveHost(root);
|
|
59
|
+
if (!host) return noop;
|
|
60
|
+
|
|
61
|
+
const islands = collectHosts(host, '[data-bronto-sources]');
|
|
62
|
+
const cleanups = [];
|
|
63
|
+
|
|
64
|
+
for (const island of islands) {
|
|
65
|
+
const timers = new Set();
|
|
66
|
+
const seeded = [];
|
|
67
|
+
|
|
68
|
+
const targetFor = (ref) => {
|
|
69
|
+
const id = sourceId(ref);
|
|
70
|
+
if (!id) return null;
|
|
71
|
+
return byIdInHost(island, id);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const seed = () => {
|
|
75
|
+
for (const ref of island.querySelectorAll(REF_SELECTOR)) {
|
|
76
|
+
const source = targetFor(ref);
|
|
77
|
+
if (!source?.id) continue;
|
|
78
|
+
|
|
79
|
+
const describedBy = ref.getAttribute('aria-describedby') || '';
|
|
80
|
+
const describedIds = describedBy.split(/\s+/).filter(Boolean);
|
|
81
|
+
const title = ref.getAttribute('title');
|
|
82
|
+
const preview = sourcePreview(source);
|
|
83
|
+
const prior = {
|
|
84
|
+
ref,
|
|
85
|
+
describedBy,
|
|
86
|
+
hadDescribedBy: ref.hasAttribute('aria-describedby'),
|
|
87
|
+
title,
|
|
88
|
+
hadTitle: ref.hasAttribute('title'),
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
if (!describedIds.includes(source.id)) {
|
|
92
|
+
ref.setAttribute('aria-describedby', [...describedIds, source.id].join(' '));
|
|
93
|
+
}
|
|
94
|
+
if (!title && preview) ref.setAttribute('title', preview);
|
|
95
|
+
if (!source.hasAttribute('tabindex')) {
|
|
96
|
+
prior.source = source;
|
|
97
|
+
prior.hadTabindex = false;
|
|
98
|
+
source.setAttribute('tabindex', '-1');
|
|
99
|
+
}
|
|
100
|
+
seeded.push(prior);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const focusSource = (ref, source) => {
|
|
105
|
+
for (const card of island.querySelectorAll(`.${ACTIVE}`)) card.classList.remove(ACTIVE);
|
|
106
|
+
for (const timer of timers) clearTimeout(timer);
|
|
107
|
+
timers.clear();
|
|
108
|
+
|
|
109
|
+
source.classList.add(ACTIVE);
|
|
110
|
+
source.focus?.({ preventScroll: true });
|
|
111
|
+
scrollIntoViewSafe(source);
|
|
112
|
+
|
|
113
|
+
const timer = setTimeout(() => {
|
|
114
|
+
source.classList.remove(ACTIVE);
|
|
115
|
+
timers.delete(timer);
|
|
116
|
+
}, 1600);
|
|
117
|
+
timers.add(timer);
|
|
118
|
+
|
|
119
|
+
island.dispatchEvent(
|
|
120
|
+
new CustomEvent('bronto:source:focus', {
|
|
121
|
+
detail: { id: source.id, citation: ref, source },
|
|
122
|
+
bubbles: true,
|
|
123
|
+
}),
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const onClick = (e) => {
|
|
128
|
+
const ref = e.target.closest?.(REF_SELECTOR);
|
|
129
|
+
if (!ref || !island.contains(ref)) return;
|
|
130
|
+
const source = targetFor(ref);
|
|
131
|
+
if (!source) return;
|
|
132
|
+
if (!ref.matches('a[href]')) e.preventDefault();
|
|
133
|
+
focusSource(ref, source);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const cleanup = bindOnce(island, 'sources', () => {
|
|
137
|
+
seed();
|
|
138
|
+
island.addEventListener('click', onClick);
|
|
139
|
+
return () => {
|
|
140
|
+
island.removeEventListener('click', onClick);
|
|
141
|
+
for (const timer of timers) clearTimeout(timer);
|
|
142
|
+
timers.clear();
|
|
143
|
+
for (const item of seeded.splice(0)) {
|
|
144
|
+
if (item.hadDescribedBy) item.ref.setAttribute('aria-describedby', item.describedBy);
|
|
145
|
+
else item.ref.removeAttribute('aria-describedby');
|
|
146
|
+
if (item.hadTitle) item.ref.setAttribute('title', item.title);
|
|
147
|
+
else item.ref.removeAttribute('title');
|
|
148
|
+
if (item.source && item.hadTabindex === false) item.source.removeAttribute('tabindex');
|
|
149
|
+
}
|
|
150
|
+
for (const card of island.querySelectorAll(`.${ACTIVE}`)) card.classList.remove(ACTIVE);
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
cleanups.push(cleanup);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return () => cleanups.forEach((fn) => fn());
|
|
158
|
+
}
|
package/classes/classes.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "@ponchia/ui class vocabulary as language-neutral data — validate emitted markup without executing the ESM cls map or parsing the .d.ts. Generated from classes/index.js — do not edit by hand; run `npm run classes:json:build`. Drift-checked in CI. `groups[].base` is null for a parts-only namespace (no standalone base class — do NOT emit it). A modifier whose name contains `__` (e.g. `ui-spark__bar--pos`) attaches to THAT part, not the base host. `states` is the author-applied `is-*` hooks (runtime/behavior-managed hooks are excluded); `behaviorAttributes` are the `data-bronto-*` wiring hooks the optional behaviors delegate on; `requiredAria` is the role/aria a generator must emit per component. `states` + `customProperties` are documented in docs/reference.md and ship outside `cls` by design.",
|
|
3
3
|
"counts": {
|
|
4
|
-
"classes":
|
|
5
|
-
"groups":
|
|
4
|
+
"classes": 593,
|
|
5
|
+
"groups": 171
|
|
6
6
|
},
|
|
7
7
|
"groups": {
|
|
8
8
|
"ui-accordion": {
|
|
@@ -303,6 +303,25 @@
|
|
|
303
303
|
],
|
|
304
304
|
"parts": []
|
|
305
305
|
},
|
|
306
|
+
"ui-claim": {
|
|
307
|
+
"base": "ui-claim",
|
|
308
|
+
"modifiers": [
|
|
309
|
+
"ui-claim--disputed",
|
|
310
|
+
"ui-claim--partial",
|
|
311
|
+
"ui-claim--supported",
|
|
312
|
+
"ui-claim--unknown",
|
|
313
|
+
"ui-claim--unsupported"
|
|
314
|
+
],
|
|
315
|
+
"parts": [
|
|
316
|
+
"ui-claim__basis",
|
|
317
|
+
"ui-claim__caveat",
|
|
318
|
+
"ui-claim__limits",
|
|
319
|
+
"ui-claim__refs",
|
|
320
|
+
"ui-claim__scope",
|
|
321
|
+
"ui-claim__statement",
|
|
322
|
+
"ui-claim__status"
|
|
323
|
+
]
|
|
324
|
+
},
|
|
306
325
|
"ui-cluster": {
|
|
307
326
|
"base": "ui-cluster",
|
|
308
327
|
"modifiers": [
|
|
@@ -526,6 +545,31 @@
|
|
|
526
545
|
"ui-error-summary__title"
|
|
527
546
|
]
|
|
528
547
|
},
|
|
548
|
+
"ui-evidence-grid": {
|
|
549
|
+
"base": "ui-evidence-grid",
|
|
550
|
+
"modifiers": [],
|
|
551
|
+
"parts": []
|
|
552
|
+
},
|
|
553
|
+
"ui-evidence-item": {
|
|
554
|
+
"base": "ui-evidence-item",
|
|
555
|
+
"modifiers": [],
|
|
556
|
+
"parts": [
|
|
557
|
+
"ui-evidence-item__body",
|
|
558
|
+
"ui-evidence-item__caveat",
|
|
559
|
+
"ui-evidence-item__kind",
|
|
560
|
+
"ui-evidence-item__meta",
|
|
561
|
+
"ui-evidence-item__method",
|
|
562
|
+
"ui-evidence-item__source",
|
|
563
|
+
"ui-evidence-item__title",
|
|
564
|
+
"ui-evidence-item__value",
|
|
565
|
+
"ui-evidence-item__window"
|
|
566
|
+
]
|
|
567
|
+
},
|
|
568
|
+
"ui-evidence-ledger": {
|
|
569
|
+
"base": "ui-evidence-ledger",
|
|
570
|
+
"modifiers": [],
|
|
571
|
+
"parts": []
|
|
572
|
+
},
|
|
529
573
|
"ui-eyebrow": {
|
|
530
574
|
"base": "ui-eyebrow",
|
|
531
575
|
"modifiers": [
|
|
@@ -894,15 +938,43 @@
|
|
|
894
938
|
"ui-report--compact",
|
|
895
939
|
"ui-report--numbered",
|
|
896
940
|
"ui-report__cover--compact",
|
|
941
|
+
"ui-report__finding--critical",
|
|
942
|
+
"ui-report__finding--major",
|
|
943
|
+
"ui-report__finding--minor",
|
|
944
|
+
"ui-report__finding--resolved",
|
|
897
945
|
"ui-report__section--unnumbered"
|
|
898
946
|
],
|
|
899
947
|
"parts": [
|
|
948
|
+
"ui-report__action",
|
|
949
|
+
"ui-report__action-criteria",
|
|
950
|
+
"ui-report__action-due",
|
|
951
|
+
"ui-report__action-owner",
|
|
952
|
+
"ui-report__action-priority",
|
|
953
|
+
"ui-report__action-source",
|
|
954
|
+
"ui-report__action-status",
|
|
955
|
+
"ui-report__action-title",
|
|
956
|
+
"ui-report__actions",
|
|
900
957
|
"ui-report__appendix",
|
|
901
958
|
"ui-report__caption",
|
|
902
959
|
"ui-report__cover",
|
|
960
|
+
"ui-report__decision",
|
|
961
|
+
"ui-report__decision-body",
|
|
962
|
+
"ui-report__decision-grid",
|
|
963
|
+
"ui-report__decision-item",
|
|
964
|
+
"ui-report__decision-kicker",
|
|
965
|
+
"ui-report__decision-label",
|
|
966
|
+
"ui-report__decision-meta",
|
|
967
|
+
"ui-report__decision-title",
|
|
968
|
+
"ui-report__decision-value",
|
|
903
969
|
"ui-report__evidence",
|
|
904
970
|
"ui-report__figure",
|
|
905
971
|
"ui-report__finding",
|
|
972
|
+
"ui-report__finding-caveat",
|
|
973
|
+
"ui-report__finding-claim",
|
|
974
|
+
"ui-report__finding-evidence",
|
|
975
|
+
"ui-report__finding-impact",
|
|
976
|
+
"ui-report__finding-remediation",
|
|
977
|
+
"ui-report__finding-title",
|
|
906
978
|
"ui-report__footnotes",
|
|
907
979
|
"ui-report__head",
|
|
908
980
|
"ui-report__meta",
|
|
@@ -1469,6 +1541,19 @@
|
|
|
1469
1541
|
"ui-chip--accent",
|
|
1470
1542
|
"ui-citation",
|
|
1471
1543
|
"ui-citation--chip",
|
|
1544
|
+
"ui-claim",
|
|
1545
|
+
"ui-claim--disputed",
|
|
1546
|
+
"ui-claim--partial",
|
|
1547
|
+
"ui-claim--supported",
|
|
1548
|
+
"ui-claim--unknown",
|
|
1549
|
+
"ui-claim--unsupported",
|
|
1550
|
+
"ui-claim__basis",
|
|
1551
|
+
"ui-claim__caveat",
|
|
1552
|
+
"ui-claim__limits",
|
|
1553
|
+
"ui-claim__refs",
|
|
1554
|
+
"ui-claim__scope",
|
|
1555
|
+
"ui-claim__statement",
|
|
1556
|
+
"ui-claim__status",
|
|
1472
1557
|
"ui-cluster",
|
|
1473
1558
|
"ui-cluster--between",
|
|
1474
1559
|
"ui-code",
|
|
@@ -1566,6 +1651,18 @@
|
|
|
1566
1651
|
"ui-error-summary",
|
|
1567
1652
|
"ui-error-summary__list",
|
|
1568
1653
|
"ui-error-summary__title",
|
|
1654
|
+
"ui-evidence-grid",
|
|
1655
|
+
"ui-evidence-item",
|
|
1656
|
+
"ui-evidence-item__body",
|
|
1657
|
+
"ui-evidence-item__caveat",
|
|
1658
|
+
"ui-evidence-item__kind",
|
|
1659
|
+
"ui-evidence-item__meta",
|
|
1660
|
+
"ui-evidence-item__method",
|
|
1661
|
+
"ui-evidence-item__source",
|
|
1662
|
+
"ui-evidence-item__title",
|
|
1663
|
+
"ui-evidence-item__value",
|
|
1664
|
+
"ui-evidence-item__window",
|
|
1665
|
+
"ui-evidence-ledger",
|
|
1569
1666
|
"ui-eyebrow",
|
|
1570
1667
|
"ui-eyebrow--muted",
|
|
1571
1668
|
"ui-eyebrow--sm",
|
|
@@ -1706,13 +1803,41 @@
|
|
|
1706
1803
|
"ui-report",
|
|
1707
1804
|
"ui-report--compact",
|
|
1708
1805
|
"ui-report--numbered",
|
|
1806
|
+
"ui-report__action",
|
|
1807
|
+
"ui-report__action-criteria",
|
|
1808
|
+
"ui-report__action-due",
|
|
1809
|
+
"ui-report__action-owner",
|
|
1810
|
+
"ui-report__action-priority",
|
|
1811
|
+
"ui-report__action-source",
|
|
1812
|
+
"ui-report__action-status",
|
|
1813
|
+
"ui-report__action-title",
|
|
1814
|
+
"ui-report__actions",
|
|
1709
1815
|
"ui-report__appendix",
|
|
1710
1816
|
"ui-report__caption",
|
|
1711
1817
|
"ui-report__cover",
|
|
1712
1818
|
"ui-report__cover--compact",
|
|
1819
|
+
"ui-report__decision",
|
|
1820
|
+
"ui-report__decision-body",
|
|
1821
|
+
"ui-report__decision-grid",
|
|
1822
|
+
"ui-report__decision-item",
|
|
1823
|
+
"ui-report__decision-kicker",
|
|
1824
|
+
"ui-report__decision-label",
|
|
1825
|
+
"ui-report__decision-meta",
|
|
1826
|
+
"ui-report__decision-title",
|
|
1827
|
+
"ui-report__decision-value",
|
|
1713
1828
|
"ui-report__evidence",
|
|
1714
1829
|
"ui-report__figure",
|
|
1715
1830
|
"ui-report__finding",
|
|
1831
|
+
"ui-report__finding--critical",
|
|
1832
|
+
"ui-report__finding--major",
|
|
1833
|
+
"ui-report__finding--minor",
|
|
1834
|
+
"ui-report__finding--resolved",
|
|
1835
|
+
"ui-report__finding-caveat",
|
|
1836
|
+
"ui-report__finding-claim",
|
|
1837
|
+
"ui-report__finding-evidence",
|
|
1838
|
+
"ui-report__finding-impact",
|
|
1839
|
+
"ui-report__finding-remediation",
|
|
1840
|
+
"ui-report__finding-title",
|
|
1716
1841
|
"ui-report__footnotes",
|
|
1717
1842
|
"ui-report__head",
|
|
1718
1843
|
"ui-report__meta",
|
|
@@ -1908,6 +2033,12 @@
|
|
|
1908
2033
|
"scope": ".ui-tab and other selectable items",
|
|
1909
2034
|
"effect": "active/selected state"
|
|
1910
2035
|
},
|
|
2036
|
+
{
|
|
2037
|
+
"class": "is-source-active",
|
|
2038
|
+
"scope": ".ui-source-card",
|
|
2039
|
+
"effect": "temporary source highlight after a citation/backref activation",
|
|
2040
|
+
"managed": "runtime"
|
|
2041
|
+
},
|
|
1911
2042
|
{
|
|
1912
2043
|
"class": "is-inactive",
|
|
1913
2044
|
"scope": "interactive .ui-legend__item",
|
|
@@ -2378,6 +2509,19 @@
|
|
|
2378
2509
|
"behavior": "initCommand",
|
|
2379
2510
|
"note": "wires the filter input + active-option keyboard model"
|
|
2380
2511
|
},
|
|
2512
|
+
{
|
|
2513
|
+
"name": "data-bronto-sources",
|
|
2514
|
+
"on": "a source/citation island",
|
|
2515
|
+
"behavior": "initSources",
|
|
2516
|
+
"note": "scopes citation preview metadata and source-card focus/highlight behavior; the host still owns numbering, fetching, and trust decisions."
|
|
2517
|
+
},
|
|
2518
|
+
{
|
|
2519
|
+
"name": "data-bronto-source-ref",
|
|
2520
|
+
"on": "a button/control that references a source card",
|
|
2521
|
+
"value": "id of the source card, with or without a leading #",
|
|
2522
|
+
"behavior": "initSources",
|
|
2523
|
+
"note": "button/control equivalent of a .ui-citation[href=\"#source-id\"]; activation focuses and highlights the referenced source."
|
|
2524
|
+
},
|
|
2381
2525
|
{
|
|
2382
2526
|
"name": "data-bronto-dismiss",
|
|
2383
2527
|
"on": "a button",
|