@ponchia/ui 0.3.6 → 0.4.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 +945 -0
- package/README.md +16 -6
- package/classes/index.d.ts +1 -0
- package/classes/index.js +1 -0
- package/classes/vscode.css-custom-data.json +4 -12
- package/css/dataviz.css +96 -0
- package/css/dots.css +30 -2
- package/css/skins.css +54 -0
- package/css/tokens.css +4 -10
- package/dist/bronto.css +1 -1
- package/dist/css/dataviz.css +1 -0
- package/dist/css/dots.css +1 -1
- package/dist/css/skins.css +1 -0
- package/dist/css/tokens.css +1 -1
- package/docs/adr/0001-color-system.md +272 -0
- package/docs/contrast.md +170 -51
- package/docs/reference.md +11 -9
- package/docs/theming.md +66 -1
- package/docs/usage.md +46 -5
- package/glyphs/glyphs.d.ts +14 -1
- package/glyphs/glyphs.js +143 -2
- package/llms.txt +43 -4
- package/package.json +54 -5
- package/react/index.d.ts +36 -0
- package/react/index.js +67 -0
- package/solid/index.d.ts +36 -0
- package/solid/index.js +67 -0
- package/tokens/charts.d.ts +37 -0
- package/tokens/charts.js +96 -0
- package/tokens/charts.json +61 -0
- package/tokens/index.d.ts +3 -3
- package/tokens/index.js +4 -8
- package/tokens/index.json +8 -16
- package/tokens/resolved.json +9 -13
- package/tokens/skins.d.ts +27 -0
- package/tokens/skins.js +62 -0
- package/tokens/tokens.dtcg.json +4 -24
package/docs/usage.md
CHANGED
|
@@ -198,11 +198,52 @@ A few sharp edges to know:
|
|
|
198
198
|
- **Directional glyphs are physical, not logical.** `arrow-left/right`,
|
|
199
199
|
`chevron-left/right` are fixed bitmaps; in an RTL context flip them yourself
|
|
200
200
|
(e.g. swap the name, or `transform: scaleX(-1)`), the framework won't.
|
|
201
|
-
- **Cost.**
|
|
202
|
-
regardless of
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
201
|
+
- **Cost / icon-at-scale.** The default (cell) render is a 16×16 grid = 256
|
|
202
|
+
cells (DOM nodes), regardless of `solid`/`grid`; `anim: 'reveal'` adds a
|
|
203
|
+
per-cell `--i`. That's the dot-matrix display look — but for **many** icons
|
|
204
|
+
(one in every row of a long table) use **`renderGlyph(name, { render: 'mask' })`**:
|
|
205
|
+
it returns a **single** `.ui-icon` element masked by the bitmap (one node, not
|
|
206
|
+
256), sizes to `size` / `--icon-size` (default `1em`) and inherits
|
|
207
|
+
`currentColor` — a normal inline icon. Pick `render: 'mask'` for icons,
|
|
208
|
+
the cell render for display marks/animation.
|
|
209
|
+
|
|
210
|
+
## Colorways: when to reach for a skin
|
|
211
|
+
|
|
212
|
+
`@ponchia/ui/css/skins.css` adds `data-bronto-skin="amber-crt |
|
|
213
|
+
phosphor-green | e-ink"` — a **root-level** colorway (apply on `<html>`, like
|
|
214
|
+
`data-theme`) that re-points the one accent to a different single hue.
|
|
215
|
+
|
|
216
|
+
- **Use a skin** when you want a distinct, on-brand _look_ (a phosphor/CRT or
|
|
217
|
+
e-ink feel) for the whole page or app — it's the supported, contrast-gated
|
|
218
|
+
way to recolour without leaving the design system.
|
|
219
|
+
- **Use a raw `--accent` override** when you just need _your_ brand hue: it's
|
|
220
|
+
one declaration (see "Re-brand obligations" below) — but then contrast is
|
|
221
|
+
yours, whereas the shipped skins are pre-gated.
|
|
222
|
+
- **Don't** put `data-bronto-skin` on a subtree — it's root-level by design
|
|
223
|
+
(the derived accent family only recomputes at `:root`); a subtree skin
|
|
224
|
+
no-ops. For a one-section recolour, scope a raw `--accent` override instead.
|
|
225
|
+
- It's **opt-in**: a separate stylesheet, never in `dist/bronto.css`. No skin
|
|
226
|
+
imported → zero cost. Full detail in [theming.md](theming.md) → "Display
|
|
227
|
+
colorways".
|
|
228
|
+
|
|
229
|
+
## Data-viz colours: charts, not chrome
|
|
230
|
+
|
|
231
|
+
`@ponchia/ui/css/dataviz.css` (opt-in) adds a Tier-4 chart palette for
|
|
232
|
+
dashboards: `--chart-1..8` (categorical), `--chart-seq-*` (sequential),
|
|
233
|
+
`--chart-div-*` (diverging), and `--chart-pattern-1..8` (dot-matrix fills).
|
|
234
|
+
|
|
235
|
+
- **Use it for charts only.** These are not UI tokens — a build gate fails if
|
|
236
|
+
`var(--chart-*)` appears in component CSS. Style buttons/badges with the
|
|
237
|
+
accent/status tiers, not chart colours.
|
|
238
|
+
- **Series 1 is the accent**, so your brand leads the palette; series 2–8 are a
|
|
239
|
+
colourblind-safe set (gated for distinctness under protan/deutan/tritan).
|
|
240
|
+
- **Always pair colour with pattern** (`--chart-pattern-N`) and/or a direct
|
|
241
|
+
label — never colour alone (WCAG 1.4.1):
|
|
242
|
+
`background: var(--chart-3); background-image: var(--chart-pattern-3); background-size: var(--chart-pattern-size);`
|
|
243
|
+
- **In JS** (Chart.js, canvas, SVG): import resolved hex from
|
|
244
|
+
`@ponchia/ui/charts.json` (`{ light, dark }`, series 1 = the resolved accent).
|
|
245
|
+
Cap a chart at ~8 series. Full detail in [theming.md](theming.md) →
|
|
246
|
+
"Data-viz palette".
|
|
206
247
|
|
|
207
248
|
## When to add a behavior
|
|
208
249
|
|
package/glyphs/glyphs.d.ts
CHANGED
|
@@ -10,10 +10,12 @@ export type GlyphName =
|
|
|
10
10
|
| 'arrow-up'
|
|
11
11
|
| 'bell'
|
|
12
12
|
| 'check'
|
|
13
|
+
| 'check-circle'
|
|
13
14
|
| 'chevron-down'
|
|
14
15
|
| 'chevron-left'
|
|
15
16
|
| 'chevron-right'
|
|
16
17
|
| 'chevron-up'
|
|
18
|
+
| 'circle'
|
|
17
19
|
| 'clock'
|
|
18
20
|
| 'close'
|
|
19
21
|
| 'download'
|
|
@@ -32,12 +34,14 @@ export type GlyphName =
|
|
|
32
34
|
| 'mail'
|
|
33
35
|
| 'menu'
|
|
34
36
|
| 'minus'
|
|
37
|
+
| 'minus-circle'
|
|
35
38
|
| 'moon'
|
|
36
39
|
| 'more-horizontal'
|
|
37
40
|
| 'more-vertical'
|
|
38
41
|
| 'pause'
|
|
39
42
|
| 'play'
|
|
40
43
|
| 'plus'
|
|
44
|
+
| 'plus-circle'
|
|
41
45
|
| 'refresh'
|
|
42
46
|
| 'search'
|
|
43
47
|
| 'spark'
|
|
@@ -46,7 +50,8 @@ export type GlyphName =
|
|
|
46
50
|
| 'trash'
|
|
47
51
|
| 'upload'
|
|
48
52
|
| 'user'
|
|
49
|
-
| 'warning'
|
|
53
|
+
| 'warning'
|
|
54
|
+
| 'x-circle';
|
|
50
55
|
|
|
51
56
|
/** A glyph name, or any string — for dynamic dispatch (a CMS/config value). The
|
|
52
57
|
* known names still autocomplete; an unknown name hits the runtime fallback
|
|
@@ -81,6 +86,14 @@ export interface RenderGlyphOptions {
|
|
|
81
86
|
/** CSS length for the gap between dots (sets `--dotmatrix-gap`; sanitized
|
|
82
87
|
* the same way as `dot`). */
|
|
83
88
|
gap?: string;
|
|
89
|
+
/** `'mask'` returns a single `.ui-icon` element masked by the glyph bitmap
|
|
90
|
+
* (one DOM node, not GLYPH_SIZE²) — the icon-at-scale path. Inherits
|
|
91
|
+
* `currentColor`; the cell-mode options above don't apply. Needs the
|
|
92
|
+
* `.ui-icon` rule from `@ponchia/ui/css`. */
|
|
93
|
+
render?: 'mask';
|
|
94
|
+
/** With `render: 'mask'`, the icon size (sets `--icon-size`; defaults to
|
|
95
|
+
* `1em`; sanitized to a length/calc allowlist). */
|
|
96
|
+
size?: string;
|
|
84
97
|
}
|
|
85
98
|
|
|
86
99
|
/** The grid edge length (rows = cols = 16). */
|
package/glyphs/glyphs.js
CHANGED
|
@@ -25,6 +25,96 @@ export const GLYPH_SIZE = 16;
|
|
|
25
25
|
// `.` off · `#` hot · `*` accent. Only `spark` uses accent dots — it is the
|
|
26
26
|
// canonical two-tone demo; the gate in check-glyphs.mjs enforces the shape.
|
|
27
27
|
const RAW = {
|
|
28
|
+
circle: [
|
|
29
|
+
'................',
|
|
30
|
+
'.....######.....',
|
|
31
|
+
'....########....',
|
|
32
|
+
'...###....###...',
|
|
33
|
+
'..##........##..',
|
|
34
|
+
'.###........###.',
|
|
35
|
+
'.##..........##.',
|
|
36
|
+
'.##..........##.',
|
|
37
|
+
'.##..........##.',
|
|
38
|
+
'.##..........##.',
|
|
39
|
+
'.###........###.',
|
|
40
|
+
'..##........##..',
|
|
41
|
+
'...###....###...',
|
|
42
|
+
'....########....',
|
|
43
|
+
'.....######.....',
|
|
44
|
+
'................',
|
|
45
|
+
],
|
|
46
|
+
'check-circle': [
|
|
47
|
+
'................',
|
|
48
|
+
'.....######.....',
|
|
49
|
+
'....########....',
|
|
50
|
+
'...###....###...',
|
|
51
|
+
'..##........##..',
|
|
52
|
+
'.###........###.',
|
|
53
|
+
'.##........####.',
|
|
54
|
+
'.##..##...##.##.',
|
|
55
|
+
'.##...##.##..##.',
|
|
56
|
+
'.##....###...##.',
|
|
57
|
+
'.###...##...###.',
|
|
58
|
+
'..##........##..',
|
|
59
|
+
'...###....###...',
|
|
60
|
+
'....########....',
|
|
61
|
+
'.....######.....',
|
|
62
|
+
'................',
|
|
63
|
+
],
|
|
64
|
+
'x-circle': [
|
|
65
|
+
'................',
|
|
66
|
+
'.....######.....',
|
|
67
|
+
'....########....',
|
|
68
|
+
'...###....###...',
|
|
69
|
+
'..##........##..',
|
|
70
|
+
'.###.##..##.###.',
|
|
71
|
+
'.##...####...##.',
|
|
72
|
+
'.##....##....##.',
|
|
73
|
+
'.##...####...##.',
|
|
74
|
+
'.##..##..##..##.',
|
|
75
|
+
'.#####....#####.',
|
|
76
|
+
'..##........##..',
|
|
77
|
+
'...###....###...',
|
|
78
|
+
'....########....',
|
|
79
|
+
'.....######.....',
|
|
80
|
+
'................',
|
|
81
|
+
],
|
|
82
|
+
'plus-circle': [
|
|
83
|
+
'................',
|
|
84
|
+
'.....######.....',
|
|
85
|
+
'....########....',
|
|
86
|
+
'...###....###...',
|
|
87
|
+
'..##........##..',
|
|
88
|
+
'.###...##...###.',
|
|
89
|
+
'.##....##....##.',
|
|
90
|
+
'.##..######..##.',
|
|
91
|
+
'.##..######..##.',
|
|
92
|
+
'.##....##....##.',
|
|
93
|
+
'.###...##...###.',
|
|
94
|
+
'..##........##..',
|
|
95
|
+
'...###....###...',
|
|
96
|
+
'....########....',
|
|
97
|
+
'.....######.....',
|
|
98
|
+
'................',
|
|
99
|
+
],
|
|
100
|
+
'minus-circle': [
|
|
101
|
+
'................',
|
|
102
|
+
'.....######.....',
|
|
103
|
+
'....########....',
|
|
104
|
+
'...###....###...',
|
|
105
|
+
'..##........##..',
|
|
106
|
+
'.###........###.',
|
|
107
|
+
'.##..........##.',
|
|
108
|
+
'.##..######..##.',
|
|
109
|
+
'.##..######..##.',
|
|
110
|
+
'.##..........##.',
|
|
111
|
+
'.###........###.',
|
|
112
|
+
'..##........##..',
|
|
113
|
+
'...###....###...',
|
|
114
|
+
'....########....',
|
|
115
|
+
'.....######.....',
|
|
116
|
+
'................',
|
|
117
|
+
],
|
|
28
118
|
'arrow-down': [
|
|
29
119
|
'................',
|
|
30
120
|
'......####......',
|
|
@@ -860,6 +950,40 @@ function cssLen(v) {
|
|
|
860
950
|
return /^[\w.%+\-*/()\s,]+$/.test(v) ? v : '';
|
|
861
951
|
}
|
|
862
952
|
|
|
953
|
+
/**
|
|
954
|
+
* Build a CSS `mask-image` `url()` of an inline SVG for a glyph's lit cells —
|
|
955
|
+
* the basis of the one-node `render: 'mask'` path. Horizontal runs are merged
|
|
956
|
+
* into single `<rect>`s (fewer nodes, no seams). The SVG is alpha-masked, so
|
|
957
|
+
* the element's `currentColor` background shows through only the lit cells —
|
|
958
|
+
* one DOM node instead of GLYPH_SIZE² (256), for an icon at any size/colour.
|
|
959
|
+
*/
|
|
960
|
+
function maskUrl(rows) {
|
|
961
|
+
let rects = '';
|
|
962
|
+
rows.forEach((row, y) => {
|
|
963
|
+
let run = 0;
|
|
964
|
+
for (let x = 0; x <= GLYPH_SIZE; x++) {
|
|
965
|
+
const on = x < GLYPH_SIZE && row[x] !== '.';
|
|
966
|
+
if (on) run++;
|
|
967
|
+
else if (run) {
|
|
968
|
+
rects += `<rect x='${x - run}' y='${y}' width='${run}' height='1'/>`;
|
|
969
|
+
run = 0;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
// The url() lands unquoted inside an HTML `style="…"` attribute, so it must
|
|
974
|
+
// carry no spaces or quotes of its own — encode them (and `<>#`) so it stays
|
|
975
|
+
// a single CSS url-token and can't break out of the attribute.
|
|
976
|
+
const svg = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${GLYPH_SIZE} ${GLYPH_SIZE}'>${rects}</svg>`;
|
|
977
|
+
const enc = svg
|
|
978
|
+
.replace(/%/g, '%25')
|
|
979
|
+
.replace(/</g, '%3C')
|
|
980
|
+
.replace(/>/g, '%3E')
|
|
981
|
+
.replace(/#/g, '%23')
|
|
982
|
+
.replace(/'/g, '%27')
|
|
983
|
+
.replace(/ /g, '%20');
|
|
984
|
+
return `url(data:image/svg+xml,${enc})`;
|
|
985
|
+
}
|
|
986
|
+
|
|
863
987
|
/**
|
|
864
988
|
* A full `.ui-dotmatrix` HTML string for a glyph (`''` if the name is
|
|
865
989
|
* unknown). Decorative by default (`aria-hidden`); pass `label` to expose it
|
|
@@ -875,11 +999,28 @@ function cssLen(v) {
|
|
|
875
999
|
* `anim` opts into a decorative animation (disabled under reduced-motion;
|
|
876
1000
|
* the static frame + `label` still carry the meaning): `'reveal'` powers the
|
|
877
1001
|
* cells on in a scan, `'pulse'` makes the glyph breathe.
|
|
1002
|
+
*
|
|
1003
|
+
* `render: 'mask'` returns a single `.ui-icon` element masked by the glyph
|
|
1004
|
+
* bitmap (one DOM node, not GLYPH_SIZE²) — the icon-at-scale path: it sizes to
|
|
1005
|
+
* `size` (or `--icon-size` / `1em`) and inherits `currentColor`. The
|
|
1006
|
+
* cell-mode options (grid/solid/anim/dot/gap) don't apply; `label` does.
|
|
1007
|
+
* Needs `@ponchia/ui/css` (the `.ui-icon` rule).
|
|
878
1008
|
*/
|
|
879
1009
|
export function renderGlyph(name, options = {}) {
|
|
1010
|
+
const rows = GLYPHS[name];
|
|
1011
|
+
if (!rows) return '';
|
|
1012
|
+
const { grid = true, solid = false, anim, label, dot, gap, render, size } = options;
|
|
1013
|
+
|
|
1014
|
+
// One-node icon: a single `.ui-icon` span masked by the glyph's bitmap, so
|
|
1015
|
+
// it scales to any font-size and inherits `currentColor` — for icon-at-scale
|
|
1016
|
+
// (e.g. one in every table row) where the GLYPH_SIZE²-cell path is too heavy.
|
|
1017
|
+
if (render === 'mask') {
|
|
1018
|
+
const a11yM = label ? `role="img" aria-label="${esc(label)}"` : 'aria-hidden="true"';
|
|
1019
|
+
const sz = size && cssLen(size) ? `--icon-size:${cssLen(size)};` : '';
|
|
1020
|
+
return `<span class="ui-icon" style="${sz}--icon-mask:${maskUrl(rows)}" ${a11yM}></span>`;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
880
1023
|
const cells = glyphCells(name);
|
|
881
|
-
if (!cells.length) return '';
|
|
882
|
-
const { grid = true, solid = false, anim, label, dot, gap } = options;
|
|
883
1024
|
|
|
884
1025
|
const style = [`--dotmatrix-cols:${GLYPH_SIZE}`];
|
|
885
1026
|
const dotLen = dot && cssLen(dot);
|
package/llms.txt
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
> CSS-first, framework-agnostic UI framework. Zero runtime dependencies.
|
|
4
4
|
> One `@layer bronto` cascade, a typed class vocabulary, design tokens as
|
|
5
|
-
> data, and optional SSR-safe vanilla behaviors.
|
|
6
|
-
> monochrome
|
|
5
|
+
> data, and optional SSR-safe vanilla behaviors. Token-driven restraint:
|
|
6
|
+
> monochrome by default, one rationed accent, dot-matrix display type, with
|
|
7
|
+
> opt-in colorways + a colourblind-safe data-viz palette layered on top.
|
|
7
8
|
>
|
|
8
9
|
> This file orients an LLM/agent. The authoritative, always-correct API
|
|
9
10
|
> is the TypeScript declarations shipped in this package (paths below):
|
|
@@ -45,6 +46,13 @@ Optional vanilla behaviors (theme toggle, etc. — SSR-safe, tree-shakeable):
|
|
|
45
46
|
import { applyStoredTheme } from '@ponchia/ui/behaviors';
|
|
46
47
|
```
|
|
47
48
|
|
|
49
|
+
For React/Solid, optional thin hook bindings over those behaviors (peer deps
|
|
50
|
+
`react` / `solid-js`, optional — core stays zero-dep):
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
import { useDialog, useToast } from '@ponchia/ui/react'; // or '@ponchia/ui/solid'
|
|
54
|
+
```
|
|
55
|
+
|
|
48
56
|
Optional display glyphs — dot-matrix bitmaps on the `.ui-dotmatrix` primitive
|
|
49
57
|
(decorative by default; `renderGlyph` is SSR-safe, `initDotGlyph` is the DOM form):
|
|
50
58
|
|
|
@@ -53,6 +61,34 @@ import { renderGlyph, GLYPH_NAMES } from '@ponchia/ui/glyphs';
|
|
|
53
61
|
el.innerHTML = renderGlyph('check', { label: 'Done' });
|
|
54
62
|
```
|
|
55
63
|
|
|
64
|
+
Optional display colorways — opt-in, never in the default bundle. Root-level,
|
|
65
|
+
like `data-theme` (the derived accent family only recomputes at `:root`):
|
|
66
|
+
|
|
67
|
+
```html
|
|
68
|
+
<link rel="stylesheet" href="@ponchia/ui/css/skins.css" />
|
|
69
|
+
<html data-bronto-skin="amber-crt | phosphor-green | e-ink">
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Each re-points the one `--accent` (OKLCH, per-theme, contrast-gated); status
|
|
73
|
+
colours and the neutral canvas are untouched. Details in `docs/theming.md`.
|
|
74
|
+
|
|
75
|
+
Optional data-viz palette for dashboards — opt-in, charts-only (never UI
|
|
76
|
+
chrome), never in the default bundle:
|
|
77
|
+
|
|
78
|
+
```html
|
|
79
|
+
<link rel="stylesheet" href="@ponchia/ui/css/dataviz.css" />
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
import charts from '@ponchia/ui/charts.json' with { type: 'json' };
|
|
84
|
+
// charts.dark.categorical → ['#ff3b41', …] (series 0 = the resolved accent)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`--chart-1..8` (categorical; series 1 = accent; colourblind-safe, gated under
|
|
88
|
+
simulated protan/deutan/tritan), `--chart-seq-*` (sequential), `--chart-div-*`
|
|
89
|
+
(diverging), and `--chart-pattern-1..8` (dot-matrix fills — pair colour N with
|
|
90
|
+
pattern N; colour is never the sole signal). Details in `docs/theming.md`.
|
|
91
|
+
|
|
56
92
|
## Authoritative offline references (shipped in this package)
|
|
57
93
|
|
|
58
94
|
Read these from `node_modules/@ponchia/ui/` — no network needed:
|
|
@@ -97,6 +133,9 @@ Read these from `node_modules/@ponchia/ui/` — no network needed:
|
|
|
97
133
|
- Prefer the `ui.*()` recipes over hand-concatenating modifier strings.
|
|
98
134
|
- Override framework styles by writing your own rules outside
|
|
99
135
|
`@layer bronto` — not with higher specificity or `!important`.
|
|
100
|
-
-
|
|
101
|
-
|
|
136
|
+
- Color is tiered (ADR-0001): neutral canvas · one rationed accent · locked
|
|
137
|
+
status · display expression · opt-in data-viz. Theme via the documented
|
|
138
|
+
tokens — re-point `--accent` (or a `data-bronto-skin` colorway), use status
|
|
139
|
+
tokens for status, and `--chart-*` (from `css/dataviz.css`) for charts only.
|
|
140
|
+
Don't add raw hues to components; `check:color-policy` enforces this.
|
|
102
141
|
- Pre-1.0 SemVer: breaking changes ship in the *minor*. Pin `~0.x`.
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ponchia/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "CSS-first, framework-agnostic UI framework — token-driven restraint (monochrome by default, one rationed accent), OKLCH colorways, a dot-matrix icon set, a colourblind-safe data-viz palette, dot-matrix motifs, zero runtime dependencies.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"css",
|
|
8
8
|
"ui",
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
"css-layers",
|
|
14
14
|
"nothing",
|
|
15
15
|
"monochrome",
|
|
16
|
+
"oklch",
|
|
17
|
+
"colorways",
|
|
18
|
+
"icons",
|
|
19
|
+
"data-visualization",
|
|
20
|
+
"wcag",
|
|
16
21
|
"framework-agnostic",
|
|
17
22
|
"zero-dependencies",
|
|
18
23
|
"dark-mode",
|
|
@@ -41,12 +46,16 @@
|
|
|
41
46
|
"classes",
|
|
42
47
|
"behaviors",
|
|
43
48
|
"glyphs",
|
|
49
|
+
"react",
|
|
50
|
+
"solid",
|
|
44
51
|
"shiki",
|
|
45
52
|
"llms.txt",
|
|
53
|
+
"CHANGELOG.md",
|
|
46
54
|
"docs/reference.md",
|
|
47
55
|
"docs/theming.md",
|
|
48
56
|
"docs/contrast.md",
|
|
49
|
-
"docs/usage.md"
|
|
57
|
+
"docs/usage.md",
|
|
58
|
+
"docs/adr/0001-color-system.md"
|
|
50
59
|
],
|
|
51
60
|
"style": "./dist/bronto.css",
|
|
52
61
|
"scripts": {
|
|
@@ -59,6 +68,8 @@
|
|
|
59
68
|
"resolved:build": "node scripts/gen-resolved.mjs",
|
|
60
69
|
"dts:build": "node scripts/gen-dts.mjs",
|
|
61
70
|
"glyphs:build": "node scripts/gen-glyphs.mjs",
|
|
71
|
+
"skins:build": "node scripts/gen-skins.mjs",
|
|
72
|
+
"charts:build": "node scripts/gen-charts.mjs",
|
|
62
73
|
"reference:build": "node scripts/gen-reference.mjs",
|
|
63
74
|
"contrast:build": "node scripts/gen-contrast.mjs",
|
|
64
75
|
"vscode:build": "node scripts/gen-vscode-data.mjs",
|
|
@@ -68,7 +79,11 @@
|
|
|
68
79
|
"check:classes": "node scripts/check-classes.mjs",
|
|
69
80
|
"check:dts": "node scripts/check-dts.mjs",
|
|
70
81
|
"check:behaviors": "node scripts/check-behaviors.mjs",
|
|
82
|
+
"check:bindings": "node scripts/check-bindings.mjs",
|
|
71
83
|
"check:glyphs": "node scripts/check-glyphs.mjs",
|
|
84
|
+
"check:color-policy": "node scripts/check-color-policy.mjs",
|
|
85
|
+
"check:skins": "node scripts/check-skins.mjs",
|
|
86
|
+
"check:charts": "node scripts/check-charts.mjs",
|
|
72
87
|
"check:types": "tsc -p tsconfig.json",
|
|
73
88
|
"check:dtcg": "node scripts/check-dtcg.mjs",
|
|
74
89
|
"check:resolved": "node scripts/check-resolved.mjs",
|
|
@@ -79,9 +94,9 @@
|
|
|
79
94
|
"check:reference": "node scripts/check-reference.mjs",
|
|
80
95
|
"check:contrast": "node scripts/check-contrast.mjs",
|
|
81
96
|
"check:vscode": "node scripts/check-vscode-data.mjs",
|
|
82
|
-
"check": "npm run lint && npm run check:format && npm run check:exports && npm run check:tokens && npm run check:classes && npm run check:dts && npm run check:types && npm run check:dtcg && npm run check:resolved && npm run check:shiki && npm run check:dist && npm run check:pack && npm run check:release && npm run check:reference && npm run check:contrast && npm run check:vscode && npm run check:behaviors && npm run check:glyphs",
|
|
97
|
+
"check": "npm run lint && npm run check:format && npm run check:exports && npm run check:tokens && npm run check:classes && npm run check:dts && npm run check:types && npm run check:dtcg && npm run check:resolved && npm run check:shiki && npm run check:dist && npm run check:pack && npm run check:release && npm run check:reference && npm run check:contrast && npm run check:vscode && npm run check:behaviors && npm run check:bindings && npm run check:glyphs && npm run check:color-policy && npm run check:skins && npm run check:charts",
|
|
83
98
|
"test": "node --test \"test/*.test.mjs\"",
|
|
84
|
-
"prepack": "npm run tokens:build && npm run dtcg:build && npm run resolved:build && npm run dts:build && npm run reference:build && npm run contrast:build && npm run vscode:build && npm run dist:build && npm run glyphs:build",
|
|
99
|
+
"prepack": "npm run tokens:build && npm run dtcg:build && npm run resolved:build && npm run dts:build && npm run reference:build && npm run contrast:build && npm run vscode:build && npm run skins:build && npm run charts:build && npm run dist:build && npm run glyphs:build",
|
|
85
100
|
"prepublishOnly": "npm run check && npm test"
|
|
86
101
|
},
|
|
87
102
|
"devDependencies": {
|
|
@@ -94,6 +109,18 @@
|
|
|
94
109
|
"stylelint-use-logical": "^2.1.3",
|
|
95
110
|
"typescript": "^6.0.3"
|
|
96
111
|
},
|
|
112
|
+
"peerDependencies": {
|
|
113
|
+
"react": ">=18",
|
|
114
|
+
"solid-js": ">=1.6"
|
|
115
|
+
},
|
|
116
|
+
"peerDependenciesMeta": {
|
|
117
|
+
"react": {
|
|
118
|
+
"optional": true
|
|
119
|
+
},
|
|
120
|
+
"solid-js": {
|
|
121
|
+
"optional": true
|
|
122
|
+
}
|
|
123
|
+
},
|
|
97
124
|
"exports": {
|
|
98
125
|
".": {
|
|
99
126
|
"style": "./dist/bronto.css",
|
|
@@ -117,6 +144,8 @@
|
|
|
117
144
|
"./css/disclosure.css": "./dist/css/disclosure.css",
|
|
118
145
|
"./css/table.css": "./dist/css/table.css",
|
|
119
146
|
"./css/app.css": "./dist/css/app.css",
|
|
147
|
+
"./css/skins.css": "./dist/css/skins.css",
|
|
148
|
+
"./css/dataviz.css": "./dist/css/dataviz.css",
|
|
120
149
|
"./css/unlayered/tokens.css": "./css/tokens.css",
|
|
121
150
|
"./css/unlayered/fonts.css": "./css/fonts.css",
|
|
122
151
|
"./css/unlayered/base.css": "./css/base.css",
|
|
@@ -132,6 +161,8 @@
|
|
|
132
161
|
"./css/unlayered/disclosure.css": "./css/disclosure.css",
|
|
133
162
|
"./css/unlayered/table.css": "./css/table.css",
|
|
134
163
|
"./css/unlayered/app.css": "./css/app.css",
|
|
164
|
+
"./css/unlayered/skins.css": "./css/skins.css",
|
|
165
|
+
"./css/unlayered/dataviz.css": "./css/dataviz.css",
|
|
135
166
|
"./tokens": {
|
|
136
167
|
"types": "./tokens/index.d.ts",
|
|
137
168
|
"default": "./tokens/index.js"
|
|
@@ -146,6 +177,7 @@
|
|
|
146
177
|
"./docs/theming.md": "./docs/theming.md",
|
|
147
178
|
"./docs/contrast.md": "./docs/contrast.md",
|
|
148
179
|
"./docs/usage.md": "./docs/usage.md",
|
|
180
|
+
"./docs/adr/0001-color-system.md": "./docs/adr/0001-color-system.md",
|
|
149
181
|
"./classes": {
|
|
150
182
|
"types": "./classes/index.d.ts",
|
|
151
183
|
"default": "./classes/index.js"
|
|
@@ -158,6 +190,23 @@
|
|
|
158
190
|
"types": "./glyphs/glyphs.d.ts",
|
|
159
191
|
"default": "./glyphs/glyphs.js"
|
|
160
192
|
},
|
|
193
|
+
"./react": {
|
|
194
|
+
"types": "./react/index.d.ts",
|
|
195
|
+
"default": "./react/index.js"
|
|
196
|
+
},
|
|
197
|
+
"./solid": {
|
|
198
|
+
"types": "./solid/index.d.ts",
|
|
199
|
+
"default": "./solid/index.js"
|
|
200
|
+
},
|
|
201
|
+
"./skins": {
|
|
202
|
+
"types": "./tokens/skins.d.ts",
|
|
203
|
+
"default": "./tokens/skins.js"
|
|
204
|
+
},
|
|
205
|
+
"./charts": {
|
|
206
|
+
"types": "./tokens/charts.d.ts",
|
|
207
|
+
"default": "./tokens/charts.js"
|
|
208
|
+
},
|
|
209
|
+
"./charts.json": "./tokens/charts.json",
|
|
161
210
|
"./fonts/*": "./fonts/*"
|
|
162
211
|
}
|
|
163
212
|
}
|
package/react/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** @ponchia/ui/react — thin React bindings over the SSR-safe behaviors.
|
|
2
|
+
* Optional peer dep `react`. Hooks run a delegated behavior for the
|
|
3
|
+
* component's lifetime; they take the same options as the behavior and
|
|
4
|
+
* return void (the cleanup is wired to unmount). See behaviors/index.d.ts. */
|
|
5
|
+
import type {
|
|
6
|
+
Cleanup,
|
|
7
|
+
DelegateOpts,
|
|
8
|
+
ThemeStorageOpts,
|
|
9
|
+
ToastOpts,
|
|
10
|
+
} from '../behaviors/index.js';
|
|
11
|
+
|
|
12
|
+
/** Run any delegated behavior for the component's lifetime (init on mount,
|
|
13
|
+
* its returned cleanup on unmount). The behavior is run once. */
|
|
14
|
+
export declare function useBrontoBehavior(
|
|
15
|
+
init: (opts?: DelegateOpts) => Cleanup | void,
|
|
16
|
+
opts?: DelegateOpts,
|
|
17
|
+
): void;
|
|
18
|
+
|
|
19
|
+
export declare function useThemeToggle(opts?: ThemeStorageOpts & DelegateOpts): void;
|
|
20
|
+
export declare function useDismissible(opts?: DelegateOpts): void;
|
|
21
|
+
export declare function useDisclosure(opts?: DelegateOpts): void;
|
|
22
|
+
export declare function useMenu(opts?: DelegateOpts): void;
|
|
23
|
+
export declare function useFormValidation(opts?: DelegateOpts): void;
|
|
24
|
+
export declare function useCombobox(opts?: DelegateOpts): void;
|
|
25
|
+
export declare function usePopover(opts?: DelegateOpts): void;
|
|
26
|
+
export declare function useTableSort(opts?: DelegateOpts): void;
|
|
27
|
+
export declare function useTabs(opts?: DelegateOpts): void;
|
|
28
|
+
export declare function useDialog(opts?: DelegateOpts): void;
|
|
29
|
+
export declare function useCarousel(opts?: DelegateOpts): void;
|
|
30
|
+
export declare function useDotGlyph(opts?: DelegateOpts): void;
|
|
31
|
+
|
|
32
|
+
/** The `toast()` imperative (no lifecycle of its own). */
|
|
33
|
+
export declare function useToast(): (message: string, opts?: ToastOpts) => Cleanup;
|
|
34
|
+
|
|
35
|
+
export { applyStoredTheme } from '../behaviors/index.js';
|
|
36
|
+
export { cls, ui, cx } from '../classes/index.js';
|
package/react/index.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ponchia/ui/react — thin React bindings over @ponchia/ui/behaviors.
|
|
3
|
+
*
|
|
4
|
+
* The CSS is the framework; these are *optional* hooks that wrap the SSR-safe
|
|
5
|
+
* vanilla `init*` behaviors in a component lifecycle (run on mount, clean up on
|
|
6
|
+
* unmount). They are deliberately thin adapters — not a component library — per
|
|
7
|
+
* the architecture ADR. `react` is an optional peer dependency.
|
|
8
|
+
*
|
|
9
|
+
* The behaviors delegate from a root (default `document`), so call a hook once
|
|
10
|
+
* near the relevant subtree; pass `{ root: ref.current }` to scope it. The root
|
|
11
|
+
* is captured on mount — keep it stable (a ref), like any effect dependency.
|
|
12
|
+
*
|
|
13
|
+
* import { useDialog, useToast } from '@ponchia/ui/react';
|
|
14
|
+
* function App() {
|
|
15
|
+
* useDialog(); // wires every .ui-modal under document
|
|
16
|
+
* const toast = useToast();
|
|
17
|
+
* return <button onClick={() => toast('Saved', { tone: 'success' })}>Save</button>;
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
import { useEffect } from 'react';
|
|
21
|
+
import {
|
|
22
|
+
applyStoredTheme,
|
|
23
|
+
initThemeToggle,
|
|
24
|
+
dismissible,
|
|
25
|
+
initDisclosure,
|
|
26
|
+
initMenu,
|
|
27
|
+
initFormValidation,
|
|
28
|
+
initCombobox,
|
|
29
|
+
initPopover,
|
|
30
|
+
initTableSort,
|
|
31
|
+
initTabs,
|
|
32
|
+
initDialog,
|
|
33
|
+
initCarousel,
|
|
34
|
+
initDotGlyph,
|
|
35
|
+
toast,
|
|
36
|
+
} from '../behaviors/index.js';
|
|
37
|
+
|
|
38
|
+
/** Run a delegated behavior for the component's lifetime (init on mount, its
|
|
39
|
+
* returned cleanup on unmount). The behavior is run once; `opts` is captured
|
|
40
|
+
* on mount — pass a stable root (a ref) if you scope it. */
|
|
41
|
+
export function useBrontoBehavior(init, opts) {
|
|
42
|
+
useEffect(() => init(opts), []); // eslint-disable-line react-hooks/exhaustive-deps -- delegated once on mount
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const useThemeToggle = (opts) => useBrontoBehavior(initThemeToggle, opts);
|
|
46
|
+
export const useDismissible = (opts) => useBrontoBehavior(dismissible, opts);
|
|
47
|
+
export const useDisclosure = (opts) => useBrontoBehavior(initDisclosure, opts);
|
|
48
|
+
export const useMenu = (opts) => useBrontoBehavior(initMenu, opts);
|
|
49
|
+
export const useFormValidation = (opts) => useBrontoBehavior(initFormValidation, opts);
|
|
50
|
+
export const useCombobox = (opts) => useBrontoBehavior(initCombobox, opts);
|
|
51
|
+
export const usePopover = (opts) => useBrontoBehavior(initPopover, opts);
|
|
52
|
+
export const useTableSort = (opts) => useBrontoBehavior(initTableSort, opts);
|
|
53
|
+
export const useTabs = (opts) => useBrontoBehavior(initTabs, opts);
|
|
54
|
+
export const useDialog = (opts) => useBrontoBehavior(initDialog, opts);
|
|
55
|
+
export const useCarousel = (opts) => useBrontoBehavior(initCarousel, opts);
|
|
56
|
+
export const useDotGlyph = (opts) => useBrontoBehavior(initDotGlyph, opts);
|
|
57
|
+
|
|
58
|
+
/** The `toast()` imperative (no lifecycle of its own). */
|
|
59
|
+
export const useToast = () => toast;
|
|
60
|
+
|
|
61
|
+
// No-flash theme application has to run before paint; do it in an inline head
|
|
62
|
+
// script, not an effect. Re-exported for manual/SSR-bootstrap use.
|
|
63
|
+
export { applyStoredTheme };
|
|
64
|
+
|
|
65
|
+
// Convenience: the framework-agnostic class contract, re-exported so a React
|
|
66
|
+
// consumer needs one import.
|
|
67
|
+
export { cls, ui, cx } from '../classes/index.js';
|
package/solid/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** @ponchia/ui/solid — thin Solid bindings over the SSR-safe behaviors.
|
|
2
|
+
* Optional peer dep `solid-js`. Primitives run a delegated behavior for the
|
|
3
|
+
* component's lifetime; they take the same options as the behavior and return
|
|
4
|
+
* void (the cleanup is wired to dispose). See behaviors/index.d.ts. */
|
|
5
|
+
import type {
|
|
6
|
+
Cleanup,
|
|
7
|
+
DelegateOpts,
|
|
8
|
+
ThemeStorageOpts,
|
|
9
|
+
ToastOpts,
|
|
10
|
+
} from '../behaviors/index.js';
|
|
11
|
+
|
|
12
|
+
/** Run any delegated behavior for the component's lifetime (init on mount,
|
|
13
|
+
* its returned cleanup on dispose). */
|
|
14
|
+
export declare function useBrontoBehavior(
|
|
15
|
+
init: (opts?: DelegateOpts) => Cleanup | void,
|
|
16
|
+
opts?: DelegateOpts,
|
|
17
|
+
): void;
|
|
18
|
+
|
|
19
|
+
export declare function useThemeToggle(opts?: ThemeStorageOpts & DelegateOpts): void;
|
|
20
|
+
export declare function useDismissible(opts?: DelegateOpts): void;
|
|
21
|
+
export declare function useDisclosure(opts?: DelegateOpts): void;
|
|
22
|
+
export declare function useMenu(opts?: DelegateOpts): void;
|
|
23
|
+
export declare function useFormValidation(opts?: DelegateOpts): void;
|
|
24
|
+
export declare function useCombobox(opts?: DelegateOpts): void;
|
|
25
|
+
export declare function usePopover(opts?: DelegateOpts): void;
|
|
26
|
+
export declare function useTableSort(opts?: DelegateOpts): void;
|
|
27
|
+
export declare function useTabs(opts?: DelegateOpts): void;
|
|
28
|
+
export declare function useDialog(opts?: DelegateOpts): void;
|
|
29
|
+
export declare function useCarousel(opts?: DelegateOpts): void;
|
|
30
|
+
export declare function useDotGlyph(opts?: DelegateOpts): void;
|
|
31
|
+
|
|
32
|
+
/** The `toast()` imperative (no lifecycle of its own). */
|
|
33
|
+
export declare function useToast(): (message: string, opts?: ToastOpts) => Cleanup;
|
|
34
|
+
|
|
35
|
+
export { applyStoredTheme } from '../behaviors/index.js';
|
|
36
|
+
export { cls, ui, cx } from '../classes/index.js';
|