@ponchia/ui 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +352 -12
- package/MIGRATIONS.json +92 -0
- package/README.md +27 -17
- package/annotations/index.d.ts +280 -0
- package/annotations/index.js +522 -0
- package/behaviors/carousel.js +197 -0
- package/behaviors/combobox.js +195 -0
- package/behaviors/command.js +187 -0
- package/behaviors/connectors.js +96 -0
- package/behaviors/crosshair.js +58 -0
- package/behaviors/dialog.js +73 -0
- package/behaviors/disclosure.js +25 -0
- package/behaviors/dismissible.js +24 -0
- package/behaviors/forms.js +158 -0
- package/behaviors/glyph.js +109 -0
- package/behaviors/index.d.ts +82 -1
- package/behaviors/index.js +18 -1336
- package/behaviors/internal.js +50 -0
- package/behaviors/legend.js +46 -0
- package/behaviors/menu.js +46 -0
- package/behaviors/popover.js +108 -0
- package/behaviors/spotlight.js +53 -0
- package/behaviors/table.js +109 -0
- package/behaviors/tabs.js +103 -0
- package/behaviors/theme.js +82 -0
- package/behaviors/toast.js +152 -0
- package/classes/index.d.ts +318 -0
- package/classes/index.js +352 -0
- package/classes/vscode.css-custom-data.json +18 -14
- package/connectors/index.d.ts +71 -0
- package/connectors/index.js +179 -0
- package/css/analytical.css +21 -0
- package/css/annotations.css +292 -0
- package/css/command.css +97 -0
- package/css/connectors.css +93 -0
- package/css/crosshair.css +100 -0
- package/css/disclosure.css +29 -0
- package/css/dots.css +2 -0
- package/css/feedback.css +104 -0
- package/css/fonts.css +11 -7
- package/css/generated.css +117 -0
- package/css/legend.css +268 -0
- package/css/marks.css +144 -0
- package/css/motion.css +88 -0
- package/css/overlay.css +52 -1
- package/css/primitives.css +18 -0
- package/css/report.css +363 -0
- package/css/selection.css +46 -0
- package/css/sources.css +179 -0
- package/css/spotlight.css +104 -0
- package/css/state.css +121 -0
- package/css/tokens.css +78 -60
- package/css/workbench.css +83 -0
- package/dist/bronto.css +1 -1
- package/dist/css/analytical.css +1 -0
- package/dist/css/annotations.css +1 -0
- package/dist/css/command.css +1 -0
- package/dist/css/connectors.css +1 -0
- package/dist/css/crosshair.css +1 -0
- package/dist/css/disclosure.css +1 -1
- package/dist/css/dots.css +1 -1
- package/dist/css/feedback.css +1 -1
- package/dist/css/fonts.css +1 -1
- package/dist/css/generated.css +1 -0
- package/dist/css/legend.css +1 -0
- package/dist/css/marks.css +1 -0
- package/dist/css/motion.css +1 -1
- package/dist/css/overlay.css +1 -1
- package/dist/css/primitives.css +1 -1
- package/dist/css/report.css +1 -0
- package/dist/css/selection.css +1 -0
- package/dist/css/sources.css +1 -0
- package/dist/css/spotlight.css +1 -0
- package/dist/css/state.css +1 -0
- package/dist/css/tokens.css +1 -1
- package/dist/css/workbench.css +1 -0
- package/docs/adr/0001-color-system.md +26 -27
- package/docs/adr/0002-scope-and-2026-baseline.md +104 -0
- package/docs/adr/0003-theme-model.md +97 -0
- package/docs/annotations.md +345 -0
- package/docs/architecture.md +202 -0
- package/docs/command.md +95 -0
- package/docs/connectors.md +91 -0
- package/docs/contrast.md +42 -42
- package/docs/crosshair.md +63 -0
- package/docs/generated.md +91 -0
- package/docs/legends.md +168 -0
- package/docs/marks.md +86 -0
- package/docs/reference.md +418 -15
- package/docs/reporting.md +305 -0
- package/docs/selection.md +40 -0
- package/docs/sources.md +110 -0
- package/docs/spotlight.md +78 -0
- package/docs/stability.md +52 -0
- package/docs/state.md +85 -0
- package/docs/theming.md +18 -6
- package/docs/usage.md +43 -3
- package/docs/workbench.md +72 -0
- package/fonts/doto-400.woff2 +0 -0
- package/fonts/doto-500.woff2 +0 -0
- package/fonts/doto-600.woff2 +0 -0
- package/fonts/doto-700.woff2 +0 -0
- package/fonts/doto-800.woff2 +0 -0
- package/fonts/doto-900.woff2 +0 -0
- package/llms.txt +288 -8
- package/package.json +95 -5
- package/qwik/index.d.ts +60 -0
- package/qwik/index.js +149 -0
- package/react/index.d.ts +40 -14
- package/react/index.js +32 -5
- package/solid/index.d.ts +40 -14
- package/solid/index.js +31 -3
- package/tokens/index.d.ts +3 -3
- package/tokens/index.js +25 -19
- package/tokens/index.json +32 -28
- package/tokens/resolved.json +34 -32
- package/tokens/tokens.dtcg.json +22 -14
- package/fonts/doto-400.ttf +0 -0
- package/fonts/doto-500.ttf +0 -0
- package/fonts/doto-600.ttf +0 -0
- package/fonts/doto-700.ttf +0 -0
- package/fonts/doto-800.ttf +0 -0
- package/fonts/doto-900.ttf +0 -0
package/README.md
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
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)
|
|
10
10
|
|
|
11
|
-
**A CSS-first
|
|
11
|
+
**A CSS-first design system for interfaces that explain themselves.** Works in plain HTML, every modern framework, and print/PDF — there's no component runtime to adopt. The look is a deliberate stance: a neutral monochrome canvas with **one _rationed_ accent** (colour _signals_, it never decorates), dot-matrix display type and hairline borders, re-skinnable from a single `--accent` knob (opt-in amber-CRT · phosphor-green · e-ink colorways). And beyond the standard component set it ships an opt-in **analytical & report layer** — SVG annotations, legends, leader-line connectors, a guided-focus spotlight, text marks, a colourblind-safe data-viz palette and a static/PDF report grammar — for dashboards and LLM-authored reports. Zero runtime dependencies; re-brand the whole thing with one CSS variable.
|
|
12
12
|
|
|
13
13
|
### [Live demo →](https://ponchia.github.io/bronto-ui/) · [Theme playground →](https://ponchia.github.io/bronto-ui/demo/theme-playground.html)
|
|
14
14
|
|
|
@@ -20,6 +20,8 @@ The demo is the kitchen sink — every component, light/dark, RTL, live theming.
|
|
|
20
20
|
|
|
21
21
|
`@ponchia/ui` ships its design as **CSS**, not components. You drop in one stylesheet and style with semantic `ui-*` classes; an optional thin layer of typed class-name recipes and SSR-safe vanilla behaviors sits on top for the few things that genuinely need JS (theme persistence, dialogs, toasts, disclosure). The guiding principle is **color is rationed, structure carries meaning** — layout, type weight and the hairline do the work before a hue does, and the accent is a spotlight, not a paint bucket. Because everything lives in a single `@layer bronto`, your own un-layered CSS overrides the framework with no specificity fight and no `!important`.
|
|
22
22
|
|
|
23
|
+
It ships a complete, accessible **standard component set** — but that's not where it competes. Its differentiator is an opt-in **analytical & communication layer** for interfaces that make complex work legible: annotations, legends, connectors, marks, a guided-focus spotlight, lifecycle/system-state and source-provenance vocabularies, and a static/PDF report grammar. Each 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.
|
|
24
|
+
|
|
23
25
|
## Install
|
|
24
26
|
|
|
25
27
|
```bash
|
|
@@ -34,7 +36,7 @@ Or drop it in with no build step, straight from a CDN:
|
|
|
34
36
|
|
|
35
37
|
## Quick start
|
|
36
38
|
|
|
37
|
-
**1. Load the CSS.** One flattened, minified bundle — the whole framework, one request (~
|
|
39
|
+
**1. Load the CSS.** One flattened, minified bundle — the whole framework, one request (~76 kB raw / ~13 kB gzip):
|
|
38
40
|
|
|
39
41
|
```css
|
|
40
42
|
@import '@ponchia/ui'; /* via a bundler */
|
|
@@ -79,7 +81,7 @@ toast('Saved', { tone: 'success' }); // body-anchored stack, no markup needed
|
|
|
79
81
|
|
|
80
82
|
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.
|
|
81
83
|
|
|
82
|
-
**5. (Optional) display glyphs — a
|
|
84
|
+
**5. (Optional) display glyphs — a 48-glyph dot-matrix icon set:**
|
|
83
85
|
|
|
84
86
|
```js
|
|
85
87
|
import { renderGlyph } from '@ponchia/ui/glyphs';
|
|
@@ -89,7 +91,7 @@ el.innerHTML = renderGlyph('search', { label: 'Search' }); // role="img"
|
|
|
89
91
|
// import { initDotGlyph } from '@ponchia/ui/behaviors'; initDotGlyph();
|
|
90
92
|
```
|
|
91
93
|
|
|
92
|
-
Arrows, chevrons, check/close/plus/minus, search/menu/gear, info/warning/bell/lock, home/user/heart/star/spark
|
|
94
|
+
Arrows, chevrons, check/close/plus/minus, search/menu/gear, info/warning/bell/lock, home/user/heart/star/spark and circle-family marks are rendered on the same `.ui-dotmatrix` primitive and re-skinned by the `--field-dot*` tokens. Default dot look is for **display** sizes; pass **`{ solid: true }`** to fuse the cells into a crisp pixel glyph that works as an **inline icon down to ~16px**. For dense lists/tables, `renderGlyph(name, { render: 'mask' })` emits one `.ui-icon` element backed by an internal CSS mask.
|
|
93
95
|
|
|
94
96
|
## What's in the box
|
|
95
97
|
|
|
@@ -100,8 +102,10 @@ Arrows, chevrons, check/close/plus/minus, search/menu/gear, info/warning/bell/lo
|
|
|
100
102
|
- **Disclosure & nav** — tabs, accordion, segmented, breadcrumb, pagination, `ui-steps`, `ui-timeline`, `ui-pagehead`, `ui-kbd`.
|
|
101
103
|
- **Shells** — an admin dashboard shell (`ui-app-*`) and a content/marketing site shell (`ui-site*`, `ui-container`).
|
|
102
104
|
- **Prose** — `.ui-prose` styles raw, unclassed semantic HTML (Markdown / CMS / LLM output) with zero classes.
|
|
105
|
+
- **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.
|
|
106
|
+
- **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.
|
|
103
107
|
- **Motion & dots** — the dot-matrix motif kit: dot grid, status dots, dot loaders, the orbital spinner, matrix reveal — all reduced-motion aware.
|
|
104
|
-
- **Glyphs** — `@ponchia/ui/glyphs`, a
|
|
108
|
+
- **Glyphs** — `@ponchia/ui/glyphs`, a 48-glyph dot-matrix icon set on the `.ui-dotmatrix` primitive (display marks + crisp `solid` inline icons + one-node `.ui-icon` mask rendering).
|
|
105
109
|
- **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.
|
|
106
110
|
- **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.
|
|
107
111
|
|
|
@@ -116,7 +120,7 @@ Everything accent-colored derives from a single `--accent` variable via `color-m
|
|
|
116
120
|
.promo { --accent: #16a34a; } /* …or just this section green */
|
|
117
121
|
```
|
|
118
122
|
|
|
119
|
-
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
|
|
123
|
+
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**.
|
|
120
124
|
|
|
121
125
|
**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)**.
|
|
122
126
|
|
|
@@ -128,7 +132,7 @@ Not an afterthought — a gate. Every contractual token pairing has a declared W
|
|
|
128
132
|
|
|
129
133
|
## Works with anything
|
|
130
134
|
|
|
131
|
-
The CSS is the framework, so it works with React, Svelte/SvelteKit, Astro, Vue, Solid 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 and
|
|
135
|
+
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.
|
|
132
136
|
|
|
133
137
|
Per-framework getting-started guides + runnable example apps live in the repo:
|
|
134
138
|
|
|
@@ -137,41 +141,47 @@ Per-framework getting-started guides + runnable example apps live in the repo:
|
|
|
137
141
|
| 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) |
|
|
138
142
|
| 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) |
|
|
139
143
|
| 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) |
|
|
140
|
-
| React
|
|
144
|
+
| 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) |
|
|
145
|
+
| 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) |
|
|
146
|
+
| 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) |
|
|
141
147
|
| Tailwind / cascade-layer interop | [tailwind.md](https://github.com/Ponchia/bronto-ui/blob/main/docs/interop/tailwind.md) | — |
|
|
142
148
|
|
|
143
149
|
## Extras
|
|
144
150
|
|
|
145
151
|
- **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).
|
|
146
|
-
- **Chart colours for dashboards** — `import charts from '@ponchia/ui/charts.json'` (resolved hex per theme; series 1 = your accent)
|
|
152
|
+
- **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`.
|
|
153
|
+
- **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`.
|
|
154
|
+
- **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; }`.
|
|
147
155
|
- **Editor IntelliSense** — point VS Code at the shipped custom-data file so every token autocompletes in `var(--…)`:
|
|
148
156
|
```json
|
|
149
157
|
{ "css.customData": ["node_modules/@ponchia/ui/classes/vscode.css-custom-data.json"] }
|
|
150
158
|
```
|
|
151
|
-
- **For AI coding agents** — the package ships `llms.txt` at its root plus `docs/reference.md`, `docs/usage.md`, `docs/theming.md`, `docs/contrast.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.
|
|
159
|
+
- **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.
|
|
152
160
|
|
|
153
|
-
> The package root is **CSS-only
|
|
161
|
+
> 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`.
|
|
162
|
+
> JS subpaths are **ESM-only**. CommonJS consumers should use dynamic
|
|
163
|
+
> `import('@ponchia/ui/behaviors')`.
|
|
154
164
|
|
|
155
165
|
## Browser support
|
|
156
166
|
|
|
157
|
-
|
|
167
|
+
Recent-evergreen, by design. The framework targets the modern web platform — cascade layers, `:has()`, `color-mix()`/`oklch()`, logical properties, native `<dialog>`, and the 2026 interaction primitives (`@starting-style`, `transition-behavior: allow-discrete`, `light-dark()`). Floor: **Chrome/Edge 125+, Safari 18+, Firefox 129+** (early–mid 2025). No fallback ships below this — pin an older tag if you need it. See [ADR-0002](https://github.com/Ponchia/bronto-ui/blob/main/docs/adr/0002-scope-and-2026-baseline.md) for the scope/greenfield rationale.
|
|
158
168
|
|
|
159
169
|
## Versioning
|
|
160
170
|
|
|
161
|
-
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.
|
|
171
|
+
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.5.0` (and equivalently `^0.5.0`) resolves to `>=0.5.0 <0.6.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.
|
|
162
172
|
|
|
163
|
-
Contractual (changes are breaking):
|
|
173
|
+
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 full public-surface matrix.
|
|
164
174
|
|
|
165
175
|
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.
|
|
166
176
|
|
|
167
177
|
## Links
|
|
168
178
|
|
|
169
179
|
- **[Live demo](https://ponchia.github.io/bronto-ui/)** · **[Theme playground](https://ponchia.github.io/bronto-ui/demo/theme-playground.html)**
|
|
170
|
-
- **[Class reference](https://github.com/Ponchia/bronto-ui/blob/main/docs/reference.md)** · **[Usage guide](https://github.com/Ponchia/bronto-ui/blob/main/docs/usage.md)** · **[Theming](https://github.com/Ponchia/bronto-ui/blob/main/docs/theming.md)** · **[Contrast](https://github.com/Ponchia/bronto-ui/blob/main/docs/contrast.md)** · **[Color system (ADR-0001)](https://github.com/Ponchia/bronto-ui/blob/main/docs/adr/0001-color-system.md)**
|
|
180
|
+
- **[Class reference](https://github.com/Ponchia/bronto-ui/blob/main/docs/reference.md)** · **[Usage guide](https://github.com/Ponchia/bronto-ui/blob/main/docs/usage.md)** · **[Theming](https://github.com/Ponchia/bronto-ui/blob/main/docs/theming.md)** · **[Contrast](https://github.com/Ponchia/bronto-ui/blob/main/docs/contrast.md)** · **[Color system (ADR-0001)](https://github.com/Ponchia/bronto-ui/blob/main/docs/adr/0001-color-system.md)** · **[Scope & 2026 baseline (ADR-0002)](https://github.com/Ponchia/bronto-ui/blob/main/docs/adr/0002-scope-and-2026-baseline.md)**
|
|
171
181
|
- **[CHANGELOG](https://github.com/Ponchia/bronto-ui/blob/main/CHANGELOG.md)** · **[Roadmap](https://github.com/Ponchia/bronto-ui/blob/main/ROADMAP.md)** · **[Contributing](https://github.com/Ponchia/bronto-ui/blob/main/CONTRIBUTING.md)**
|
|
172
182
|
|
|
173
183
|
## License
|
|
174
184
|
|
|
175
185
|
[MIT](https://github.com/Ponchia/bronto-ui/blob/main/LICENSE) © Ponchia.
|
|
176
186
|
|
|
177
|
-
The bundled **Doto** font (`fonts/*.
|
|
187
|
+
The bundled **Doto** font (`fonts/*.woff2`) is © 2024 The Doto Project Authors and licensed separately under the [SIL Open Font License 1.1](https://github.com/Ponchia/bronto-ui/blob/main/fonts/OFL.txt) — see `fonts/OFL.txt`.
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/** @ponchia/ui — SVG annotation geometry helpers. */
|
|
2
|
+
|
|
3
|
+
export interface AnnotationPoint {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface AnnotationOffset {
|
|
9
|
+
dx: number;
|
|
10
|
+
dy: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type AnnotationConnectorType = 'callout' | 'elbow' | 'curve';
|
|
14
|
+
export type AnnotationAlign = 'start' | 'middle' | 'end';
|
|
15
|
+
export type AnnotationValign = 'top' | 'middle' | 'bottom';
|
|
16
|
+
export type AxisOrientation = 'horizontal' | 'vertical';
|
|
17
|
+
export type TimelineDirection = 'up' | 'down' | 'left' | 'right';
|
|
18
|
+
|
|
19
|
+
export interface CircleSubject {
|
|
20
|
+
type: 'circle';
|
|
21
|
+
radius: number;
|
|
22
|
+
radiusPadding?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface RectSubject {
|
|
26
|
+
type: 'rect';
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
x?: number;
|
|
30
|
+
y?: number;
|
|
31
|
+
padding?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type ConnectorSubject = CircleSubject | RectSubject;
|
|
35
|
+
|
|
36
|
+
export interface ConnectorOptions extends AnnotationOffset {
|
|
37
|
+
subject?: ConnectorSubject;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface CircleSubjectOptions {
|
|
41
|
+
radius: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface RectSubjectOptions {
|
|
45
|
+
width: number;
|
|
46
|
+
height: number;
|
|
47
|
+
x?: number;
|
|
48
|
+
y?: number;
|
|
49
|
+
padding?: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ThresholdOptions {
|
|
53
|
+
x1?: number;
|
|
54
|
+
y1?: number;
|
|
55
|
+
x2: number;
|
|
56
|
+
y2: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface AxisThresholdOptions {
|
|
60
|
+
orientation?: AxisOrientation;
|
|
61
|
+
value?: number;
|
|
62
|
+
start?: number;
|
|
63
|
+
end: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface BracketSubjectOptions {
|
|
67
|
+
x1: number;
|
|
68
|
+
y1: number;
|
|
69
|
+
x2: number;
|
|
70
|
+
y2: number;
|
|
71
|
+
depth?: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface BandSubjectOptions {
|
|
75
|
+
x?: number;
|
|
76
|
+
y?: number;
|
|
77
|
+
width: number;
|
|
78
|
+
height: number;
|
|
79
|
+
padding?: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface SlopeSubjectOptions {
|
|
83
|
+
x1: number;
|
|
84
|
+
y1: number;
|
|
85
|
+
x2: number;
|
|
86
|
+
y2: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface ComparisonBraceOptions {
|
|
90
|
+
x1: number;
|
|
91
|
+
y1: number;
|
|
92
|
+
x2: number;
|
|
93
|
+
y2: number;
|
|
94
|
+
depth?: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface OutlierClusterOptions {
|
|
98
|
+
points: AnnotationPoint[];
|
|
99
|
+
radius?: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface TimelineEventOptions {
|
|
103
|
+
size?: number;
|
|
104
|
+
direction?: TimelineDirection;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface EvidenceMarkerOptions {
|
|
108
|
+
x?: number;
|
|
109
|
+
y?: number;
|
|
110
|
+
width?: number;
|
|
111
|
+
height?: number;
|
|
112
|
+
padding?: number;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface ConnectorEndDotOptions extends AnnotationPoint {
|
|
116
|
+
radius?: number;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface ConnectorEndArrowOptions {
|
|
120
|
+
x1?: number;
|
|
121
|
+
y1?: number;
|
|
122
|
+
x2: number;
|
|
123
|
+
y2: number;
|
|
124
|
+
size?: number;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface NoteTransformOptions {
|
|
128
|
+
dx?: number;
|
|
129
|
+
dy?: number;
|
|
130
|
+
x?: number;
|
|
131
|
+
y?: number;
|
|
132
|
+
align?: AnnotationAlign;
|
|
133
|
+
valign?: AnnotationValign;
|
|
134
|
+
width?: number;
|
|
135
|
+
height?: number;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface AnnotationBounds {
|
|
139
|
+
x?: number;
|
|
140
|
+
y?: number;
|
|
141
|
+
width: number;
|
|
142
|
+
height: number;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface NotePlacementOptions {
|
|
146
|
+
x?: number;
|
|
147
|
+
y?: number;
|
|
148
|
+
width: number;
|
|
149
|
+
height: number;
|
|
150
|
+
bounds: AnnotationBounds;
|
|
151
|
+
padding?: number;
|
|
152
|
+
gap?: number;
|
|
153
|
+
preferred?: 'right' | 'left' | 'top' | 'bottom';
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface NotePlacement {
|
|
157
|
+
dx: number;
|
|
158
|
+
dy: number;
|
|
159
|
+
align: AnnotationAlign;
|
|
160
|
+
valign: AnnotationValign;
|
|
161
|
+
transform: string;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export type AnnotationPartsSubject =
|
|
165
|
+
| CircleSubject
|
|
166
|
+
| RectSubject
|
|
167
|
+
| ({ type: 'threshold' } & ThresholdOptions)
|
|
168
|
+
| ({ type: 'bracket' } & BracketSubjectOptions)
|
|
169
|
+
| ({ type: 'band' } & BandSubjectOptions)
|
|
170
|
+
| ({ type: 'slope' } & SlopeSubjectOptions)
|
|
171
|
+
| ({ type: 'compare' } & ComparisonBraceOptions)
|
|
172
|
+
| ({ type: 'cluster' } & OutlierClusterOptions)
|
|
173
|
+
| ({ type: 'axis' } & AxisThresholdOptions)
|
|
174
|
+
| ({ type: 'timeline' } & TimelineEventOptions)
|
|
175
|
+
| ({ type: 'evidence' } & EvidenceMarkerOptions);
|
|
176
|
+
|
|
177
|
+
export interface AnnotationPartsOptions {
|
|
178
|
+
type?: AnnotationConnectorType;
|
|
179
|
+
x?: number;
|
|
180
|
+
y?: number;
|
|
181
|
+
dx?: number;
|
|
182
|
+
dy?: number;
|
|
183
|
+
subject?: AnnotationPartsSubject;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface AnnotationParts {
|
|
187
|
+
transform: string;
|
|
188
|
+
subject: string;
|
|
189
|
+
connector: string;
|
|
190
|
+
note: string;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export declare function annotationTransform(point?: Partial<AnnotationPoint>): string;
|
|
194
|
+
export declare function noteTransform(options?: NoteTransformOptions): string;
|
|
195
|
+
export declare function notePlacement(options: NotePlacementOptions): NotePlacement;
|
|
196
|
+
export declare function circleSubjectPath(options: CircleSubjectOptions): string;
|
|
197
|
+
export declare function rectSubjectPath(options: RectSubjectOptions): string;
|
|
198
|
+
export declare function thresholdPath(options: ThresholdOptions): string;
|
|
199
|
+
export declare function axisThresholdPath(options: AxisThresholdOptions): string;
|
|
200
|
+
export declare function bracketSubjectPath(options: BracketSubjectOptions): string;
|
|
201
|
+
export declare function bandSubjectPath(options: BandSubjectOptions): string;
|
|
202
|
+
export declare function slopeSubjectPath(options: SlopeSubjectOptions): string;
|
|
203
|
+
export declare function comparisonBracePath(options: ComparisonBraceOptions): string;
|
|
204
|
+
export declare function outlierClusterPath(options: OutlierClusterOptions): string;
|
|
205
|
+
export declare function timelineEventPath(options?: TimelineEventOptions): string;
|
|
206
|
+
export declare function evidenceMarkerPath(options?: EvidenceMarkerOptions): string;
|
|
207
|
+
export declare function connectorEndDot(options: ConnectorEndDotOptions): string;
|
|
208
|
+
export declare function connectorEndArrow(options: ConnectorEndArrowOptions): string;
|
|
209
|
+
export declare function connectorLine(options: ConnectorOptions): string;
|
|
210
|
+
export declare function connectorElbow(options: ConnectorOptions): string;
|
|
211
|
+
export declare function connectorCurve(options: ConnectorOptions): string;
|
|
212
|
+
export declare function annotationParts(options?: AnnotationPartsOptions): AnnotationParts;
|
|
213
|
+
|
|
214
|
+
export interface DeclutterLabelItem {
|
|
215
|
+
/** Desired centre coordinate along the axis. */
|
|
216
|
+
pos: number;
|
|
217
|
+
/** The label's extent along the axis. */
|
|
218
|
+
size: number;
|
|
219
|
+
}
|
|
220
|
+
export interface DeclutterLabelsOptions {
|
|
221
|
+
/** Minimum gap kept between adjacent labels. Default 0. */
|
|
222
|
+
gap?: number;
|
|
223
|
+
/** Lower bound of the axis. Default -Infinity. */
|
|
224
|
+
min?: number;
|
|
225
|
+
/** Upper bound of the axis. Default Infinity. */
|
|
226
|
+
max?: number;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* 1-D label declutter: nudge overlapping labels apart, order-preserving and
|
|
230
|
+
* deterministic. Returns the adjusted centre per input item (input order). Not
|
|
231
|
+
* a general 2-D collision solver.
|
|
232
|
+
*/
|
|
233
|
+
export declare function declutterLabels(
|
|
234
|
+
items: DeclutterLabelItem[],
|
|
235
|
+
opts?: DeclutterLabelsOptions,
|
|
236
|
+
): number[];
|
|
237
|
+
|
|
238
|
+
export interface DirectLabelItem {
|
|
239
|
+
/** The true data point the label refers to (figure coordinates). */
|
|
240
|
+
anchor: AnnotationPoint;
|
|
241
|
+
/** The label's extent along the layout axis. */
|
|
242
|
+
size: number;
|
|
243
|
+
/** Optional identifier, echoed back on the matching output (input order). */
|
|
244
|
+
key?: string | number;
|
|
245
|
+
}
|
|
246
|
+
export interface DirectLabelsOptions {
|
|
247
|
+
/** Axis the labels declutter along. 'y' = a vertical column. Default 'y'. */
|
|
248
|
+
axis?: 'x' | 'y';
|
|
249
|
+
/** Fixed coordinate on the other axis where the label column/row sits. Default 0. */
|
|
250
|
+
cross?: number;
|
|
251
|
+
/** Minimum gap kept between adjacent labels. Default 0. */
|
|
252
|
+
gap?: number;
|
|
253
|
+
/** Lower bound of the layout axis. Default -Infinity. */
|
|
254
|
+
min?: number;
|
|
255
|
+
/** Upper bound of the layout axis. Default Infinity. */
|
|
256
|
+
max?: number;
|
|
257
|
+
/** Leader-line shape. Default 'straight'. */
|
|
258
|
+
shape?: 'straight' | 'elbow' | 'curve';
|
|
259
|
+
}
|
|
260
|
+
export interface DirectLabel {
|
|
261
|
+
/** Placed label point — the leader's label-side end. */
|
|
262
|
+
x: number;
|
|
263
|
+
y: number;
|
|
264
|
+
/** The echoed input anchor. */
|
|
265
|
+
anchor: AnnotationPoint;
|
|
266
|
+
/** The echoed input key, if any. */
|
|
267
|
+
key?: string | number;
|
|
268
|
+
/** SVG path for the leader (anchor → label point); '' if they coincide. */
|
|
269
|
+
d: string;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Direct labeling: declutter labels along one axis and draw a leader from each
|
|
273
|
+
* anchor to its placed label (reusing the connector kernel). Deterministic and
|
|
274
|
+
* pure — no scales, no DOM, no 2-D placement. Output feeds a
|
|
275
|
+
* `<path class="ui-annotation__connector">` plus a label at `{x, y}`.
|
|
276
|
+
*/
|
|
277
|
+
export declare function directLabels(
|
|
278
|
+
items: DirectLabelItem[],
|
|
279
|
+
opts?: DirectLabelsOptions,
|
|
280
|
+
): DirectLabel[];
|